/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you 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 org.apache.chemistry.opencmis.client.bindings.spi.atompub; | |
import java.io.OutputStream; | |
import java.math.BigInteger; | |
import java.util.ArrayList; | |
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession; | |
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement; | |
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry; | |
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomFeed; | |
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink; | |
import org.apache.chemistry.opencmis.client.bindings.spi.http.Output; | |
import org.apache.chemistry.opencmis.client.bindings.spi.http.Response; | |
import org.apache.chemistry.opencmis.commons.data.ExtensionsData; | |
import org.apache.chemistry.opencmis.commons.data.ObjectData; | |
import org.apache.chemistry.opencmis.commons.data.ObjectList; | |
import org.apache.chemistry.opencmis.commons.enums.CmisVersion; | |
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; | |
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; | |
import org.apache.chemistry.opencmis.commons.impl.Constants; | |
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder; | |
import org.apache.chemistry.opencmis.commons.impl.XMLConverter; | |
import org.apache.chemistry.opencmis.commons.impl.XMLUtils; | |
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl; | |
import org.apache.chemistry.opencmis.commons.impl.dataobjects.QueryTypeImpl; | |
import org.apache.chemistry.opencmis.commons.spi.DiscoveryService; | |
import org.apache.chemistry.opencmis.commons.spi.ExtendedHolder; | |
import org.apache.chemistry.opencmis.commons.spi.Holder; | |
import org.xmlpull.v1.XmlSerializer; | |
/** | |
* Discovery Service AtomPub client. | |
*/ | |
public class DiscoveryServiceImpl extends AbstractAtomPubService implements DiscoveryService { | |
/** | |
* Constructor. | |
*/ | |
public DiscoveryServiceImpl(BindingSession session) { | |
setSession(session); | |
} | |
public ObjectList getContentChanges(String repositoryId, Holder<String> changeLogToken, Boolean includeProperties, | |
String filter, Boolean includePolicyIds, Boolean includeACL, BigInteger maxItems, ExtensionsData extension) { | |
ObjectListImpl result = new ObjectListImpl(); | |
// find the link | |
String link = null; | |
UrlBuilder url = null; | |
// if the application doesn't know the change log token but the link to | |
// the next Atom feed | |
if (changeLogToken instanceof ExtendedHolder && changeLogToken.getValue() == null) { | |
link = (String) ((ExtendedHolder<String>) changeLogToken).getExtraValue(Constants.REP_REL_CHANGES); | |
if (link != null) { | |
url = new UrlBuilder(link); | |
} | |
} | |
// if the application didn't provide a link to next Atom feed | |
if (link == null) { | |
link = loadRepositoryLink(repositoryId, Constants.REP_REL_CHANGES); | |
if (link != null) { | |
url = new UrlBuilder(link); | |
url.addParameter(Constants.PARAM_CHANGE_LOG_TOKEN, | |
(changeLogToken == null ? null : changeLogToken.getValue())); | |
url.addParameter(Constants.PARAM_PROPERTIES, includeProperties); | |
url.addParameter(Constants.PARAM_FILTER, filter); | |
url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds); | |
url.addParameter(Constants.PARAM_ACL, includeACL); | |
url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems); | |
} | |
} | |
if (link == null) { | |
throw new CmisObjectNotFoundException("Unknown repository or content changes not supported!"); | |
} | |
// read and parse | |
Response resp = read(url); | |
AtomFeed feed = parse(resp.getStream(), AtomFeed.class); | |
String lastChangeLogToken = null; | |
// handle top level | |
String nextLink = null; | |
for (AtomElement element : feed.getElements()) { | |
if (element.getObject() instanceof AtomLink) { | |
if (isNextLink(element)) { | |
result.setHasMoreItems(Boolean.TRUE); | |
nextLink = ((AtomLink) element.getObject()).getHref(); | |
} | |
} else if (isInt(NAME_NUM_ITEMS, element)) { | |
result.setNumItems((BigInteger) element.getObject()); | |
} else if (isStr("changeLogToken", element)) { | |
lastChangeLogToken = (String) element.getObject(); | |
} | |
} | |
// get the changes | |
if (!feed.getEntries().isEmpty()) { | |
result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size())); | |
for (AtomEntry entry : feed.getEntries()) { | |
ObjectData hit = null; | |
// walk through the entry | |
for (AtomElement element : entry.getElements()) { | |
if (element.getObject() instanceof ObjectData) { | |
hit = (ObjectData) element.getObject(); | |
} | |
} | |
if (hit != null) { | |
result.getObjects().add(hit); | |
} | |
} | |
} | |
if (changeLogToken != null) { | |
// the AtomPub binding cannot return a new change log token, | |
// but an OpenCMIS server uses a proprietary tag | |
changeLogToken.setValue(lastChangeLogToken); | |
// but we can provide the link to the next Atom feed | |
if (changeLogToken instanceof ExtendedHolder && nextLink != null) { | |
((ExtendedHolder<String>) changeLogToken).setExtraValue(Constants.REP_REL_CHANGES, nextLink); | |
} | |
} | |
return result; | |
} | |
public ObjectList query(String repositoryId, String statement, Boolean searchAllVersions, | |
Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, | |
BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) { | |
ObjectListImpl result = new ObjectListImpl(); | |
// find the link | |
String link = loadCollection(repositoryId, Constants.COLLECTION_QUERY); | |
if (link == null) { | |
throw new CmisObjectNotFoundException("Unknown repository or query not supported!"); | |
} | |
UrlBuilder url = new UrlBuilder(link); | |
// compile query request | |
final QueryTypeImpl query = new QueryTypeImpl(); | |
query.setStatement(statement); | |
query.setSearchAllVersions(searchAllVersions); | |
query.setIncludeAllowableActions(includeAllowableActions); | |
query.setIncludeRelationships(includeRelationships); | |
query.setRenditionFilter(renditionFilter); | |
query.setMaxItems(maxItems); | |
query.setSkipCount(skipCount); | |
final CmisVersion cmisVersion = getCmisVersion(repositoryId); | |
// post the query and parse results | |
Response resp = post(url, Constants.MEDIATYPE_QUERY, new Output() { | |
public void write(OutputStream out) throws Exception { | |
XmlSerializer writer = XMLUtils.createWriter(out); | |
XMLUtils.startXmlDocument(writer); | |
XMLConverter.writeQuery(writer, cmisVersion, query); | |
XMLUtils.endXmlDocument(writer); | |
} | |
}); | |
AtomFeed feed = parse(resp.getStream(), AtomFeed.class); | |
// handle top level | |
for (AtomElement element : feed.getElements()) { | |
if (element.getObject() instanceof AtomLink) { | |
if (isNextLink(element)) { | |
result.setHasMoreItems(Boolean.TRUE); | |
} | |
} else if (isInt(NAME_NUM_ITEMS, element)) { | |
result.setNumItems((BigInteger) element.getObject()); | |
} | |
} | |
// get the result set | |
if (!feed.getEntries().isEmpty()) { | |
result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size())); | |
for (AtomEntry entry : feed.getEntries()) { | |
ObjectData hit = null; | |
// walk through the entry | |
for (AtomElement element : entry.getElements()) { | |
if (element.getObject() instanceof ObjectData) { | |
hit = (ObjectData) element.getObject(); | |
} | |
} | |
if (hit != null) { | |
result.getObjects().add(hit); | |
} | |
} | |
} | |
return result; | |
} | |
} |