blob: aa94123497a18c9b50feec30b8f288e5b65b502b [file] [log] [blame]
/*
* 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.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase;
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.Response;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
import org.apache.chemistry.opencmis.commons.data.ObjectList;
import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.impl.Constants;
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
import org.apache.chemistry.opencmis.commons.spi.NavigationService;
/**
* Navigation Service AtomPub client.
*/
public class NavigationServiceImpl extends AbstractAtomPubService implements NavigationService {
/**
* Constructor.
*/
public NavigationServiceImpl(BindingSession session) {
setSession(session);
}
public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter, String orderBy,
Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
ObjectInFolderListImpl result = new ObjectInFolderListImpl();
// find the link
String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
if (link == null) {
throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_FILTER, filter);
url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
// read and parse
Response resp = read(url);
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 children
if (!feed.getEntries().isEmpty()) {
result.setObjects(new ArrayList<ObjectInFolderData>(feed.getEntries().size()));
for (AtomEntry entry : feed.getEntries()) {
ObjectInFolderDataImpl child = null;
String pathSegment = null;
lockLinks();
try {
// clean up cache
removeLinks(repositoryId, entry.getId());
// walk through the entry
for (AtomElement element : entry.getElements()) {
if (element.getObject() instanceof AtomLink) {
addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
} else if (isStr(NAME_PATH_SEGMENT, element)) {
pathSegment = (String) element.getObject();
} else if (element.getObject() instanceof ObjectData) {
child = new ObjectInFolderDataImpl();
child.setObject((ObjectData) element.getObject());
}
}
} finally {
unlockLinks();
}
if (child != null) {
child.setPathSegment(pathSegment);
result.getObjects().add(child);
}
}
}
return result;
}
public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId, BigInteger depth,
String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
// find the link
String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
if (link == null) {
throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_DEPTH, depth);
url.addParameter(Constants.PARAM_FILTER, filter);
url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
// read and parse
Response resp = read(url);
AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
// process tree
addDescendantsLevel(repositoryId, feed, result);
return result;
}
public ObjectData getFolderParent(String repositoryId, String folderId, String filter, ExtensionsData extension) {
ObjectData result = null;
// find the link
String link = loadLink(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
if (link == null) {
throwLinkException(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_FILTER, filter);
// read
Response resp = read(url);
AtomBase base = parse(resp.getStream(), AtomBase.class);
// get the entry
AtomEntry entry = null;
if (base instanceof AtomFeed) {
AtomFeed feed = (AtomFeed) base;
if (feed.getEntries().isEmpty()) {
throw new CmisRuntimeException("Parent feed is empty!");
}
entry = feed.getEntries().get(0);
} else if (base instanceof AtomEntry) {
entry = (AtomEntry) base;
} else {
throw new CmisRuntimeException("Unexpected document!");
}
lockLinks();
try {
// clean up cache
removeLinks(repositoryId, entry.getId());
// walk through the entry
for (AtomElement element : entry.getElements()) {
if (element.getObject() instanceof AtomLink) {
addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
} else if (element.getObject() instanceof ObjectData) {
result = (ObjectData) element.getObject();
}
}
} finally {
unlockLinks();
}
return result;
}
public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId, BigInteger depth,
String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
// find the link
String link = loadLink(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
if (link == null) {
throwLinkException(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_DEPTH, depth);
url.addParameter(Constants.PARAM_FILTER, filter);
url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
// read and parse
Response resp = read(url);
AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
// process tree
addDescendantsLevel(repositoryId, feed, result);
return result;
}
public List<ObjectParentData> getObjectParents(String repositoryId, String objectId, String filter,
Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
Boolean includeRelativePathSegment, ExtensionsData extension) {
List<ObjectParentData> result = new ArrayList<ObjectParentData>();
// find the link
String link = loadLink(repositoryId, objectId, Constants.REL_UP, Constants.MEDIATYPE_FEED);
if (link == null) {
// root and unfiled objects have no UP link
return result;
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_FILTER, filter);
url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
url.addParameter(Constants.PARAM_RELATIVE_PATH_SEGMENT, includeRelativePathSegment);
// read and parse
Response resp = read(url);
AtomBase base = parse(resp.getStream(), AtomBase.class);
if (base instanceof AtomFeed) {
// it's a feed
AtomFeed feed = (AtomFeed) base;
// walk through the feed
for (AtomEntry entry : feed.getEntries()) {
ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
if (objectParent != null) {
result.add(objectParent);
}
}
} else if (base instanceof AtomEntry) {
// it's an entry
AtomEntry entry = (AtomEntry) base;
ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
if (objectParent != null) {
result.add(objectParent);
}
}
return result;
}
private ObjectParentDataImpl processParentEntry(AtomEntry entry, String repositoryId) {
ObjectParentDataImpl result = null;
String relativePathSegment = null;
lockLinks();
try {
// clean up cache
removeLinks(repositoryId, entry.getId());
// walk through the entry
for (AtomElement element : entry.getElements()) {
if (element.getObject() instanceof AtomLink) {
addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
} else if (element.getObject() instanceof ObjectData) {
result = new ObjectParentDataImpl((ObjectData) element.getObject());
} else if (is(NAME_RELATIVE_PATH_SEGMENT, element)) {
relativePathSegment = (String) element.getObject();
}
}
} finally {
unlockLinks();
}
if (result != null) {
result.setRelativePathSegment(relativePathSegment);
}
return result;
}
public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy,
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_CHECKEDOUT);
if (link == null) {
throw new CmisObjectNotFoundException("Unknown repository or checkedout collection not supported!");
}
UrlBuilder url = new UrlBuilder(link);
url.addParameter(Constants.PARAM_FOLDER_ID, folderId);
url.addParameter(Constants.PARAM_FILTER, filter);
url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
// read and parse
Response resp = read(url);
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 documents
if (!feed.getEntries().isEmpty()) {
result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
for (AtomEntry entry : feed.getEntries()) {
ObjectData child = null;
lockLinks();
try {
// clean up cache
removeLinks(repositoryId, entry.getId());
// walk through the entry
for (AtomElement element : entry.getElements()) {
if (element.getObject() instanceof AtomLink) {
addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
} else if (element.getObject() instanceof ObjectData) {
child = (ObjectData) element.getObject();
}
}
} finally {
unlockLinks();
}
if (child != null) {
result.getObjects().add(child);
}
}
}
return result;
}
// ---- internal ----
/**
* Adds descendants level recursively.
*/
private void addDescendantsLevel(String repositoryId, AtomFeed feed, List<ObjectInFolderContainer> containerList) {
if (feed == null || feed.getEntries().isEmpty()) {
return;
}
// walk through the feed
for (AtomEntry entry : feed.getEntries()) {
ObjectInFolderDataImpl objectInFolder = null;
String pathSegment = null;
List<ObjectInFolderContainer> childContainerList = new ArrayList<ObjectInFolderContainer>();
lockLinks();
try {
// clean up cache
removeLinks(repositoryId, entry.getId());
// walk through the entry
for (AtomElement element : entry.getElements()) {
if (element.getObject() instanceof AtomLink) {
addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
} else if (element.getObject() instanceof ObjectData) {
objectInFolder = new ObjectInFolderDataImpl((ObjectData) element.getObject());
} else if (is(NAME_PATH_SEGMENT, element)) {
pathSegment = (String) element.getObject();
} else if (element.getObject() instanceof AtomFeed) {
addDescendantsLevel(repositoryId, (AtomFeed) element.getObject(), childContainerList);
}
}
} finally {
unlockLinks();
}
if (objectInFolder != null) {
objectInFolder.setPathSegment(pathSegment);
ObjectInFolderContainerImpl childContainer = new ObjectInFolderContainerImpl(objectInFolder);
childContainer.setChildren(childContainerList);
containerList.add(childContainer);
}
}
}
}