/*
* Copyright 2008 - 2009 Lars Heuer (heuer[at]semagia.com). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.semagia.atomico.server.impl.restlet.resources;
import java.util.List;
import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.representation.Variant;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
import com.semagia.atomico.MediaType;
import com.semagia.atomico.server.IConfiguration;
import com.semagia.atomico.server.dm.ICollectionInfo;
import com.semagia.atomico.server.dm.IFragmentInfo;
import com.semagia.atomico.server.dm.ISnapshotInfo;
import com.semagia.atomico.server.impl.restlet.AtomicoServerApplication;
import com.semagia.atomico.server.impl.restlet.IRestletServerConstants;
import com.semagia.atomico.server.storage.IStorage;
import com.semagia.atomico.server.storage.StorageException;
/**
* Commmon base class for all resources.
* <p>
* This resource provides some convenient functions and provides access to
* a {@link IStorage} instance.
* </p>
*
* @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
* @version $Rev: 66 $ - $Date: 2010-09-06 10:29:07 -0500 (Mon, 06 Sep 2010) $
*/
abstract class AbstractBaseResource extends ServerResource implements
IRestletServerConstants {
/**
* The collection info to operate on.
* Might be <tt>null</tt>.
*/
protected ICollectionInfo _collInfo;
/**
* The storage to operate on.
*/
protected final IStorage _storage;
/**
* Creates a base resource.
*/
protected AbstractBaseResource() {
super();
_storage = getApplication().getStorage();
super.setAnnotated(false);
}
/**
* Initializes the {@link #_collInfo}.
* <p>
* Side effects: If the collection info is null, the resource is marked as
* non-existent and the status is set to 404.
* </p>
*
* @throws ResourceException
*/
protected final void initializeCollectionInfo() throws ResourceException {
initializeCollectionInfo(true);
}
/**
* Initializes the collection information.
*
* @param mustExist Indicates if the collection must exists.
* @throws ResourceException In case of a {@link StorageException} or if
* <tt>mustExists</tt> is <tt>true</tt> and the collection does not
* exist.
*/
protected final void initializeCollectionInfo(boolean mustExist) throws ResourceException {
final String collId = (String) getRequest().getAttributes().get(COLLECTION_ID);
try {
_collInfo = collId == null ? null : _storage.getCollectionInfo(collId);
}
catch (StorageException ex) {
throw new ResourceException(ex);
}
if (mustExist && _collInfo == null) {
throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND);
}
}
/* (non-Javadoc)
* @see org.restlet.resource.ServerResource#isExisting()
*/
@Override
public boolean isExisting() {
return _collInfo != null;
}
/* (non-Javadoc)
* @see org.restlet.Handler#getApplication()
*/
@Override
public AtomicoServerApplication getApplication() {
return (AtomicoServerApplication) super.getApplication();
}
/**
* Returns the time when the resource was modified.
*
* @return The time when this resource was modified.
*/
protected abstract long lastModification();
/**
* Returns the application-specific configuration.
*
* @return The configuration instance.
*/
protected final IConfiguration getConfiguration() {
return getApplication().getConfiguration();
}
/**
* Returns the request URL / IRI as string.
*
* @return The request IRI as string.
*/
protected final String getRequestIRI() {
return getRequest().getResourceRef().toString();
}
protected abstract Iterable<MediaType> getMediaTypes();
/* (non-Javadoc)
* @see org.restlet.resource.ServerResource#getVariants(org.restlet.data.Method)
*/
@Override
public List<Variant> getVariants(Method method) {
if (Method.GET.equals(method)) {
for (MediaType mt: getMediaTypes()) {
super.getVariants().put(method, new ImmutableVariant(MediaTypeUtils.toRestletMediaType(mt)));
}
}
return super.getVariants(method);
}
private static String _getSnapshotsPath() {
return "snapshots";
}
private static String _getFragmentsPath() {
return "fragments";
}
/**
* Returns the root.
*
* @return
*/
private String _getRoot() {
return getRequest().getRootRef().toString();
}
/**
*
*
* @param collId
* @return
*/
public String linkToCollection(String collId) {
return _linkToCollection(collId, new StringBuilder(collId.length()+2)).toString();
}
/**
*
*
* @param collId
* @param buff
* @return
*/
private StringBuilder _linkToCollection(String collId, StringBuilder buff) {
buff.append('/')
.append(collId)
.append('/');
return buff;
}
/**
*
*
* @param collId
* @return
*/
public String linkToSnapshots(String collId) {
return _linkToSubResource(collId, "snapshots");
}
/**
*
*
* @param collId
* @param snapshotId
* @return
*/
public String linkToSnapshot(String collId, String snapshotId) {
final String path = _getSnapshotsPath();
StringBuilder buff = new StringBuilder(collId.length() + path.length() + snapshotId.length() + 4);
_linkToSubResource(collId, path, buff)
.append(snapshotId);
return buff.toString();
}
/**
*
*
* @param collId
* @return
*/
public String linkToFragments(String collId) {
return _linkToSubResource(collId, _getFragmentsPath());
}
/**
*
*
* @param collId
* @param subPath
* @return
*/
private String _linkToSubResource(String collId, String subPath) {
return _linkToSubResource(collId, subPath,
new StringBuilder(collId.length() + subPath.length() + 4)).toString();
}
/**
*
*
* @param collId
* @param subPath
* @param buff
* @return
*/
private StringBuilder _linkToSubResource(String collId, String subPath, StringBuilder buff) {
_linkToCollection(collId, buff)
.append(subPath)
.append('/');
return buff;
}
/**
*
*
* @param collId
* @param fragmentId
* @return
*/
public String linkToFragment(String collId, String fragmentId) {
final String path = _getFragmentsPath();
StringBuilder buff = new StringBuilder(collId.length() + path.length() + fragmentId.length() + 4);
_linkToSubResource(collId, path, buff)
.append(fragmentId);
return buff.toString();
}
/**
* Returns a link to the snapshots feed.
*
* @return The link to the snapshots feed.
* @throws ResourceException If this resource didn't find the collection
* to operate upon.
*/
protected final String linkToSnapshots() throws ResourceException {
if (_collInfo == null) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return _getRoot()
+ linkToSnapshots(_collInfo.getCollectionId());
}
/**
* Returns the link to the fragments feed.
*
* @return The link to the fragments feed.
* @throws ResourceException If this resource didn't find the collection
* to operate upon.
*/
protected final String linkToFragments() throws ResourceException {
if (_collInfo == null) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return _getRoot()
+ linkToFragments(_collInfo.getCollectionId());
}
/**
* Returns the link to the underlying collection.
*
* @return A link to the collection.
* @throws ResourceException If there is no underlying collection.
*/
protected final String linkToCollection() throws ResourceException {
return linkToCollection(_collInfo);
}
/**
* Returns the link to the provided <tt>collectionInfo</tt>.
*
* @param collectionInfo The collection info to generate a link for.
* @return The link to the specified collection.
* @throws ResourceException In case the collection does not exist.
*/
protected final String linkToCollection(ICollectionInfo collectionInfo) throws ResourceException {
if (collectionInfo == null) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return _getRoot()
+ linkToCollection(collectionInfo.getCollectionId());
}
/**
*
*
* @param collInfo
* @param info
* @return
* @throws ResourceException
*/
protected final String linkTo(final ISnapshotInfo info) throws ResourceException {
if (_collInfo == null) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return _getRoot()
+ linkToSnapshot(
_collInfo.getCollectionId(), info.getSnapshotId());
}
/**
*
*
* @param collInfo
* @param info
* @return
* @throws ResourceException
*/
protected final String linkTo(final IFragmentInfo info) throws ResourceException {
if (_collInfo == null) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return _getRoot()
+ linkToFragment(
_collInfo.getCollectionId(), info.getFragmentId());
}
}