Author: fmui
Date: Fri Feb  3 17:47:12 2017
New Revision: 1781583

URL: http://svn.apache.org/viewvc?rev=1781583&view=rev
Log:
more convenient methods and code clean up

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/QueryStatementImpl.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-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/util/TypeUtils.java
    
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ObjectService.java
    
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateAndDeleteFolderTest.java
    
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateBigDocument.java
    
chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/FolderTable.java

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=1781583&r1=1781582&r2=1781583&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
 Fri Feb  3 17:47:12 2017
@@ -62,8 +62,8 @@ import org.apache.chemistry.opencmis.com
  * some incompliant repositories might throw other exception than you expect.
  * <p>
  * Refer to the <a href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/";>CMIS 
1.0
- * specification</a> or the <a
- * href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/";>CMIS 1.1
+ * specification</a> or the
+ * <a href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/";>CMIS 1.1
  * specification</a> for details about the domain model, terms, concepts, base
  * types, properties, IDs and query names, query language, etc.
  * </p>
@@ -127,9 +127,9 @@ public interface Session extends Seriali
      * Creates a new operation context object with the given properties.
      * 
      * @param filter
-     *            the property filter, a comma separated string of
-     *            <em>query names</em> or "*" for all properties or {@code 
null}
-     *            to let the repository determine a set of properties
+     *            the property filter, a comma separated string of <em>query
+     *            names</em> or "*" for all properties or {@code null} to let
+     *            the repository determine a set of properties
      * @param includeAcls
      *            indicates whether ACLs should be included or not
      * @param includeAllowableActions
@@ -145,9 +145,9 @@ public interface Session extends Seriali
      *            indicates whether path segment or the relative path segment
      *            should be included or not
      * @param orderBy
-     *            the object order, a comma-separated list of
-     *            <em>query names</em> and the ascending modifier "ASC" or the
-     *            descending modifier "DESC" for each query name
+     *            the object order, a comma-separated list of <em>query
+     *            names</em> and the ascending modifier "ASC" or the descending
+     *            modifier "DESC" for each query name
      * @param cacheEnabled
      *            flag that indicates if the object cache should be used
      * @param maxItemsPerPage
@@ -1029,6 +1029,11 @@ public interface Session extends Seriali
     /**
      * Creates a new folder.
      * 
+     * @param properties
+     *            the folder properties
+     * @param folderId
+     *            the folder ID of the parent folder, not {@code null}
+     * 
      * @return the object ID of the new folder
      * 
      * @see Folder#createFolder(Map, List, List, List, OperationContext)
@@ -1041,6 +1046,11 @@ public interface Session extends Seriali
     /**
      * Creates a new folder.
      * 
+     * @param properties
+     *            the folder properties
+     * @param folderId
+     *            the folder ID of the parent folder, not {@code null}
+     * 
      * @return the object ID of the new folder
      * 
      * @see Folder#createFolder(Map, List, List, List, OperationContext)
@@ -1050,8 +1060,109 @@ public interface Session extends Seriali
     ObjectId createFolder(Map<String, ?> properties, ObjectId folderId);
 
     /**
+     * Creates a folder path.
+     * 
+     * All missing folders in the path are created. Existing folders are not
+     * touched.
+     * 
+     * @param newPath
+     *            the absolute path
+     * @param typeId
+     *            the type ID of all folders that are being created
+     * 
+     * @return the object ID of the deepest folder
+     * 
+     * @cmis 1.0
+     */
+    ObjectId createPath(String newPath, String typeId);
+
+    /**
+     * Creates a folder path.
+     * 
+     * All missing folders in the path are created. Existing folders are not
+     * touched.
+     * 
+     * @param startFolderId
+     *            the ID of a folder in the path that the path creation should
+     *            start with, {@code null} for the root folder.
+     * @param newPath
+     *            the absolute path
+     * @param typeId
+     *            the type ID of all folders that are being created
+     * 
+     * @return the object ID of the deepest folder
+     * 
+     * @cmis 1.0
+     */
+    ObjectId createPath(ObjectId startFolderId, String newPath, String typeId);
+
+    /**
+     * Creates a folder path.
+     * 
+     * All missing folders in the path are created. Existing folders are not
+     * touched.
+     * 
+     * @param newPath
+     *            the absolute path
+     * @param properties
+     *            the properties of all folders that are being created
+     * 
+     * @return the object ID of the deepest folder
+     * 
+     * @cmis 1.0
+     */
+    ObjectId createPath(String newPath, Map<String, ?> properties);
+
+    /**
+     * Creates a folder path.
+     * 
+     * All missing folders in the path are created. Existing folders are not
+     * touched.
+     * 
+     * @param startFolderId
+     *            the ID of a folder in the path that the path creation should
+     *            start with, {@code null} for the root folder
+     * @param newPath
+     *            the absolute path
+     * @param properties
+     *            the properties of all folders that are being created
+     * 
+     * @return the object ID of the deepest folder
+     * 
+     * @cmis 1.0
+     */
+    ObjectId createPath(ObjectId startFolderId, String newPath, Map<String, ?> 
properties);
+
+    /**
+     * Creates a folder path.
+     * 
+     * All missing folders in the path are created. Existing folders are not
+     * touched.
+     * 
+     * @param startFolderId
+     *            the ID of a folder in the path that the path creation should
+     *            start with, {@code null} for the root folder
+     * @param newPath
+     *            the absolute path
+     * @param properties
+     *            the properties of all folders that are being created
+     * 
+     * @return the object ID of the deepest folder
+     * 
+     * @cmis 1.0
+     */
+    ObjectId createPath(ObjectId startFolderId, String newPath, Map<String, ?> 
properties, List<Policy> policies,
+            List<Ace> addAces, List<Ace> removeAces);
+
+    /**
      * Creates a new policy.
      * 
+     * @param properties
+     *            the policy properties
+     * @param folderId
+     *            the folder ID of the parent folder, {@code null} for an
+     *            unfiled policy
+     * 
      * @return the object ID of the new policy
      * 
      * @see Folder#createPolicy(Map, List, List, List, OperationContext)
@@ -1064,6 +1175,12 @@ public interface Session extends Seriali
     /**
      * Creates a new policy.
      * 
+     * @param properties
+     *            the policy properties
+     * @param folderId
+     *            the folder ID of the parent folder, {@code null} for an
+     *            unfiled policy
+     * 
      * @return the object ID of the new policy
      * 
      * @see Folder#createPolicy(Map, List, List, List, OperationContext)
@@ -1075,6 +1192,12 @@ public interface Session extends Seriali
     /**
      * Creates a new item.
      * 
+     * @param properties
+     *            the item properties
+     * @param folderId
+     *            the folder ID of the parent folder, {@code null} for an
+     *            unfiled item
+     * 
      * @return the object ID of the new policy
      * 
      * @see Folder#createItem(Map, List, List, List, OperationContext)
@@ -1087,6 +1210,12 @@ public interface Session extends Seriali
     /**
      * Creates a new item.
      * 
+     * @param properties
+     *            the item properties
+     * @param folderId
+     *            the folder ID of the parent folder, {@code null} for an
+     *            unfiled item
+     * 
      * @return the object ID of the new item
      * 
      * @see Folder#createItem(Map, List, List, List, OperationContext)
@@ -1097,7 +1226,10 @@ public interface Session extends Seriali
 
     /**
      * Creates a new relationship.
-     * 
+     *
+     * @param properties
+     *            the relationship properties
+     *
      * @return the object ID of the new relationship
      * 
      * @cmis 1.0
@@ -1108,6 +1240,9 @@ public interface Session extends Seriali
     /**
      * Creates a new relationship.
      * 
+     * @param properties
+     *            the relationship properties
+     * 
      * @return the object ID of the new relationship
      * 
      * @cmis 1.0
@@ -1155,6 +1290,43 @@ public interface Session extends Seriali
     void delete(ObjectId objectId, boolean allVersions);
 
     /**
+     * Deletes an object by path and, if it is a document, all versions in the
+     * version series.
+     * 
+     * @param path
+     *            the path of the object
+     * 
+     * @cmis 1.0
+     */
+    public void deleteByPath(String path);
+
+    /**
+     * Deletes an object by path and, if it is a document, all versions in the
+     * version series.
+     * 
+     * @param parentPath
+     *            the path of the parent folder
+     * @param name
+     *            the (path segment) name of the object in the folder
+     * 
+     * @cmis 1.0
+     */
+    void deleteByPath(String parentPath, String name);
+
+    /**
+     * Deletes an object by path.
+     * 
+     * @param path
+     *            the path 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
+     */
+    void deleteByPath(String path, boolean allVersions);
+
+    /**
      * Deletes a folder and all subfolders.
      * 
      * @param folderId
@@ -1176,6 +1348,51 @@ public interface Session extends Seriali
     List<String> deleteTree(ObjectId folderId, boolean allVersions, 
UnfileObject unfile, boolean continueOnFailure);
 
     /**
+     * Deletes a folder and all subfolders by path.
+     * 
+     * @param parentPath
+     *            the path of the parent folder
+     * @param name
+     *            the (path segment) name of the folder in the parent 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> deleteTreebyPath(String parentPath, String name, boolean 
allVersions, UnfileObject unfile,
+            boolean continueOnFailure);
+
+    /**
+     * Deletes a folder and all subfolders by path.
+     * 
+     * @param path
+     *            the path 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> deleteTreebyPath(String path, 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/QueryStatementImpl.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/QueryStatementImpl.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/QueryStatementImpl.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/QueryStatementImpl.java
 Fri Feb  3 17:47:12 2017
@@ -30,7 +30,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.TimeZone;
 
 import org.apache.chemistry.opencmis.client.api.ItemIterable;
 import org.apache.chemistry.opencmis.client.api.ObjectId;
@@ -130,8 +129,8 @@ public class QueryStatementImpl implemen
                     primaryType = type;
                     primaryAlias = alias;
                 } else {
-                    throw new IllegalArgumentException("Two primary types 
found: " + primaryType.getId() + " and "
-                            + type.getId());
+                    throw new IllegalArgumentException(
+                            "Two primary types found: " + primaryType.getId() 
+ " and " + type.getId());
                 }
             }
 
@@ -193,8 +192,8 @@ public class QueryStatementImpl implemen
                 }
 
                 if (propertyDef == null) {
-                    throw new IllegalArgumentException("Property '" + 
propertyId
-                            + "' is not defined in the provided object 
types!");
+                    throw new IllegalArgumentException(
+                            "Property '" + propertyId + "' is not defined in 
the provided object types!");
                 }
 
                 if (propertyDef.getQueryName() == null) {
@@ -269,8 +268,8 @@ public class QueryStatementImpl implemen
                 }
 
                 if (propertyDef == null) {
-                    throw new IllegalArgumentException("Property '" + 
realPropertyId
-                            + "' is not defined in the provided object 
types!");
+                    throw new IllegalArgumentException(
+                            "Property '" + realPropertyId + "' is not defined 
in the provided object types!");
                 }
 
                 if (propertyDef.getQueryName() == null) {

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=1781583&r1=1781582&r2=1781583&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
 Fri Feb  3 17:47:12 2017
@@ -83,6 +83,7 @@ import org.apache.chemistry.opencmis.com
 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.CmisBaseException;
 import 
org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import 
org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
 import 
org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
@@ -122,7 +123,6 @@ public class SessionImpl implements Sess
     }
 
     // private static Logger log = LoggerFactory.getLogger(SessionImpl.class);
-
     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
     private transient LinkedHashMap<String, ObjectType> objectTypeCache;
 
@@ -198,7 +198,7 @@ public class SessionImpl implements Sess
     }
 
     private Locale determineLocale(Map<String, String> parameters) {
-        Locale result = null;
+        Locale result;
 
         String language = 
parameters.get(SessionParameter.LOCALE_ISO639_LANGUAGE);
         String country = 
parameters.get(SessionParameter.LOCALE_ISO3166_COUNTRY);
@@ -207,18 +207,14 @@ public class SessionImpl implements Sess
         if (variant != null) {
             // all 3 parameter must not be null and valid
             result = new Locale(language, country, variant);
+        } else if (country != null) {
+            // 2 parameter must not be null and valid
+            result = new Locale(language, country);
+        } else if (language != null) {
+            // 1 parameter must not be null and valid
+            result = new Locale(language);
         } else {
-            if (country != null) {
-                // 2 parameter must not be null and valid
-                result = new Locale(language, country);
-            } else {
-                if (language != null) {
-                    // 1 parameter must not be null and valid
-                    result = new Locale(language);
-                } else {
-                    result = Locale.getDefault();
-                }
-            }
+            result = Locale.getDefault();
         }
 
         return result;
@@ -432,6 +428,7 @@ public class SessionImpl implements Sess
                 };
             }
         }) {
+
             @Override
             public ItemIterable<ChangeEvent> skipTo(long position) {
                 throw new CmisNotSupportedException("Skipping not supported!");
@@ -446,6 +443,7 @@ public class SessionImpl implements Sess
             public ItemIterable<ChangeEvent> getPage(int maxNumItems) {
                 throw new CmisNotSupportedException("Paging not supported!");
             }
+
         };
     }
 
@@ -587,24 +585,7 @@ public class SessionImpl implements Sess
 
     @Override
     public CmisObject getObjectByPath(String parentPath, String name, 
OperationContext context) {
-        if (parentPath == null || parentPath.length() < 1) {
-            throw new IllegalArgumentException("Parent path must be set!");
-        }
-        if (parentPath.charAt(0) != '/') {
-            throw new IllegalArgumentException("Parent path must start with a 
'/'!");
-        }
-        if (name == null || name.length() < 1) {
-            throw new IllegalArgumentException("Name must be set!");
-        }
-
-        StringBuilder path = new StringBuilder(parentPath.length() + 
name.length() + 2);
-        path.append(parentPath);
-        if (!parentPath.endsWith("/")) {
-            path.append('/');
-        }
-        path.append(name);
-
-        return getObjectByPath(path.toString(), context);
+        return getObjectByPath(buildPath(parentPath, name), context);
     }
 
     @Override
@@ -767,41 +748,22 @@ public class SessionImpl implements Sess
         checkPath(path);
 
         try {
-            ObjectData object = 
binding.getObjectService().getObjectByPath(getRepositoryId(), path, 
"cmis:objectId",
-                    Boolean.FALSE, IncludeRelationships.NONE, "cmis:none", 
Boolean.FALSE, Boolean.FALSE, null);
-
+            String objectId = getObjectIdByPath(path);
             String cacheObjectId = cache.getObjectIdByPath(path);
-            if (cacheObjectId != null && 
!cacheObjectId.equals(object.getId())) {
+
+            if (cacheObjectId != null && !cacheObjectId.equals(objectId)) {
                 cache.removePath(path);
             }
 
             return true;
         } catch (CmisObjectNotFoundException onf) {
-            cache.removePath(path);
             return false;
         }
     }
 
     @Override
     public boolean existsPath(String parentPath, String name) {
-        if (parentPath == null || parentPath.length() < 1) {
-            throw new IllegalArgumentException("Parent path must be set!");
-        }
-        if (parentPath.charAt(0) != '/') {
-            throw new IllegalArgumentException("Parent path must start with a 
'/'!");
-        }
-        if (name == null || name.length() < 1) {
-            throw new IllegalArgumentException("Name must be set!");
-        }
-
-        StringBuilder path = new StringBuilder(parentPath.length() + 
name.length() + 2);
-        path.append(parentPath);
-        if (!parentPath.endsWith("/")) {
-            path.append('/');
-        }
-        path.append(name);
-
-        return existsPath(path.toString());
+        return existsPath(buildPath(parentPath, name));
     }
 
     @Override
@@ -846,33 +808,33 @@ public class SessionImpl implements Sess
     public ItemIterable<ObjectType> getTypeChildren(final String typeId, final 
boolean includePropertyDefinitions) {
         final RepositoryService repositoryService = 
getBinding().getRepositoryService();
 
-        return new CollectionIterable<ObjectType>(new 
AbstractPageFetcher<ObjectType>(getDefaultContext()
-                .getMaxItemsPerPage()) {
-
-            @Override
-            protected AbstractPageFetcher.Page<ObjectType> fetchPage(long 
skipCount) {
+        return new CollectionIterable<ObjectType>(
+                new 
AbstractPageFetcher<ObjectType>(getDefaultContext().getMaxItemsPerPage()) {
 
-                // fetch the data
-                TypeDefinitionList tdl = 
repositoryService.getTypeChildren(SessionImpl.this.getRepositoryId(), typeId,
-                        includePropertyDefinitions, 
BigInteger.valueOf(this.maxNumItems),
-                        BigInteger.valueOf(skipCount), null);
+                    @Override
+                    protected AbstractPageFetcher.Page<ObjectType> 
fetchPage(long skipCount) {
 
-                // convert type definitions
-                List<ObjectType> page = new 
ArrayList<ObjectType>(tdl.getList().size());
-                for (TypeDefinition typeDefinition : tdl.getList()) {
-                    page.add(convertTypeDefinition(typeDefinition));
-                }
+                        // fetch the data
+                        TypeDefinitionList tdl = 
repositoryService.getTypeChildren(SessionImpl.this.getRepositoryId(),
+                                typeId, includePropertyDefinitions, 
BigInteger.valueOf(this.maxNumItems),
+                                BigInteger.valueOf(skipCount), null);
+
+                        // convert type definitions
+                        List<ObjectType> page = new 
ArrayList<ObjectType>(tdl.getList().size());
+                        for (TypeDefinition typeDefinition : tdl.getList()) {
+                            page.add(convertTypeDefinition(typeDefinition));
+                        }
 
-                return new AbstractPageFetcher.Page<ObjectType>(page, 
tdl.getNumItems(), tdl.hasMoreItems()) {
-                };
-            }
-        });
+                        return new AbstractPageFetcher.Page<ObjectType>(page, 
tdl.getNumItems(), tdl.hasMoreItems()) {
+                        };
+                    }
+                });
     }
 
     @Override
     public ObjectType getTypeDefinition(String typeId) {
-        TypeDefinition typeDefinition = 
getBinding().getRepositoryService().getTypeDefinition(getRepositoryId(),
-                typeId, null);
+        TypeDefinition typeDefinition = 
getBinding().getRepositoryService().getTypeDefinition(getRepositoryId(), typeId,
+                null);
 
         return convertAndCacheTypeDefinition(typeDefinition, true);
     }
@@ -922,7 +884,7 @@ public class SessionImpl implements Sess
 
     /**
      * Converts a type definition into an object type and caches the result.
-     * 
+     *
      * The cache should only be used for type definitions that have been 
fetched
      * with getTypeDefinition() because the high level cache should roughly
      * correspond to the low level type cache. The type definitions returned by
@@ -1154,8 +1116,8 @@ public class SessionImpl implements Sess
                 throw new IllegalStateException("Repository ID is not set!");
             }
 
-            repositoryInfo = 
objectFactory.convertRepositoryInfo(getBinding().getRepositoryService().getRepositoryInfo(
-                    repositoryId, null));
+            repositoryInfo = objectFactory
+                    
.convertRepositoryInfo(getBinding().getRepositoryService().getRepositoryInfo(repositoryId,
 null));
         } finally {
             lock.writeLock().unlock();
         }
@@ -1188,7 +1150,6 @@ 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) {
@@ -1243,8 +1204,8 @@ public class SessionImpl implements Sess
     }
 
     @Override
-    public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId, 
List<Policy> policies,
-            List<Ace> addAces, List<Ace> removeAces) {
+    public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId, 
List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces) {
         checkFolderId(folderId);
         checkProperties(properties);
 
@@ -1261,8 +1222,141 @@ public class SessionImpl implements Sess
     }
 
     @Override
-    public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId, 
List<Policy> policies,
+    public ObjectId createPath(String newPath, String typeId) {
+        return createPath(null, newPath, typeId);
+    }
+
+    @Override
+    public ObjectId createPath(ObjectId startFolderId, String newPath, String 
typeId) {
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put(PropertyIds.OBJECT_TYPE_ID, typeId);
+
+        return createPath(startFolderId, newPath, properties, null, null, 
null);
+    }
+
+    @Override
+    public ObjectId createPath(String newPath, Map<String, ?> properties) {
+        return createPath(null, newPath, properties);
+    }
+
+    @Override
+    public ObjectId createPath(ObjectId startFolderId, String newPath, 
Map<String, ?> properties) {
+        return createPath(startFolderId, newPath, properties, null, null, 
null);
+    }
+
+    @Override
+    public ObjectId createPath(ObjectId startFolderId, String newPath, 
Map<String, ?> properties, List<Policy> policies,
             List<Ace> addAces, List<Ace> removeAces) {
+        checkPath(newPath);
+        if (newPath.length() == 1) {
+            throw new IllegalArgumentException("Cannot create root folder!");
+        }
+        if (newPath.charAt(newPath.length() - 1) == '/') {
+            throw new IllegalArgumentException("Path cannot end with a '/'!");
+        }
+
+        checkProperties(properties);
+        if (!(properties.get(PropertyIds.OBJECT_TYPE_ID) instanceof String)) {
+            throw new IllegalArgumentException("Property '" + 
PropertyIds.OBJECT_TYPE_ID + "' not set or invalid!");
+        }
+
+        StringBuilder nextPath = new StringBuilder(newPath.length());
+        String[] segements;
+        ObjectId lastFolderId = null;
+        boolean create = false;
+
+        // check start folder
+        if (startFolderId != null && startFolderId.getId() != null) {
+            if (startFolderId instanceof Folder) {
+                Folder startFolder = (Folder) startFolderId;
+                if (!startFolder.isRootFolder()) {
+                    nextPath.append(startFolder.getPath());
+                    lastFolderId = startFolder;
+                }
+            } else {
+                ObjectData startFolderData = null;
+                try {
+                    startFolderData = 
getBinding().getObjectService().getObject(getRepositoryId(),
+                            startFolderId.getId(), 
"cmis:objectId,cmis:baseTypeId,cmis:name,cmis:path", false,
+                            IncludeRelationships.NONE, "cmis:none", false, 
false, null);
+                } catch (CmisBaseException cbe) {
+                    throw new IllegalArgumentException("Start folder does not 
exist or is not accessible!", cbe);
+                }
+
+                if (startFolderData.getBaseTypeId() != BaseTypeId.CMIS_FOLDER) 
{
+                    throw new IllegalArgumentException("Start folder is not a 
folder!");
+                }
+
+                if (startFolderData.getProperties() == null || 
startFolderData.getProperties().getProperties() == null
+                        || 
startFolderData.getProperties().getProperties().get(PropertyIds.PATH) == null) {
+                    throw new IllegalArgumentException("Start folder has no 
path property?!");
+                }
+
+                Object startPath = 
startFolderData.getProperties().getProperties().get(PropertyIds.PATH)
+                        .getFirstValue();
+                if (!(startPath instanceof String)) {
+                    throw new IllegalArgumentException("Start folder has an 
invalid path property?!");
+                }
+
+                if 
(!repositoryInfo.getRootFolderId().equals(startFolderData.getId())) {
+                    nextPath.append(startPath);
+                    lastFolderId = startFolderId;
+                }
+            }
+
+            if (!newPath.startsWith(nextPath.toString())) {
+                throw new IllegalArgumentException("Start folder in not in the 
path!");
+            }
+
+            segements = newPath.substring(nextPath.length()).split("/");
+        } else {
+            segements = newPath.split("/");
+        }
+
+        // create folders
+        for (int i = 1; i < segements.length; i++) {
+            if (create) {
+                lastFolderId = 
createFolder(buildCreatePathProperties(properties, segements[i]), lastFolderId, 
policies,
+                        addAces, removeAces);
+            } else {
+                try {
+                    nextPath.append('/');
+                    nextPath.append(segements[i]);
+
+                    ObjectData folderData = 
getBinding().getObjectService().getObjectByPath(getRepositoryId(),
+                            nextPath.toString(), 
"cmis:objectId,cmis:baseTypeId,cmis:name", false,
+                            IncludeRelationships.NONE, "cmis:none", false, 
false, null);
+                    if (folderData.getBaseTypeId() != BaseTypeId.CMIS_FOLDER) {
+                        throw new CmisConstraintException("Cannot create a 
folder '" + segements[i]
+                                + "' because there is already an object with 
this name, which is not a folder!");
+                    }
+
+                    lastFolderId = new ObjectIdImpl(folderData.getId());
+                } catch (CmisObjectNotFoundException onfe) {
+                    if (lastFolderId == null) {
+                        lastFolderId = new 
ObjectIdImpl(repositoryInfo.getRootFolderId());
+                    }
+
+                    lastFolderId = 
createFolder(buildCreatePathProperties(properties, segements[i]), lastFolderId,
+                            policies, addAces, removeAces);
+                    create = true;
+                }
+            }
+        }
+
+        return lastFolderId;
+    }
+
+    private Map<String, ?> buildCreatePathProperties(Map<String, ?> 
properties, String name) {
+        Map<String, Object> newProperties = new HashMap<String, 
Object>(properties);
+        newProperties.put(PropertyIds.NAME, name);
+
+        return newProperties;
+    }
+
+    @Override
+    public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId, 
List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces) {
         checkProperties(properties);
 
         String newId = 
getBinding().getObjectService().createPolicy(getRepositoryId(),
@@ -1339,7 +1433,6 @@ public class SessionImpl implements Sess
     }
 
     // --- relationships ---
-
     @Override
     public ObjectId createRelationship(Map<String, ?> properties) {
         return createRelationship(properties, null, null, null);
@@ -1386,7 +1479,6 @@ public class SessionImpl implements Sess
     }
 
     // --- bulk update ---
-
     @Override
     public List<BulkUpdateObjectIdAndChangeToken> 
bulkUpdateProperties(List<CmisObject> objects,
             Map<String, ?> properties, List<String> addSecondaryTypeIds, 
List<String> removeSecondaryTypeIds) {
@@ -1402,8 +1494,8 @@ public class SessionImpl implements Sess
                 ObjectType secondaryType = getTypeDefinition(stid);
 
                 if (!(secondaryType instanceof SecondaryType)) {
-                    throw new IllegalArgumentException("Secondary types 
contains a type that is not a secondary type: "
-                            + secondaryType.getId());
+                    throw new IllegalArgumentException(
+                            "Secondary types contains a type that is not a 
secondary type: " + secondaryType.getId());
                 }
 
                 secondaryTypes.put(secondaryType.getId(), (SecondaryType) 
secondaryType);
@@ -1417,8 +1509,8 @@ public class SessionImpl implements Sess
                 continue;
             }
 
-            objectIdsAndChangeTokens.add(new 
BulkUpdateObjectIdAndChangeTokenImpl(object.getId(), object
-                    .getChangeToken()));
+            objectIdsAndChangeTokens
+                    .add(new 
BulkUpdateObjectIdAndChangeTokenImpl(object.getId(), object.getChangeToken()));
 
             if (objectType == null) {
                 objectType = object.getType();
@@ -1440,7 +1532,6 @@ public class SessionImpl implements Sess
     }
 
     // --- delete ---
-
     @Override
     public void delete(ObjectId objectId) {
         delete(objectId, true);
@@ -1455,6 +1546,23 @@ public class SessionImpl implements Sess
     }
 
     @Override
+    public void deleteByPath(String path) {
+        deleteByPath(path, true);
+    }
+
+    @Override
+    public void deleteByPath(String parentPath, String name) {
+        deleteByPath(buildPath(parentPath, name), true);
+    }
+
+    @Override
+    public void deleteByPath(String path, boolean allVersions) {
+        checkPath(path);
+
+        delete(new ObjectIdImpl(getObjectIdByPath(path)), allVersions);
+    }
+
+    @Override
     public List<String> deleteTree(ObjectId folderId, boolean allVersions, 
UnfileObject unfile,
             boolean continueOnFailure) {
         checkFolderId(folderId);
@@ -1469,8 +1577,21 @@ public class SessionImpl implements Sess
         return (failed != null ? failed.getIds() : null);
     }
 
-    // --- content stream ---
+    @Override
+    public List<String> deleteTreebyPath(String parentPath, String name, 
boolean allVersions, UnfileObject unfile,
+            boolean continueOnFailure) {
+        return deleteTreebyPath(buildPath(parentPath, name), allVersions, 
unfile, continueOnFailure);
+    }
+
+    @Override
+    public List<String> deleteTreebyPath(String path, boolean allVersions, 
UnfileObject unfile,
+            boolean continueOnFailure) {
+        checkPath(path);
+
+        return deleteTree(new ObjectIdImpl(getObjectIdByPath(path)), 
allVersions, unfile, continueOnFailure);
+    }
 
+    // --- content stream ---
     @Override
     public ContentStream getContentStream(ObjectId docId) {
         return getContentStream(docId, null, null, null);
@@ -1483,8 +1604,8 @@ public class SessionImpl implements Sess
         // get the stream
         ContentStream contentStream = null;
         try {
-            contentStream = 
getBinding().getObjectService().getContentStream(getRepositoryId(), 
docId.getId(),
-                    streamId, offset, length, null);
+            contentStream = 
getBinding().getObjectService().getContentStream(getRepositoryId(), 
docId.getId(), streamId,
+                    offset, length, null);
         } catch (CmisConstraintException e) {
             // no content stream
             return null;
@@ -1506,13 +1627,13 @@ public class SessionImpl implements Sess
         checkPath(path);
 
         // check the cache
-        String docId = cache.getObjectIdByPath(path);
+        boolean fromCache = true;
+        String objectId = cache.getObjectIdByPath(path);
 
         // not in cache -> get the object
-        if (docId == null) {
-            ObjectData objectData = 
getBinding().getObjectService().getObjectByPath(getRepositoryId(), path,
-                    "cmis:objectId,cmis:baseTypeId", false, 
IncludeRelationships.NONE, "cmis:none", false, false, null);
-            docId = objectData.getId();
+        if (objectId == null) {
+            fromCache = false;
+            objectId = getObjectIdByPath(path);
 
             // don't check if the object is a document
             // the path could belong to a folder or an item and the stream ID
@@ -1522,22 +1643,33 @@ public class SessionImpl implements Sess
         // get the stream
         ContentStream contentStream = null;
         try {
-            contentStream = 
getBinding().getObjectService().getContentStream(getRepositoryId(), docId, 
streamId,
+            contentStream = 
getBinding().getObjectService().getContentStream(getRepositoryId(), objectId, 
streamId,
                     offset, length, null);
         } catch (CmisConstraintException ce) {
             // no content stream
             return null;
         } catch (CmisObjectNotFoundException onfe) {
-            removeObjectFromCache(docId);
-            cache.remove(docId);
-            throw onfe;
+            if (fromCache) {
+                removeObjectFromCache(objectId);
+                cache.removePath(path);
+            } else {
+                throw onfe;
+            }
+        }
+
+        if (contentStream == null) {
+            // we are here because we got the object ID from the cache but the
+            // object couldn't be found anymore
+            // there maybe now a new object at this path -> let's try again
+
+            contentStream = 
getBinding().getObjectService().getContentStream(getRepositoryId(), 
getObjectIdByPath(path),
+                    streamId, offset, length, null);
         }
 
         return contentStream;
     }
 
     // --- ACL ---
-
     @Override
     public Acl getAcl(ObjectId objectId, boolean onlyBasicPermissions) {
         checkObjectId(objectId);
@@ -1573,7 +1705,6 @@ public class SessionImpl implements Sess
     }
 
     // --- Policies ---
-
     @Override
     public void applyPolicy(ObjectId objectId, ObjectId... policyIds) {
         checkObjectId(objectId);
@@ -1619,6 +1750,37 @@ public class SessionImpl implements Sess
     }
 
     // ----
+    protected String buildPath(String parentPath, String name) {
+        if (parentPath == null || parentPath.length() < 1) {
+            throw new IllegalArgumentException("Parent path must be set!");
+        }
+        if (parentPath.charAt(0) != '/') {
+            throw new IllegalArgumentException("Parent path must start with a 
'/'!");
+        }
+        if (name == null || name.length() < 1) {
+            throw new IllegalArgumentException("Name must be set!");
+        }
+
+        StringBuilder path = new StringBuilder(parentPath.length() + 
name.length() + 2);
+        path.append(parentPath);
+        if (!parentPath.endsWith("/")) {
+            path.append('/');
+        }
+        path.append(name);
+
+        return path.toString();
+    }
+
+    protected String getObjectIdByPath(String path) {
+        try {
+            return 
getBinding().getObjectService().getObjectByPath(getRepositoryId(), path,
+                    "cmis:objectId,cmis:baseTypeId", false, 
IncludeRelationships.NONE, "cmis:none", false, false, null)
+                    .getId();
+        } catch (CmisObjectNotFoundException onfe) {
+            cache.removePath(path);
+            throw onfe;
+        }
+    }
 
     protected final void checkObjectId(ObjectId objectId) {
         if (objectId == null || objectId.getId() == null) {
@@ -1678,7 +1840,6 @@ public class SessionImpl implements Sess
     }
 
     // ----
-
     @Override
     public String toString() {
         return "Session " + getBinding().getSessionId();

Modified: 
chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/util/TypeUtils.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/util/TypeUtils.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/util/TypeUtils.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/util/TypeUtils.java
 Fri Feb  3 17:47:12 2017
@@ -26,7 +26,6 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -223,7 +222,8 @@ public final class TypeUtils {
         if (type.isControllableAcl() == null) {
             errors.add(new ValidationError("controllableACL", "ControllableACL 
flag must be set."));
         } else if (type.getBaseTypeId() == BaseTypeId.CMIS_SECONDARY && 
Boolean.TRUE.equals(type.isControllableAcl())) {
-            errors.add(new ValidationError("controllableACL", "ControllableACL 
flag must be FALSE for secondary types."));
+            errors.add(
+                    new ValidationError("controllableACL", "ControllableACL 
flag must be FALSE for secondary types."));
         }
 
         if (type.isFulltextIndexed() == null) {
@@ -342,7 +342,8 @@ public final class TypeUtils {
             errors.add(new ValidationError("orderable", "Orderable flag must 
be set."));
         } else if (propDef.isOrderable().booleanValue()) {
             if (propDef.getCardinality() == Cardinality.MULTI) {
-                errors.add(new ValidationError("orderable", "Orderable flag is 
set to TRUE for a multi-value property."));
+                errors.add(
+                        new ValidationError("orderable", "Orderable flag is 
set to TRUE for a multi-value property."));
             }
         }
 
@@ -352,35 +353,43 @@ public final class TypeUtils {
 
         if (propDef instanceof PropertyIdDefinition) {
             if (propDef.getPropertyType() != PropertyType.ID) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyStringDefinition) {
             if (propDef.getPropertyType() != PropertyType.STRING) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyIntegerDefinition) {
             if (propDef.getPropertyType() != PropertyType.INTEGER) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyDecimalDefinition) {
             if (propDef.getPropertyType() != PropertyType.DECIMAL) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyBooleanDefinition) {
             if (propDef.getPropertyType() != PropertyType.BOOLEAN) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyDateTimeDefinition) {
             if (propDef.getPropertyType() != PropertyType.DATETIME) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyHtmlDefinition) {
             if (propDef.getPropertyType() != PropertyType.HTML) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         } else if (propDef instanceof PropertyUriDefinition) {
             if (propDef.getPropertyType() != PropertyType.URI) {
-                errors.add(new ValidationError("propertyType", "Property type 
does not match the property definition."));
+                errors.add(
+                        new ValidationError("propertyType", "Property type 
does not match the property definition."));
             }
         }
 

Modified: 
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ObjectService.java
URL: 
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ObjectService.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ObjectService.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ObjectService.java
 Fri Feb  3 17:47:12 2017
@@ -27,7 +27,6 @@ import java.math.BigInteger;
 import java.util.GregorianCalendar;
 import java.util.List;
 import java.util.Map;
-import java.util.TimeZone;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;

Modified: 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateAndDeleteFolderTest.java
URL: 
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateAndDeleteFolderTest.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateAndDeleteFolderTest.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateAndDeleteFolderTest.java
 Fri Feb  3 17:47:12 2017
@@ -41,67 +41,97 @@ public class CreateAndDeleteFolderTest e
     public void init(Map<String, String> parameters) {
         super.init(parameters);
         setName("Create and Delete Folder Test");
-        setDescription("Creates a few folders, checks the newly created 
folders and their parent and finally deletes the created folders.");
+        setDescription(
+                "Creates a few folders, checks the newly created folders and 
their parent and finally deletes the created folders.");
     }
 
     @Override
     public void run(Session session) {
-        CmisTestResult f;
-
-        int numOfFolders = 20;
-
         // create a test folder
         Folder testFolder = createTestFolder(session);
 
         try {
-            Map<String, Folder> folders = new HashMap<String, Folder>();
+            testFolderList(session, testFolder, 20);
+            testDeepHierarchy(session, testFolder, 20);
+        } finally {
+            // delete the test folder
+            deleteTestFolder();
+        }
+    }
 
-            // create folders
-            for (int i = 0; i < numOfFolders; i++) {
-                Folder newFolder = createFolder(session, testFolder, "folder" 
+ i);
-                folders.put(newFolder.getId(), newFolder);
-            }
+    private void testFolderList(Session session, Folder testFolder, int 
numOfFolders) {
+        CmisTestResult f;
 
-            // simple children test
-            addResult(checkChildren(session, testFolder, "Test folder children 
check"));
+        Map<String, Folder> folders = new HashMap<String, Folder>();
 
-            // check if all folders are there
-            ItemIterable<CmisObject> children = 
testFolder.getChildren(SELECT_ALL_NO_CACHE_OC);
-            List<String> childrenIds = new ArrayList<String>();
-            for (CmisObject child : children) {
-                if (child != null) {
-                    childrenIds.add(child.getId());
-                    Folder folder = folders.get(child.getId());
-
-                    f = createResult(FAILURE, "Folder and test folder child 
don't match! Id: " + child.getId());
-                    addResult(assertShallowEquals(folder, child, null, f));
-                }
-            }
+        // create folders
+        for (int i = 0; i < numOfFolders; i++) {
+            Folder newFolder = createFolder(session, testFolder, "folder" + i);
+            folders.put(newFolder.getId(), newFolder);
+        }
 
-            f = createResult(FAILURE, "Number of created folders does not 
match the number of existing folders!");
-            addResult(assertEquals(numOfFolders, childrenIds.size(), null, f));
+        // simple children test
+        addResult(checkChildren(session, testFolder, "Test folder children 
check"));
 
-            for (Folder folder : folders.values()) {
-                if (!childrenIds.contains(folder.getId())) {
-                    addResult(createResult(FAILURE,
-                            "Created folder not found in test folder children! 
Id: " + folder.getId()));
-                }
+        // check if all folders are there
+        ItemIterable<CmisObject> children = 
testFolder.getChildren(SELECT_ALL_NO_CACHE_OC);
+        List<String> childrenIds = new ArrayList<String>();
+        for (CmisObject child : children) {
+            if (child != null) {
+                childrenIds.add(child.getId());
+                Folder folder = folders.get(child.getId());
+
+                f = createResult(FAILURE, "Folder and test folder child don't 
match! Id: " + child.getId());
+                addResult(assertShallowEquals(folder, child, null, f));
             }
+        }
 
-            // delete all folders
-            for (Folder folder : folders.values()) {
-                // empty folders should be deleteable like this
-                folder.delete(true);
-
-                f = createResult(FAILURE,
-                        "Folder should not exist anymore but it is still 
there! Id: " + folder.getId());
-                addResult(assertIsFalse(exists(folder), null, f));
+        f = createResult(FAILURE, "Number of created folders does not match 
the number of existing folders!");
+        addResult(assertEquals(numOfFolders, childrenIds.size(), null, f));
+
+        for (Folder folder : folders.values()) {
+            if (!childrenIds.contains(folder.getId())) {
+                addResult(createResult(FAILURE,
+                        "Created folder not found in test folder children! Id: 
" + folder.getId()));
             }
-        } finally {
-            // delete the test folder
-            deleteTestFolder();
+        }
+
+        // delete all folders
+        for (Folder folder : folders.values()) {
+            // empty folders should be deleteable like this
+            folder.delete(true);
+
+            f = createResult(FAILURE, "Folder should not exist anymore but it 
is still there! Id: " + folder.getId());
+            addResult(assertIsFalse(exists(folder), null, f));
         }
 
         addResult(createInfoResult("Tested the creation and deletion of " + 
numOfFolders + " folders."));
     }
+
+    private void testDeepHierarchy(Session session, Folder testFolder, int 
depth) {
+        String folderName = "depth";
+
+        StringBuilder path = new StringBuilder(testFolder.getPath());
+        for (int i = 0; i < depth; i++) {
+            path.append('/');
+            path.append(folderName + i);
+        }
+
+        session.createPath(testFolder, path.toString(), getFolderTestTypeId());
+
+        for (int i = 0; i < depth; i++) {
+            CmisObject folderObj = session.getObjectByPath(path.toString(), 
SELECT_ALL_NO_CACHE_OC);
+
+            if (folderObj instanceof Folder) {
+                session.deleteByPath(((Folder) folderObj).getPath());
+            } else {
+                addResult(createResult(FAILURE, "Just created folder is not a 
folder! Id: " + folderObj.getId()));
+            }
+
+            path.delete(path.lastIndexOf("/"), path.length());
+        }
+
+        addResult(createInfoResult("Tested the creation of a folder hierarchy 
with a depth of " + (depth + 1)
+                + " below the test folder."));
+    }
 }

Modified: 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateBigDocument.java
URL: 
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateBigDocument.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateBigDocument.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/crud/CreateBigDocument.java
 Fri Feb  3 17:47:12 2017
@@ -23,6 +23,7 @@ import static org.apache.chemistry.openc
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.chemistry.opencmis.client.api.Document;
@@ -35,6 +36,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.tck.CmisTestResult;
+import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.FAILURE;
 import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTest;
 
 /**
@@ -105,8 +107,14 @@ public class CreateBigDocument extends A
             f = createResult(FAILURE, "Content stream length doesn't match the 
uploaded content!", true);
             assertEquals(size, doc.getContentStreamLength(), null, f);
 
-            // delete it
-            doc.delete(true);
+            // delete it by path
+            List<String> paths = doc.getPaths();
+
+            f = createResult(FAILURE,
+                    "The document must have at least one path because it was 
created in a folder! Id: " + doc.getId());
+            addResult(assertIsTrue(paths != null && paths.size() > 0, null, 
f));
+
+            session.deleteByPath(paths.get(0));
         } finally {
             // delete the test folder
             deleteTestFolder();

Modified: 
chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/FolderTable.java
URL: 
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/FolderTable.java?rev=1781583&r1=1781582&r2=1781583&view=diff
==============================================================================
--- 
chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/FolderTable.java
 (original)
+++ 
chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/FolderTable.java
 Fri Feb  3 17:47:12 2017
@@ -148,9 +148,9 @@ public class FolderTable extends JTable
             @Override
             public void actionPerformed(ActionEvent e) {
                 if (model.getCurrentObject() != null) {
-                    int answer = 
JOptionPane.showConfirmDialog(FolderTable.this, "Do you really want to delete '"
-                            + model.getCurrentObject().getName() + "'?", 
"Delete", JOptionPane.YES_NO_OPTION,
-                            JOptionPane.WARNING_MESSAGE);
+                    int answer = 
JOptionPane.showConfirmDialog(FolderTable.this,
+                            "Do you really want to delete '" + 
model.getCurrentObject().getName() + "'?", "Delete",
+                            JOptionPane.YES_NO_OPTION, 
JOptionPane.WARNING_MESSAGE);
 
                     if (answer == JOptionPane.YES_OPTION) {
                         DeleteWorker worker = new 
DeleteWorker(FolderTable.this, model.getCurrentObject()) {
@@ -257,17 +257,17 @@ public class FolderTable extends JTable
 
         // load icon and set icon column size
         loadIcons();
-        getColumnModel().getColumn(0).setPreferredWidth(
-                (int) (icons.get(BaseTypeId.CMIS_DOCUMENT).getIconWidth() * 
1.1));
+        getColumnModel().getColumn(0)
+                .setPreferredWidth((int) 
(icons.get(BaseTypeId.CMIS_DOCUMENT).getIconWidth() * 1.1));
     }
 
     private void loadIcons() {
         icons = new EnumMap<BaseTypeId, Icon>(BaseTypeId.class);
-        icons.put(BaseTypeId.CMIS_DOCUMENT, new 
DocumentIcon(ClientHelper.OBJECT_ICON_SIZE,
-                ClientHelper.OBJECT_ICON_SIZE));
+        icons.put(BaseTypeId.CMIS_DOCUMENT,
+                new DocumentIcon(ClientHelper.OBJECT_ICON_SIZE, 
ClientHelper.OBJECT_ICON_SIZE));
         icons.put(BaseTypeId.CMIS_FOLDER, new 
FolderIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
-        icons.put(BaseTypeId.CMIS_RELATIONSHIP, new 
RelationshipIcon(ClientHelper.OBJECT_ICON_SIZE,
-                ClientHelper.OBJECT_ICON_SIZE));
+        icons.put(BaseTypeId.CMIS_RELATIONSHIP,
+                new RelationshipIcon(ClientHelper.OBJECT_ICON_SIZE, 
ClientHelper.OBJECT_ICON_SIZE));
         icons.put(BaseTypeId.CMIS_POLICY, new 
PolicyIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
         icons.put(BaseTypeId.CMIS_ITEM, new 
ItemIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
 
@@ -332,7 +332,7 @@ public class FolderTable extends JTable
                 if (obj instanceof Document) {
                     Document doc = (Document) obj;
                     if (Boolean.TRUE.equals(doc.isVersionSeriesCheckedOut())) {
-                        if 
(doc.getId().equals(doc.getVersionSeriesCheckedOutId())) {
+                        if 
(Boolean.TRUE.equals(doc.isVersionSeriesPrivateWorkingCopy())) {
                             return pwcIcon;
                         } else {
                             return checkedOutIcon;
@@ -421,8 +421,8 @@ public class FolderTable extends JTable
 
             File file = null;
             try {
-                List<File> fileList = (List<File>) 
support.getTransferable().getTransferData(
-                        DataFlavor.javaFileListFlavor);
+                List<File> fileList = (List<File>) support.getTransferable()
+                        .getTransferData(DataFlavor.javaFileListFlavor);
 
                 if (fileList == null || fileList.size() != 1 || 
fileList.get(0) == null || !fileList.get(0).isFile()) {
                     return false;


Reply via email to