/**
* Copyright (C) 2010 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xcmis.restatom.collections;
import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.model.Content;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.model.Person;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.ResponseContext;
import org.apache.abdera.protocol.server.TargetType;
import org.apache.abdera.protocol.server.context.AbstractResponseContext;
import org.apache.abdera.protocol.server.context.BaseResponseContext;
import org.apache.abdera.protocol.server.context.EmptyResponseContext;
import org.apache.abdera.protocol.server.context.ResponseContextException;
import org.apache.abdera.protocol.server.impl.AbstractEntityCollectionAdapter;
import org.xcmis.restatom.AtomCMIS;
import org.xcmis.restatom.ProviderImpl;
import org.xcmis.spi.Connection;
import org.xcmis.spi.utils.Logger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:andrey.parfonov@exoplatform.com">Andrey Parfonov</a>
* @version $Id: AbstractCmisCollection.java 2634 2009-08-12 06:26:41Z andrew00x
* $
*/
public abstract class AbstractCmisCollection<T> extends AbstractEntityCollectionAdapter<T>
{
/** The logger. */
private static final Logger LOG = Logger.getLogger(AbstractCmisCollection.class);
/** The Constant ANONYMOUS. */
protected static final String ANONYMOUS = "anonymous";
/** The Constant SYSTEM. */
protected static final String SYSTEM = "system";
/*protected*/private final Connection connection;
public AbstractCmisCollection(Connection connection)
{
this.connection = connection;
}
/**
* {@inheritDoc}
*/
public void deleteEntry(String resourceName, RequestContext request) throws ResponseContextException
{
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Object getContent(T entry, RequestContext request) throws ResponseContextException
{
return null;
}
/**
* {@inheritDoc}
*/
public ResponseContext postEntry(RequestContext request)
{
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public T postEntry(String title, IRI id, String summary, Date updated, List<Person> authors, Content content,
RequestContext request) throws ResponseContextException
{
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void putEntry(T entry, String title, Date updated, List<Person> authors, String summary, Content content,
RequestContext request) throws ResponseContextException
{
throw new UnsupportedOperationException();
}
/**
* @param id id
* @param feed feed to which are added links
* @param atomdocType type of collections. See {@link ProviderImpl}.
* @param maxItems max items in each response
* @param skipCount number of skipped results from the begin of set
* @param total total number items in result set. If total number is unknown
* then this parameter must be set as -1.
* @param hasMore true if has more items in result set false otherwise
* @param request request context
*/
protected void addPageLinks(String id, Feed feed, String atomdocType, int maxItems, int skipCount, int total,
boolean hasMore, RequestContext request)
{
Map<String, String> params = new HashMap<String, String>();
params.put("repoid", getRepositoryId(request));
params.put("atomdoctype", atomdocType);
params.put("id", id);
// First link
params.put(AtomCMIS.PARAM_SKIP_COUNT, "0");
params.put(AtomCMIS.PARAM_MAX_ITEMS, //
Integer.toString((skipCount == 0) ? maxItems //
: (maxItems < skipCount ? maxItems : skipCount) /* If started not from first page. */));
feed.addLink(request.absoluteUrlFor("feed", params), AtomCMIS.LINK_FIRST, AtomCMIS.MEDIATYPE_ATOM_FEED, null,
null, -1);
// Previous link.
if (skipCount > 0)
{
params.put(AtomCMIS.PARAM_MAX_ITEMS, Integer.toString(maxItems < skipCount ? maxItems : skipCount));
params.put(AtomCMIS.PARAM_SKIP_COUNT, Integer.toString(maxItems < skipCount ? skipCount - maxItems : 0));
feed.addLink(request.absoluteUrlFor("feed", params), AtomCMIS.LINK_PREVIOUS, AtomCMIS.MEDIATYPE_ATOM_FEED,
null, null, -1);
}
if (hasMore)
{
// Next link.
params.put(AtomCMIS.PARAM_SKIP_COUNT, Integer.toString(skipCount + maxItems));
params.put(AtomCMIS.PARAM_MAX_ITEMS, Integer.toString(maxItems));
// If has more items then provide next link.
feed.addLink(request.absoluteUrlFor("feed", params), AtomCMIS.LINK_NEXT, AtomCMIS.MEDIATYPE_ATOM_FEED, null,
null, -1);
// Total link.
if (total > 0)
{
// If total number result in set is unknown then unable to determine last page link.
int pages = (total - skipCount) / maxItems;
int rem = (total - skipCount) % maxItems;
if (rem == 0)
{
skipCount = total - maxItems;
}
else if (pages != 0)
{
skipCount = skipCount + pages * maxItems;
}
params.put(AtomCMIS.PARAM_SKIP_COUNT, Integer.toString(skipCount));
params.put(AtomCMIS.PARAM_MAX_ITEMS, Integer.toString(maxItems));
feed.addLink(request.absoluteUrlFor("feed", params), AtomCMIS.LINK_LAST, AtomCMIS.MEDIATYPE_ATOM_FEED,
null, null, -1);
}
}
}
/**
* {@inheritDoc}
*/
protected ResponseContext buildCreateEntryResponse(String link, Entry entry)
{
Document<Entry> doc = entry.getDocument();
ResponseContext rc = new BaseResponseContext<Document<Entry>>(doc);
rc.setLocation(link);
rc.setContentLocation(rc.getLocation().toString());
// rc.setEntityTag(ProviderHelper.calculateEntityTag(entry));
rc.setStatus(201);
return rc;
}
/**
* {@inheritDoc}
*/
@Override
protected ResponseContext buildGetEntryResponse(RequestContext request, Entry entry) throws ResponseContextException
{
// The same as in super class but without ETag.
Document<Entry> doc = entry.getDocument();
ResponseContext rc = new BaseResponseContext<Document<Entry>>(doc);
// rc.setEntityTag(ProviderHelper.calculateEntityTag(entry));
return rc;
}
/**
* {@inheritDoc}
*/
@Override
protected ResponseContext buildGetFeedResponse(Feed feed)
{
// The same as in super class but without ETag.
Document<Feed> document = feed.getDocument();
AbstractResponseContext rc = new BaseResponseContext<Document<Feed>>(document);
// rc.setEntityTag(calculateEntityTag(document.getRoot()));
return rc;
}
/**
* Creates the error response.
*
* @param msg the msg
* @param status the status
*
* @return the response context
*/
protected ResponseContext createErrorResponse(String msg, int status)
{
LOG.error(msg);
return new EmptyResponseContext(status, msg);
}
/**
* Creates the error response.
*
* @param t the t
* @param status the status
*
* @return the response context
*/
protected ResponseContext createErrorResponse(Throwable t, int status)
{
LOG.error(t.getMessage(), t);
return new EmptyResponseContext(status, t.getMessage());
}
/**
* Create link to object type description.
*
* @param id object type id
* @param request request context
* @return link to AtomPub Document that describes object type
*/
protected String getObjectTypeLink(String id, RequestContext request)
{
Map<String, String> params = new HashMap<String, String>();
params.put("repoid", getRepositoryId(request));
params.put("atomdoctype", "typebyid");
params.put("id", id);
String type = request.absoluteUrlFor(TargetType.ENTRY, params);
return type;
}
/**
* Get id of CMIS repository.
*
* @param request RequestContext
* @return repositoryId string
*/
protected String getRepositoryId(RequestContext request)
{
String id = request.getTarget().getParameter("repoid").replace(" ", "%20");
return id;
}
/**
* Create link to AtomPub Service Document contains the set of repositories
* that are available.
*
* @param request the request context
* @return link to AtomPub Service Document
*/
protected String getServiceLink(RequestContext request)
{
Map<String, String> p = new HashMap<String, String>();
p.put("repoid", getRepositoryId(request));
String service = request.absoluteUrlFor(TargetType.SERVICE, p);
return service;
}
/**
* To get Connection for provided repository Id within request.
*
* @param request the request context
* @return the Connection to CMIS storage
*/
protected Connection getConnection(RequestContext request)
{
return connection;
//return CmisRegistry.getInstance().getConnection(getRepositoryId(request));
}
protected boolean getBooleanParameter(RequestContext request, String name, boolean defaultValue)
{
String param = request.getParameter(name);
if (param != null && param.length() > 0)
{
return Boolean.parseBoolean(param);
}
else
{
return defaultValue;
}
}
protected Integer getIntegerParameter(RequestContext request, String name, Integer defaultValue)
throws ResponseContextException
{
Integer result;
String param = request.getParameter(name);
if (param != null && param.length() > 0)
{
try
{
result = new Integer(param);
}
catch (NumberFormatException nfe)
{
String msg = "Invalid parameter for name '" + name + "' with value: '" + name + "'";
throw new ResponseContextException(msg, 400);
}
}
else
{
result = defaultValue;
}
return result;
}
}