You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2015/05/23 22:48:21 UTC

svn commit: r1681380 [1/2] - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache...

Author: fmui
Date: Sat May 23 20:48:20 2015
New Revision: 1681380

URL: http://svn.apache.org/r1681380
Log:
CMIS-913: added API for asynchronous operations and a Java SE implementation and TCK tests

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSession.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSessionFactory.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractAsyncSession.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractExecutorServiceAsyncSession.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AsyncSessionFactoryImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/ThreadPoolExecutorAsyncSession.java
    chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/AsyncCreateAndDeleteDocumentTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/AsyncCreateAndDeleteFolderTest.java
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/FolderImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/impl/AbstractCmisTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CRUDTestGroup.java

Added: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSession.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSession.java?rev=1681380&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSession.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSession.java Sat May 23 20:48:20 2015
@@ -0,0 +1,670 @@
+/*
+ * 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.api;
+
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import org.apache.chemistry.opencmis.commons.data.Ace;
+import org.apache.chemistry.opencmis.commons.data.Acl;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
+import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
+
+/**
+ * This interface provides
+ */
+public interface AsyncSession {
+
+    /**
+     * Returns the session object.
+     * 
+     * @return the session object, not {@code null}
+     */
+    Session getSession();
+
+    // --- types ---
+
+    /**
+     * Gets the definition of a type.
+     * 
+     * @param typeId
+     *            the ID of the type
+     * 
+     * @return the type definition
+     * 
+     * @throws CmisObjectNotFoundException
+     *             if a type with the given type ID doesn't exist
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectType> getTypeDefinition(String typeId);
+
+    /**
+     * Creates a new type.
+     * 
+     * @param type
+     *            the type definition
+     * 
+     * @return the new type definition
+     * 
+     * @cmis 1.1
+     */
+    Future<ObjectType> createType(TypeDefinition type);
+
+    /**
+     * Updates an existing type.
+     * 
+     * @param type
+     *            the type definition updates
+     * 
+     * @return the updated type definition
+     * 
+     * @cmis 1.1
+     */
+    Future<ObjectType> updateType(TypeDefinition type);
+
+    /**
+     * Deletes a type.
+     * 
+     * @param typeId
+     *            the ID of the type to delete
+     * 
+     * @cmis 1.1
+     */
+    Future<?> deleteType(String typeId);
+
+    // --- objects ---
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the cache is turned off per default {@link OperationContext}, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param objectId
+     *            the object ID
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObject(ObjectId objectId);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the given {@link OperationContext} has caching turned off, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param objectId
+     *            the object ID
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObject(ObjectId objectId, OperationContext context);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the cache is turned off per default {@link OperationContext}, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param objectId
+     *            the object ID
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObject(String objectId);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the given {@link OperationContext} has caching turned off, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param objectId
+     *            the object ID
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObject(String objectId, OperationContext context);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the cache is turned off per default {@link OperationContext}, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param path
+     *            the object path
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObjectByPath(String path);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the given {@link OperationContext} has caching turned off, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param path
+     *            the object path
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObjectByPath(String path, OperationContext context);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the cache is turned off per default {@link OperationContext}, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param parentPath
+     *            the path of the parent folder
+     * @param name
+     *            the (path segment) name of the object in the folder
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObjectByPath(String parentPath, String name);
+
+    /**
+     * Returns a CMIS object from the session cache. If the object is not in the
+     * cache or the given {@link OperationContext} has caching turned off, it
+     * will load the object from the repository and puts it into the cache.
+     * <p>
+     * This method might return a stale object if the object has been found in
+     * the cache and has been changed in or removed from the repository. Use
+     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
+     * update the object if necessary.
+     * 
+     * @param parentPath
+     *            the path of the parent folder
+     * @param name
+     *            the (path segment) name of the object in the folder
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the requested object
+     * 
+     * @cmis 1.0
+     */
+    Future<CmisObject> getObjectByPath(String parentPath, String name, OperationContext context);
+
+    /**
+     * Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(ObjectId objectId);
+
+    /**
+     * Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(ObjectId objectId, OperationContext context);
+
+    /**
+     * Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * @param major
+     *            if {@code true} the latest major version will be returned,
+     *            otherwise the very last version will be returned
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(ObjectId objectId, boolean major, OperationContext context);
+
+    /**
+     * /** Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(String objectId);
+
+    /**
+     * Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(String objectId, OperationContext context);
+
+    /**
+     * Returns the latest version in a version series.
+     * 
+     * @param objectId
+     *            the document ID of an arbitrary version in the version series
+     * @param major
+     *            if {@code true} the latest major version will be returned,
+     *            otherwise the very last version will be returned
+     * @param context
+     *            the {@link OperationContext} to use
+     * 
+     * @return the latest document version
+     * 
+     * @cmis 1.0
+     */
+    Future<Document> getLatestDocumentVersion(String objectId, boolean major, OperationContext context);
+
+    // --- create ---
+
+    /**
+     * Creates a new document.
+     * 
+     * The stream in {@code contentStream} is consumed but not closed by this
+     * method.
+     * 
+     * @return the object ID of the new document
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
+            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces);
+
+    /**
+     * Creates a new document.
+     * 
+     * The stream in {@code contentStream} is consumed but not closed by this
+     * method.
+     * 
+     * @return the object ID of the new document
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
+            VersioningState versioningState);
+
+    /**
+     * Creates a new document from a source document.
+     * 
+     * @return the object ID of the new document
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
+            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces);
+
+    /**
+     * Creates a new document from a source document.
+     * 
+     * @return the object ID of the new document
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
+            VersioningState versioningState);
+
+    /**
+     * Creates a new folder.
+     * 
+     * @return the object ID of the new folder
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createFolder(Map<String, ?> properties, ObjectId folderId, List<Policy> policies,
+            List<Ace> addAces, List<Ace> removeAces);
+
+    /**
+     * Creates a new folder.
+     * 
+     * @return the object ID of the new folder
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createFolder(Map<String, ?> properties, ObjectId folderId);
+
+    /**
+     * Creates a new policy.
+     * 
+     * @return the object ID of the new policy
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createPolicy(Map<String, ?> properties, ObjectId folderId, List<Policy> policies,
+            List<Ace> addAces, List<Ace> removeAces);
+
+    /**
+     * Creates a new policy.
+     * 
+     * @return the object ID of the new policy
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createPolicy(Map<String, ?> properties, ObjectId folderId);
+
+    /**
+     * Creates a new item.
+     * 
+     * @return the object ID of the new policy
+     * 
+     * @cmis 1.1
+     */
+    Future<ObjectId> createItem(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces);
+
+    /**
+     * Creates a new item.
+     * 
+     * @return the object ID of the new item
+     * 
+     * @cmis 1.1
+     */
+    Future<ObjectId> createItem(Map<String, ?> properties, ObjectId folderId);
+
+    /**
+     * Creates a new relationship.
+     * 
+     * @return the object ID of the new relationship
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createRelationship(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces);
+
+    /**
+     * Creates a new relationship.
+     * 
+     * @return the object ID of the new relationship
+     * 
+     * @cmis 1.0
+     */
+    Future<ObjectId> createRelationship(Map<String, ?> properties);
+
+    // --- content ---
+
+    /**
+     * Retrieves the content stream of a document.
+     * 
+     * @param docId
+     *            the ID of the document
+     * @param streamId
+     *            the stream ID
+     * @param offset
+     *            the offset of the stream or {@code null} to read the stream
+     *            from the beginning
+     * @param length
+     *            the maximum length of the stream or {@code null} to read to
+     *            the end of the stream
+     * 
+     * @return the content stream or {@code null} if the document has no content
+     *         stream
+     * 
+     * @cmis 1.0
+     */
+    Future<ContentStream> getContentStream(ObjectId docId, String streamId, BigInteger offset, BigInteger length);
+
+    /**
+     * Retrieves the main content stream of a document.
+     * 
+     * @param docId
+     *            the ID of the document
+     * 
+     * @return the content stream or {@code null} if the document has no content
+     *         stream
+     * 
+     * @cmis 1.0
+     */
+    Future<ContentStream> getContentStream(ObjectId docId);
+
+    /**
+     * Reads the document content and writes it to an output stream.
+     * 
+     * The output stream is not closed.
+     * 
+     * @param docId
+     *            the ID of the document
+     * @param streamId
+     *            the stream ID
+     * @param offset
+     *            the offset of the stream or {@code null} to read the stream
+     *            from the beginning
+     * @param length
+     *            the maximum length of the stream or {@code null} to read to
+     *            the end of the stream
+     * 
+     * @return the content stream object (the input stream is closed) or
+     *         {@code null} if the document has no content stream
+     * 
+     * @cmis 1.0
+     */
+    Future<ContentStream> storeContentStream(ObjectId docId, String streamId, BigInteger offset, BigInteger length,
+            OutputStream target);
+
+    /**
+     * Reads the document content and writes it to an output stream.
+     * 
+     * The output stream is not closed.
+     * 
+     * @param docId
+     *            the ID of the document
+     * 
+     * @return the content stream object (the input stream is closed) or
+     *         {@code null} if the document has no content stream
+     * 
+     * @cmis 1.0
+     */
+    Future<ContentStream> storeContentStream(ObjectId docId, OutputStream target);
+
+    // --- delete ---
+
+    /**
+     * Deletes an object.
+     * 
+     * @param objectId
+     *            the ID of the object
+     * @param allVersions
+     *            if this object is a document this parameter defines if only
+     *            this version or all versions should be deleted
+     * 
+     * @cmis 1.0
+     */
+    Future<?> delete(ObjectId objectId, boolean allVersions);
+
+    /**
+     * Deletes an object and, if it is a document, all versions in the version
+     * series.
+     * 
+     * @param objectId
+     *            the ID of the object
+     * 
+     * @cmis 1.0
+     */
+    Future<?> delete(ObjectId objectId);
+
+    /**
+     * Deletes a folder and all subfolders.
+     * 
+     * @param folderId
+     *            the ID of the folder
+     * @param allVersions
+     *            if this object is a document this parameter defines if only
+     *            this version or all versions should be deleted
+     * @param unfile
+     *            defines how objects should be unfiled
+     * @param continueOnFailure
+     *            if {@code true} the repository tries to delete as many objects
+     *            as possible; if {@code false} the repository stops at the
+     *            first object that could not be deleted
+     * 
+     * @return a list of object IDs which failed to be deleted
+     * 
+     * @cmis 1.0
+     */
+    Future<List<String>> deleteTree(ObjectId folderId, boolean allVersions, UnfileObject unfile,
+            boolean continueOnFailure);
+
+    // --- ACL ---
+
+    /**
+     * Applies ACL changes to an object and dependent objects.
+     * 
+     * Only direct ACEs can be added and removed.
+     * 
+     * @param objectId
+     *            the ID the object
+     * @param addAces
+     *            list of ACEs to be added or {@code null} if no ACEs should be
+     *            added
+     * @param removeAces
+     *            list of ACEs to be removed or {@code null} if no ACEs should
+     *            be removed
+     * @param aclPropagation
+     *            value that defines the propagation of the ACE changes;
+     *            {@code null} is equal to
+     *            {@link AclPropagation#REPOSITORYDETERMINED}
+     * 
+     * @return the new ACL of the object
+     * 
+     * @cmis 1.0
+     */
+    Future<Acl> applyAcl(ObjectId objectId, List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation);
+
+    /**
+     * Removes the direct ACEs of an object and sets the provided ACEs.
+     * 
+     * The changes are local to the given object and are not propagated to
+     * dependent objects.
+     * 
+     * @param objectId
+     *            the ID the object
+     * @param aces
+     *            list of ACEs to be set
+     * 
+     * @return the new ACL of the object
+     * 
+     * @cmis 1.0
+     */
+    Future<Acl> setAcl(ObjectId objectId, List<Ace> aces);
+
+    // --- policy ---
+
+    /**
+     * Applies a set of policies to an object.
+     * 
+     * This operation is not atomic. If it fails some policies might already be
+     * applied.
+     * 
+     * @param objectId
+     *            the ID the object
+     * @param policyIds
+     *            the IDs of the policies to be applied
+     * 
+     * @cmis 1.0
+     */
+    Future<?> applyPolicy(ObjectId objectId, ObjectId... policyIds);
+
+    /**
+     * Removes a set of policies from an object.
+     * 
+     * This operation is not atomic. If it fails some policies might already be
+     * removed.
+     * 
+     * @param objectId
+     *            the ID the object
+     * @param policyIds
+     *            the IDs of the policies to be removed
+     * 
+     * @cmis 1.0
+     */
+    Future<?> removePolicy(ObjectId objectId, ObjectId... policyIds);
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSessionFactory.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSessionFactory.java?rev=1681380&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSessionFactory.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/AsyncSessionFactory.java Sat May 23 20:48:20 2015
@@ -0,0 +1,52 @@
+/*
+ * 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.api;
+
+/**
+ * Factory for asynchronous sessions.
+ */
+public interface AsyncSessionFactory {
+
+    /**
+     * Creates a {@link AsyncSession} session object.
+     * 
+     * @param session
+     *            the session, not {@code null}
+     * 
+     * @return a new {@link AsyncSession} session object
+     * 
+     * @see Session
+     */
+    AsyncSession createAsyncSession(Session session);
+
+    /**
+     * Creates a {@link AsyncSession} session object.
+     * 
+     * @param session
+     *            the session, not {@code null}
+     * @param maxParallelRequests
+     *            the maximum number of parallel requests (best-effort of the
+     *            implementation)
+     * 
+     * @return a new {@link AsyncSession} session object
+     * 
+     * @see Session
+     */
+    AsyncSession createAsyncSession(Session session, int maxParallelRequests);
+}

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java?rev=1681380&r1=1681379&r2=1681380&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java Sat May 23 20:48:20 2015
@@ -35,6 +35,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
+import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
@@ -1043,6 +1044,27 @@ public interface Session extends Seriali
     void delete(ObjectId objectId, boolean allVersions);
 
     /**
+     * Deletes a folder and all subfolders.
+     * 
+     * @param folderId
+     *            the ID of the folder
+     * @param allVersions
+     *            if this object is a document this parameter defines if only
+     *            this version or all versions should be deleted
+     * @param unfile
+     *            defines how objects should be unfiled
+     * @param continueOnFailure
+     *            if {@code true} the repository tries to delete as many objects
+     *            as possible; if {@code false} the repository stops at the
+     *            first object that could not be deleted
+     * 
+     * @return a list of object IDs which failed to be deleted
+     * 
+     * @cmis 1.0
+     */
+    List<String> deleteTree(ObjectId folderId, boolean allVersions, UnfileObject unfile, boolean continueOnFailure);
+
+    /**
      * Retrieves the main content stream of a document.
      * 
      * @param docId

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/FolderImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/FolderImpl.java?rev=1681380&r1=1681379&r2=1681380&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/FolderImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/FolderImpl.java Sat May 23 20:48:20 2015
@@ -44,7 +44,6 @@ import org.apache.chemistry.opencmis.cli
 import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.data.Ace;
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
-import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
@@ -170,17 +169,7 @@ public class FolderImpl extends Abstract
     }
 
     public List<String> deleteTree(boolean allVersions, UnfileObject unfile, boolean continueOnFailure) {
-        String repositoryId = getRepositoryId();
-        String objectId = getObjectId();
-
-        FailedToDeleteData failed = getBinding().getObjectService().deleteTree(repositoryId, objectId, allVersions,
-                unfile, continueOnFailure, null);
-
-        if (failed == null || isNullOrEmpty(failed.getIds())) {
-            getSession().removeObjectFromCache(this);
-        }
-
-        return (failed != null ? failed.getIds() : null);
+        return getSession().deleteTree(this, allVersions, unfile, continueOnFailure);
     }
 
     public String getParentId() {

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java?rev=1681380&r1=1681379&r2=1681380&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java Sat May 23 20:48:20 2015
@@ -65,6 +65,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.data.Acl;
 import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken;
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
 import org.apache.chemistry.opencmis.commons.data.ObjectList;
 import org.apache.chemistry.opencmis.commons.data.PropertyData;
@@ -78,6 +79,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
+import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
 import org.apache.chemistry.opencmis.commons.enums.Updatability;
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
@@ -268,6 +270,7 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public void clear() {
         lock.writeLock().lock();
         try {
@@ -284,19 +287,20 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public ObjectFactory getObjectFactory() {
         assert objectFactory != null;
         return objectFactory;
     }
 
+    @Override
     public ItemIterable<Document> getCheckedOutDocs() {
         return getCheckedOutDocs(getDefaultContext());
     }
 
+    @Override
     public ItemIterable<Document> getCheckedOutDocs(OperationContext context) {
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         final NavigationService navigationService = getBinding().getNavigationService();
         final ObjectFactory of = getObjectFactory();
@@ -333,15 +337,15 @@ public class SessionImpl implements Sess
         });
     }
 
+    @Override
     public ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems) {
         return getContentChanges(changeLogToken, includeProperties, maxNumItems, getDefaultContext());
     }
 
+    @Override
     public ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems,
             OperationContext context) {
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         Holder<String> changeLogTokenHolder = new Holder<String>(changeLogToken);
         ObjectList objectList = null;
@@ -358,15 +362,15 @@ public class SessionImpl implements Sess
         return objectFactory.convertChangeEvents(changeLogTokenHolder.getValue(), objectList);
     }
 
+    @Override
     public ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, final boolean includeProperties) {
         return getContentChanges(changeLogToken, includeProperties, getDefaultContext());
     }
 
+    @Override
     public ItemIterable<ChangeEvent> getContentChanges(final String changeLogToken, final boolean includeProperties,
             OperationContext context) {
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         final DiscoveryService discoveryService = getBinding().getDiscoveryService();
         final ObjectFactory of = getObjectFactory();
@@ -442,6 +446,7 @@ public class SessionImpl implements Sess
         return getBinding().getRepositoryService().getRepositoryInfo(getRepositoryId(), null).getLatestChangeLogToken();
     }
 
+    @Override
     public OperationContext getDefaultContext() {
         lock.readLock().lock();
         try {
@@ -451,6 +456,7 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public void setDefaultContext(OperationContext context) {
         lock.writeLock().lock();
         try {
@@ -460,6 +466,7 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public OperationContext createOperationContext(Set<String> filter, boolean includeAcls,
             boolean includeAllowableActions, boolean includePolicies, IncludeRelationships includeRelationships,
             Set<String> renditionFilter, boolean includePathSegments, String orderBy, boolean cacheEnabled,
@@ -469,10 +476,12 @@ public class SessionImpl implements Sess
                 maxItemsPerPage);
     }
 
+    @Override
     public OperationContext createOperationContext() {
         return OperationContextUtils.createOperationContext();
     }
 
+    @Override
     public ObjectId createObjectId(String id) {
         return new ObjectIdImpl(id);
     }
@@ -481,29 +490,26 @@ public class SessionImpl implements Sess
         return locale;
     }
 
+    @Override
     public CmisObject getObject(ObjectId objectId) {
         return getObject(objectId, getDefaultContext());
     }
 
+    @Override
     public CmisObject getObject(ObjectId objectId, OperationContext context) {
-        if (objectId == null || objectId.getId() == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-
+        checkObjectId(objectId);
         return getObject(objectId.getId(), context);
     }
 
+    @Override
     public CmisObject getObject(String objectId) {
         return getObject(objectId, getDefaultContext());
     }
 
+    @Override
     public CmisObject getObject(String objectId, OperationContext context) {
-        if (objectId == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkObjectId(objectId);
+        checkContext(context);
 
         CmisObject result = null;
 
@@ -530,17 +536,17 @@ public class SessionImpl implements Sess
         return result;
     }
 
+    @Override
     public CmisObject getObjectByPath(String path) {
         return getObjectByPath(path, getDefaultContext());
     }
 
+    @Override
     public CmisObject getObjectByPath(String path, OperationContext context) {
         if (path == null) {
             throw new IllegalArgumentException("Path must be set!");
         }
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         CmisObject result = null;
 
@@ -567,10 +573,12 @@ public class SessionImpl implements Sess
         return result;
     }
 
+    @Override
     public CmisObject getObjectByPath(String parentPath, String name) {
         return getObjectByPath(parentPath, name, getDefaultContext());
     }
 
+    @Override
     public CmisObject getObjectByPath(String parentPath, String name, OperationContext context) {
         if (parentPath == null || parentPath.length() < 1) {
             throw new IllegalArgumentException("Parent path must be set!");
@@ -592,46 +600,38 @@ public class SessionImpl implements Sess
         return getObjectByPath(path.toString(), context);
     }
 
+    @Override
     public Document getLatestDocumentVersion(ObjectId objectId) {
         return getLatestDocumentVersion(objectId, false, getDefaultContext());
     }
 
+    @Override
     public Document getLatestDocumentVersion(String objectId, OperationContext context) {
-        if (objectId == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-
+        checkDocumentId(objectId);
         return getLatestDocumentVersion(createObjectId(objectId), false, context);
     }
 
+    @Override
     public Document getLatestDocumentVersion(String objectId, boolean major, OperationContext context) {
-        if (objectId == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-
+        checkDocumentId(objectId);
         return getLatestDocumentVersion(createObjectId(objectId), major, context);
     }
 
+    @Override
     public Document getLatestDocumentVersion(String objectId) {
-        if (objectId == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-
+        checkDocumentId(objectId);
         return getLatestDocumentVersion(createObjectId(objectId), false, getDefaultContext());
     }
 
+    @Override
     public Document getLatestDocumentVersion(ObjectId objectId, OperationContext context) {
         return getLatestDocumentVersion(objectId, false, context);
     }
 
+    @Override
     public Document getLatestDocumentVersion(ObjectId objectId, boolean major, OperationContext context) {
-        if (objectId == null || objectId.getId() == null) {
-            throw new IllegalArgumentException("Object ID must be set!");
-        }
-
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkDocumentId(objectId);
+        checkContext(context);
 
         CmisObject result = null;
 
@@ -704,18 +704,18 @@ public class SessionImpl implements Sess
         return (Document) result;
     }
 
+    @Override
     public void removeObjectFromCache(ObjectId objectId) {
-        if (objectId == null || objectId.getId() == null) {
-            return;
-        }
-
+        checkObjectId(objectId);
         removeObjectFromCache(objectId.getId());
     }
 
+    @Override
     public void removeObjectFromCache(String objectId) {
         cache.remove(objectId);
     }
 
+    @Override
     public RepositoryInfo getRepositoryInfo() {
         lock.readLock().lock();
         try {
@@ -725,10 +725,12 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public Folder getRootFolder() {
         return getRootFolder(getDefaultContext());
     }
 
+    @Override
     public Folder getRootFolder(OperationContext context) {
         String rootFolderId = getRepositoryInfo().getRootFolderId();
 
@@ -740,6 +742,7 @@ public class SessionImpl implements Sess
         return (Folder) rootFolder;
     }
 
+    @Override
     public ItemIterable<ObjectType> getTypeChildren(final String typeId, final boolean includePropertyDefinitions) {
         final RepositoryService repositoryService = getBinding().getRepositoryService();
 
@@ -766,6 +769,7 @@ public class SessionImpl implements Sess
         });
     }
 
+    @Override
     public ObjectType getTypeDefinition(String typeId) {
         TypeDefinition typeDefinition = getBinding().getRepositoryService().getTypeDefinition(getRepositoryId(),
                 typeId, null);
@@ -773,6 +777,7 @@ public class SessionImpl implements Sess
         return convertAndCacheTypeDefinition(typeDefinition, true);
     }
 
+    @Override
     public ObjectType getTypeDefinition(String typeId, boolean useCache) {
         RepositoryService service = getBinding().getRepositoryService();
         if (!(service instanceof ExtendedRepositoryService)) {
@@ -786,6 +791,7 @@ public class SessionImpl implements Sess
         return convertAndCacheTypeDefinition(typeDefinition, useCache);
     }
 
+    @Override
     public List<Tree<ObjectType>> getTypeDescendants(String typeId, int depth, boolean includePropertyDefinitions) {
         List<TypeDefinitionContainer> descendants = getBinding().getRepositoryService().getTypeDescendants(
                 getRepositoryId(), typeId, BigInteger.valueOf(depth), includePropertyDefinitions, null);
@@ -882,19 +888,17 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public ObjectType createType(TypeDefinition type) {
-        if (repositoryInfo.getCmisVersion() == CmisVersion.CMIS_1_0) {
-            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
-        }
+        checkCmisVersion();
 
         TypeDefinition newType = getBinding().getRepositoryService().createType(getRepositoryId(), type, null);
         return convertTypeDefinition(newType);
     }
 
+    @Override
     public ObjectType updateType(TypeDefinition type) {
-        if (repositoryInfo.getCmisVersion() == CmisVersion.CMIS_1_0) {
-            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
-        }
+        checkCmisVersion();
 
         TypeDefinition updatedType = getBinding().getRepositoryService().updateType(getRepositoryId(), type, null);
 
@@ -903,24 +907,23 @@ public class SessionImpl implements Sess
         return convertTypeDefinition(updatedType);
     }
 
+    @Override
     public void deleteType(String typeId) {
-        if (repositoryInfo.getCmisVersion() == CmisVersion.CMIS_1_0) {
-            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
-        }
+        checkCmisVersion();
 
         getBinding().getRepositoryService().deleteType(getRepositoryId(), typeId, null);
         removeFromObjectTypeCache(typeId);
     }
 
+    @Override
     public ItemIterable<QueryResult> query(final String statement, final boolean searchAllVersions) {
         return query(statement, searchAllVersions, getDefaultContext());
     }
 
+    @Override
     public ItemIterable<QueryResult> query(final String statement, final boolean searchAllVersions,
             OperationContext context) {
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         final DiscoveryService discoveryService = getBinding().getDiscoveryService();
         final ObjectFactory of = getObjectFactory();
@@ -955,15 +958,14 @@ public class SessionImpl implements Sess
         });
     }
 
+    @Override
     public ItemIterable<CmisObject> queryObjects(String typeId, String where, final boolean searchAllVersions,
             OperationContext context) {
         if (typeId == null || typeId.trim().length() == 0) {
             throw new IllegalArgumentException("Type ID must be set!");
         }
 
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkContext(context);
 
         final DiscoveryService discoveryService = getBinding().getDiscoveryService();
         final ObjectFactory of = getObjectFactory();
@@ -1023,10 +1025,12 @@ public class SessionImpl implements Sess
         });
     }
 
+    @Override
     public QueryStatement createQueryStatement(final String statement) {
         return new QueryStatementImpl(this, statement);
     }
 
+    @Override
     public QueryStatement createQueryStatement(final Collection<String> selectPropertyIds,
             final Map<String, String> fromTypes, final String whereClause, final List<String> orderByPropertyIds) {
         return new QueryStatementImpl(this, selectPropertyIds, fromTypes, whereClause, orderByPropertyIds);
@@ -1084,11 +1088,10 @@ public class SessionImpl implements Sess
 
     // --- creates ---
 
+    @Override
     public ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
             VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) {
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Properties must not be empty!");
-        }
+        checkProperties(properties);
 
         String newId = getBinding().getObjectService().createDocument(getRepositoryId(),
                 objectFactory.convertProperties(properties, null, null, CREATE_AND_CHECKOUT_UPDATABILITY),
@@ -1103,9 +1106,10 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
             VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) {
-        if ((source == null) || (source.getId() == null)) {
+        if (source == null || source.getId() == null) {
             throw new IllegalArgumentException("Source must be set!");
         }
 
@@ -1137,14 +1141,11 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId, List<Policy> policies,
             List<Ace> addAces, List<Ace> removeAces) {
-        if ((folderId == null) || (folderId.getId() == null)) {
-            throw new IllegalArgumentException("Folder ID must be set!");
-        }
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Properties must not be empty!");
-        }
+        checkFolderId(folderId);
+        checkProperties(properties);
 
         String newId = getBinding().getObjectService().createFolder(getRepositoryId(),
                 objectFactory.convertProperties(properties, null, null, CREATE_UPDATABILITY), folderId.getId(),
@@ -1158,11 +1159,10 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId, List<Policy> policies,
             List<Ace> addAces, List<Ace> removeAces) {
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Properties must not be empty!");
-        }
+        checkProperties(properties);
 
         String newId = getBinding().getObjectService().createPolicy(getRepositoryId(),
                 objectFactory.convertProperties(properties, null, null, CREATE_UPDATABILITY),
@@ -1176,11 +1176,10 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createItem(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces,
             List<Ace> removeAces) {
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Properties must not be empty!");
-        }
+        checkProperties(properties);
 
         String newId = getBinding().getObjectService().createItem(getRepositoryId(),
                 objectFactory.convertProperties(properties, null, null, CREATE_UPDATABILITY),
@@ -1194,11 +1193,10 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createRelationship(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
             List<Ace> removeAces) {
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Properties must not be empty!");
-        }
+        checkProperties(properties);
 
         String newId = getBinding().getObjectService().createRelationship(getRepositoryId(),
                 objectFactory.convertProperties(properties, null, null, CREATE_UPDATABILITY),
@@ -1212,42 +1210,45 @@ public class SessionImpl implements Sess
         return createObjectId(newId);
     }
 
+    @Override
     public ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
             VersioningState versioningState) {
         return createDocument(properties, folderId, contentStream, versioningState, null, null, null);
     }
 
+    @Override
     public ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
             VersioningState versioningState) {
         return createDocumentFromSource(source, properties, folderId, versioningState, null, null, null);
     }
 
+    @Override
     public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId) {
         return createFolder(properties, folderId, null, null, null);
     }
 
+    @Override
     public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId) {
         return createPolicy(properties, folderId, null, null, null);
     }
 
+    @Override
     public ObjectId createItem(Map<String, ?> properties, ObjectId folderId) {
         return createItem(properties, folderId, null, null, null);
     }
 
     // --- relationships ---
 
+    @Override
     public ObjectId createRelationship(Map<String, ?> properties) {
         return createRelationship(properties, null, null, null);
     }
 
+    @Override
     public ItemIterable<Relationship> getRelationships(ObjectId objectId, final boolean includeSubRelationshipTypes,
             final RelationshipDirection relationshipDirection, ObjectType type, OperationContext context) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
-        if (context == null) {
-            throw new IllegalArgumentException("Operation context must be set!");
-        }
+        checkObjectId(objectId);
+        checkContext(context);
 
         final String id = objectId.getId();
         final String typeId = (type == null ? null : type.getId());
@@ -1285,15 +1286,11 @@ public class SessionImpl implements Sess
 
     // --- bulk update ---
 
+    @Override
     public List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(List<CmisObject> objects,
             Map<String, ?> properties, List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds) {
-        if (repositoryInfo.getCmisVersion() == CmisVersion.CMIS_1_0) {
-            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
-        }
-
-        if (isNullOrEmpty(properties)) {
-            throw new IllegalArgumentException("Objects must be set!");
-        }
+        checkCmisVersion();
+        checkProperties(properties);
 
         ObjectType objectType = null;
         Map<String, SecondaryType> secondaryTypes = new HashMap<String, SecondaryType>();
@@ -1312,7 +1309,7 @@ public class SessionImpl implements Sess
             }
         }
 
-        // gather ids and change tokens
+        // gather IDs and change tokens
         List<BulkUpdateObjectIdAndChangeToken> objectIdsAndChangeTokens = new ArrayList<BulkUpdateObjectIdAndChangeToken>();
         for (CmisObject object : objects) {
             if (object == null) {
@@ -1343,29 +1340,44 @@ public class SessionImpl implements Sess
 
     // --- delete ---
 
+    @Override
     public void delete(ObjectId objectId) {
         delete(objectId, true);
     }
 
+    @Override
     public void delete(ObjectId objectId, boolean allVersions) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
+        checkObjectId(objectId);
 
         getBinding().getObjectService().deleteObject(getRepositoryId(), objectId.getId(), allVersions, null);
         removeObjectFromCache(objectId);
     }
 
+    @Override
+    public List<String> deleteTree(ObjectId folderId, boolean allVersions, UnfileObject unfile,
+            boolean continueOnFailure) {
+        checkFolderId(folderId);
+
+        FailedToDeleteData failed = getBinding().getObjectService().deleteTree(getRepositoryId(), folderId.getId(),
+                allVersions, unfile, continueOnFailure, null);
+
+        if (failed == null || isNullOrEmpty(failed.getIds())) {
+            removeObjectFromCache(folderId);
+        }
+
+        return (failed != null ? failed.getIds() : null);
+    }
+
     // --- content stream ---
 
+    @Override
     public ContentStream getContentStream(ObjectId docId) {
         return getContentStream(docId, null, null, null);
     }
 
+    @Override
     public ContentStream getContentStream(ObjectId docId, String streamId, BigInteger offset, BigInteger length) {
-        if ((docId == null) || (docId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid document ID!");
-        }
+        checkDocumentId(docId);
 
         // get the stream
         ContentStream contentStream = null;
@@ -1382,20 +1394,15 @@ public class SessionImpl implements Sess
 
     // --- ACL ---
 
+    @Override
     public Acl getAcl(ObjectId objectId, boolean onlyBasicPermissions) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
-
-        String id = objectId.getId();
-
-        return getBinding().getAclService().getAcl(getRepositoryId(), id, onlyBasicPermissions, null);
+        checkObjectId(objectId);
+        return getBinding().getAclService().getAcl(getRepositoryId(), objectId.getId(), onlyBasicPermissions, null);
     }
 
+    @Override
     public Acl applyAcl(ObjectId objectId, List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
+        checkObjectId(objectId);
 
         ObjectFactory of = getObjectFactory();
 
@@ -1403,10 +1410,10 @@ public class SessionImpl implements Sess
                 of.convertAces(removeAces), aclPropagation, null);
     }
 
+    @Override
     public Acl setAcl(ObjectId objectId, List<Ace> aces) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
+        checkObjectId(objectId);
+
         if (aces == null) {
             aces = Collections.emptyList();
         }
@@ -1423,12 +1430,11 @@ public class SessionImpl implements Sess
 
     // --- Policies ---
 
+    @Override
     public void applyPolicy(ObjectId objectId, ObjectId... policyIds) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
+        checkObjectId(objectId);
 
-        if ((policyIds == null) || (policyIds.length == 0)) {
+        if (policyIds == null || policyIds.length == 0) {
             throw new IllegalArgumentException("No Policies provided!");
         }
 
@@ -1446,12 +1452,11 @@ public class SessionImpl implements Sess
         }
     }
 
+    @Override
     public void removePolicy(ObjectId objectId, ObjectId... policyIds) {
-        if ((objectId == null) || (objectId.getId() == null)) {
-            throw new IllegalArgumentException("Invalid object ID!");
-        }
+        checkObjectId(objectId);
 
-        if ((policyIds == null) || (policyIds.length == 0)) {
+        if (policyIds == null || policyIds.length == 0) {
             throw new IllegalArgumentException("No Policies provided!");
         }
 
@@ -1469,6 +1474,56 @@ public class SessionImpl implements Sess
         }
     }
 
+    // ----
+
+    protected final void checkObjectId(ObjectId objectId) {
+        if (objectId == null || objectId.getId() == null) {
+            throw new IllegalArgumentException("Invalid object ID!");
+        }
+    }
+
+    protected final void checkObjectId(String objectId) {
+        if (objectId == null) {
+            throw new IllegalArgumentException("Invalid object ID!");
+        }
+    }
+
+    protected final void checkDocumentId(ObjectId docId) {
+        if (docId == null || docId.getId() == null) {
+            throw new IllegalArgumentException("Invalid document ID!");
+        }
+    }
+
+    protected final void checkDocumentId(String docId) {
+        if (docId == null) {
+            throw new IllegalArgumentException("Invalid document ID!");
+        }
+    }
+
+    protected final void checkFolderId(ObjectId folderId) {
+        if (folderId == null || folderId.getId() == null) {
+            throw new IllegalArgumentException("Invalid folder ID!");
+        }
+    }
+
+    protected final void checkContext(OperationContext context) {
+        if (context == null) {
+            throw new IllegalArgumentException("Invalid Operation Context!");
+        }
+    }
+
+    protected final void checkProperties(Map<String, ?> properties) {
+        if (isNullOrEmpty(properties)) {
+            throw new IllegalArgumentException("Properties must not be empty!");
+        }
+    }
+
+    protected final void checkCmisVersion() {
+        if (repositoryInfo.getCmisVersion() == CmisVersion.CMIS_1_0) {
+            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
+        }
+    }
+
     // ----
 
     @Override

Added: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractAsyncSession.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractAsyncSession.java?rev=1681380&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractAsyncSession.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/async/AbstractAsyncSession.java Sat May 23 20:48:20 2015
@@ -0,0 +1,141 @@
+/*
+ * 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.runtime.async;
+
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import org.apache.chemistry.opencmis.client.api.AsyncSession;
+import org.apache.chemistry.opencmis.client.api.CmisObject;
+import org.apache.chemistry.opencmis.client.api.Document;
+import org.apache.chemistry.opencmis.client.api.ObjectId;
+import org.apache.chemistry.opencmis.client.api.OperationContext;
+import org.apache.chemistry.opencmis.client.api.Session;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+
+/**
+ * An abstract implementation of the {@link AsyncSession} interface providing
+ * convenience implementations.
+ */
+public abstract class AbstractAsyncSession implements AsyncSession {
+
+    protected Session session;
+
+    public AbstractAsyncSession(Session session) {
+        if (session == null) {
+            throw new IllegalArgumentException("Session must be set!");
+        }
+
+        this.session = session;
+    }
+
+    @Override
+    public Session getSession() {
+        return session;
+    }
+
+    @Override
+    public Future<CmisObject> getObject(ObjectId objectId) {
+        return getObject(objectId, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<CmisObject> getObject(String objectId) {
+        return getObject(objectId, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<CmisObject> getObjectByPath(String path) {
+        return getObjectByPath(path, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<CmisObject> getObjectByPath(String parentPath, String name) {
+        return getObjectByPath(parentPath, name, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<Document> getLatestDocumentVersion(ObjectId objectId) {
+        return getLatestDocumentVersion(objectId, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<Document> getLatestDocumentVersion(ObjectId objectId, OperationContext context) {
+        return getLatestDocumentVersion(objectId, false, context);
+    }
+
+    @Override
+    public Future<Document> getLatestDocumentVersion(String objectId) {
+        return getLatestDocumentVersion(objectId, session.getDefaultContext());
+    }
+
+    @Override
+    public Future<Document> getLatestDocumentVersion(String objectId, OperationContext context) {
+        return getLatestDocumentVersion(objectId, false, context);
+    }
+
+    @Override
+    public Future<ObjectId> createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
+            VersioningState versioningState) {
+        return createDocument(properties, folderId, contentStream, versioningState, null, null, null);
+    }
+
+    @Override
+    public Future<ObjectId> createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
+            VersioningState versioningState) {
+        return createDocumentFromSource(source, properties, folderId, versioningState, null, null, null);
+    }
+
+    @Override
+    public Future<ObjectId> createFolder(Map<String, ?> properties, ObjectId folderId) {
+        return createFolder(properties, folderId, null, null, null);
+    }
+
+    @Override
+    public Future<ObjectId> createPolicy(Map<String, ?> properties, ObjectId folderId) {
+        return createPolicy(properties, folderId, null, null, null);
+    }
+
+    @Override
+    public Future<ObjectId> createItem(Map<String, ?> properties, ObjectId folderId) {
+        return createItem(properties, folderId, null, null, null);
+    }
+
+    @Override
+    public Future<ObjectId> createRelationship(Map<String, ?> properties) {
+        return createRelationship(properties, null, null, null);
+    }
+
+    @Override
+    public Future<ContentStream> getContentStream(ObjectId docId) {
+        return getContentStream(docId, null, null, null);
+    }
+
+    @Override
+    public Future<ContentStream> storeContentStream(ObjectId docId, OutputStream target) {
+        return storeContentStream(docId, null, null, null, target);
+    }
+
+    @Override
+    public Future<?> delete(ObjectId objectId) {
+        return delete(objectId, true);
+    }
+}