PortCMIS: more code,more test, more documentation

git-svn-id: https://svn.apache.org/repos/asf/chemistry/portcmis/trunk@1743666 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/PortCMIS/client/ClientCaches.cs b/PortCMIS/client/ClientCaches.cs
index fdfdc9e..9494ba4 100644
--- a/PortCMIS/client/ClientCaches.cs
+++ b/PortCMIS/client/ClientCaches.cs
@@ -83,12 +83,25 @@
         ICmisObject GetByPath(string path, string cacheKey);

 

         /// <summary>

+        /// Gets the object ID by path.

+        /// </summary>

+        /// <param name="path">the path</param>

+        /// <returns>the object ID</returns>

+        string GetObjectIdByPath(string path);

+

+        /// <summary>

         /// Removes an object from the cache.

         /// </summary>

         /// <param name="objectId">the object ID</param>

         void Remove(string objectId);

 

         /// <summary>

+        /// Removes a path from the cache.

+        /// </summary>

+        /// <param name="path">the path</param>

+        void RemovePath(string path);

+

+        /// <summary>

         /// Clears the cache.

         /// </summary>

         void Clear();

@@ -126,9 +139,15 @@
         public ICmisObject GetByPath(string path, string cacheKey) { return null; }

 

         /// <inheritdoc/> 

+        public string GetObjectIdByPath(string path) { return null; }

+

+        /// <inheritdoc/> 

         public void Remove(string objectId) { }

 

         /// <inheritdoc/> 

+        public void RemovePath(string path) { }

+

+        /// <inheritdoc/> 

         public void Clear() { }

 

         /// <inheritdoc/> 

@@ -343,6 +362,16 @@
         }

 

         /// <inheritdoc/> 

+        public string GetObjectIdByPath(string path)

+        {

+            lock (cacheLock)

+            {

+                return pathToIdCache.Get(path);

+            }

+        }

+

+

+        /// <inheritdoc/> 

         public void Remove(string objectId)

         {

             if (objectId == null)

@@ -357,6 +386,20 @@
         }

 

         /// <inheritdoc/> 

+        public void RemovePath(string path)

+        {

+            if (path == null)

+            {

+                return;

+            }

+

+            lock (cacheLock)

+            {

+                pathToIdCache.Remove(path);

+            }

+        }

+

+        /// <inheritdoc/> 

         public int CacheSize

         {

             get { return cacheSize; }

diff --git a/PortCMIS/client/ClientImpl.cs b/PortCMIS/client/ClientImpl.cs
index 59abe28..693cdd5 100644
--- a/PortCMIS/client/ClientImpl.cs
+++ b/PortCMIS/client/ClientImpl.cs
@@ -642,10 +642,8 @@
         /// <inheritdoc/>

         public ICmisObject GetObjectByPath(string path, IOperationContext context)

         {

-            if (path == null)

-            {

-                throw new ArgumentNullException("path");

-            }

+            CheckPath(path);

+

             if (context == null)

             {

                 throw new ArgumentNullException("context");

@@ -835,6 +833,89 @@
         }

 

         /// <inheritdoc/>

+        public bool Exists(IObjectId objectId)

+        {

+            if (objectId == null)

+            {

+                throw new ArgumentNullException("objectId");

+            }

+            return Exists(objectId.Id);

+        }

+

+        /// <inheritdoc/>

+        public bool Exists(string objectId)

+        {

+            if (objectId == null)

+            {

+                throw new ArgumentNullException(objectId);

+            }

+

+            try

+            {

+                Binding.GetObjectService().GetObject(RepositoryId, objectId, "cmis:objectId", false,

+                    IncludeRelationships.None, "cmis:none", false, false, null);

+                return true;

+            }

+            catch (CmisObjectNotFoundException)

+            {

+                RemoveObjectFromCache(objectId);

+                return false;

+            }

+        }

+

+        /// <inheritdoc/>

+        public bool ExistsPath(string path)

+        {

+            CheckPath(path);

+

+            try

+            {

+                IObjectData obj = Binding.GetObjectService().GetObjectByPath(RepositoryId, path, "cmis:objectId",

+                    false, IncludeRelationships.None, "cmis:none", false, false, null);

+

+                string cacheObjectId = Cache.GetObjectIdByPath(path);

+                if (cacheObjectId != obj.Id)

+                {

+                    Cache.RemovePath(path);

+                }

+

+                return true;

+            }

+            catch (CmisObjectNotFoundException)

+            {

+                Cache.RemovePath(path);

+                return false;

+            }

+        }

+

+        /// <inheritdoc/>

+        public bool ExistsPath(string parentPath, string name)

+        {

+            if (parentPath == null || parentPath.Length < 1)

+            {

+                throw new ArgumentException("Parent path must be set!", "parentPath");

+            }

+            if (parentPath[0] != '/')

+            {

+                throw new ArgumentException("Parent path must start with a '/'!", "parentPath");

+            }

+            if (name == null || name.Length < 1)

+            {

+                throw new ArgumentException("Name must be set!", "name");

+            }

+

+            StringBuilder path = new StringBuilder(parentPath.Length + name.Length + 2);

+            path.Append(parentPath);

+            if (!parentPath.EndsWith("/"))

+            {

+                path.Append('/');

+            }

+            path.Append(name);

+

+            return ExistsPath(path.ToString());

+        }

+

+        /// <inheritdoc/>

         public void RemoveObjectFromCache(IObjectId objectId)

         {

             if (objectId == null || objectId.Id == null)

@@ -1352,6 +1433,21 @@
                 Binding.GetPolicyService().RemovePolicy(RepositoryId, id, objectId.Id, null);

             }

         }

+

+        /// <summary>

+        /// Checks if the given string is a valid path.

+        /// </summary>

+        protected void CheckPath(string path)

+        {

+            if (path == null || path.Length < 1)

+            {

+                throw new ArgumentException("Invalid path!");

+            }

+            if (path[0] != '/')

+            {

+                throw new ArgumentException("Path must start with a '/'!");

+            }

+        }

     }

 

     internal class QueryStatement : IQueryStatement

diff --git a/PortCMIS/client/ClientIntf.cs b/PortCMIS/client/ClientIntf.cs
index a6c73ff..0fee33e 100644
--- a/PortCMIS/client/ClientIntf.cs
+++ b/PortCMIS/client/ClientIntf.cs
@@ -400,6 +400,43 @@
         IDocument GetLatestDocumentVersion(IObjectId objectId, bool major, IOperationContext context);

 

         /// <summary>

+        ///  Checks if an object with given object ID exists in the repository and is visible for the current user.

+        /// </summary>

+        /// <remarks>If the object doesn't exist (anymore), it is removed from the cache.</remarks>

+        /// <param name="objectId">the object ID</param>

+        /// <returns><c>true</c> if the object exists in the repository, <c>false</c> otherwise</returns>

+        /// <cmis>1.0</cmis>

+        bool Exists(IObjectId objectId);

+

+        /// <summary>

+        ///  Checks if an object with given object ID exists in the repository and is visible for the current user.

+        /// </summary>

+        /// <remarks>If the object doesn't exist (anymore), it is removed from the cache.</remarks>

+        /// <param name="objectId">the object ID</param>

+        /// <returns><c>true</c> if the object exists in the repository, <c>false</c> otherwise</returns>

+        /// <cmis>1.0</cmis>

+        bool Exists(string objectId);

+

+        /// <summary>

+        ///  Checks if an object with given path exists in the repository and is visible for the current user.

+        /// </summary>

+        /// <remarks>If the object doesn't exist (anymore), it is removed from the cache.</remarks>

+        /// <param name="path">the path</param>

+        /// <returns><c>true</c> if the object exists in the repository, <c>false</c> otherwise</returns>

+        /// <cmis>1.0</cmis>

+        bool ExistsPath(string path);

+

+        /// <summary>

+        ///  Checks if an object with given path exists in the repository and is visible for the current user.

+        /// </summary>

+        /// <remarks>If the object doesn't exist (anymore), it is removed from the cache.</remarks>

+        /// <param name="parentPath">the path of the parent folder</param>

+        /// <param name="name">the (path segment) name of the object in the folder</param>

+        /// <returns><c>true</c> if the object exists in the repository, <c>false</c> otherwise</returns>

+        /// <cmis>1.0</cmis>

+        bool ExistsPath(string parentPath, string name);

+

+        /// <summary>

         ///  Removes the given object from the cache.

         /// </summary>

         /// <param name="objectId">the object ID</param>

@@ -1529,6 +1566,11 @@
         IAcl Acl { get; }

 

         /// <summary>

+        /// Checks whether the given allowable action is set or not.

+        /// </summary>

+        bool HasAllowableAction(PortCMIS.Enums.Action action);

+

+        /// <summary>

         /// Deletes this object.

         /// </summary>

         /// <remarks>

diff --git a/PortCMIS/client/ClientObjects.cs b/PortCMIS/client/ClientObjects.cs
index a1ea256..1f964a3 100644
--- a/PortCMIS/client/ClientObjects.cs
+++ b/PortCMIS/client/ClientObjects.cs
@@ -25,6 +25,7 @@
 using PortCMIS.Exceptions;

 using System;

 using System.Collections.Generic;

+using System.IO;

 using System.Numerics;

 using System.Text;

 

@@ -544,6 +545,18 @@
             }

         }

 

+        /// <inheritdoc/>

+        public virtual bool HasAllowableAction(PortCMIS.Enums.Action action)

+        {

+            IAllowableActions currentAllowableActions = AllowableActions;

+            if (currentAllowableActions == null || currentAllowableActions.Actions == null)

+            {

+                throw new Exception("Allowable Actions are not available!");

+            }

+

+            return currentAllowableActions.Actions.Contains(action);

+        }

+

         // --- renditions ---

 

         /// <inheritdoc/>

@@ -696,6 +709,20 @@
                 }

             }

         }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            lock (objectLock)

+            {

+                if (objectType == null)

+                {

+                    return "<unknown>";

+                }

+

+                return objectType.BaseTypeId + " (" + objectType.Id + "): " + Id;

+            }

+        }

     }

 

     /// <summary>

@@ -930,8 +957,15 @@
         public virtual IDocument Copy(IObjectId targetFolderId, IDictionary<string, object> properties, VersioningState? versioningState,

             IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces, IOperationContext context)

         {

-

-            IObjectId newId = Session.CreateDocumentFromSource(this, properties, targetFolderId, versioningState, policies, addAces, removeAces);

+            IObjectId newId;

+            try

+            {

+                newId = Session.CreateDocumentFromSource(this, properties, targetFolderId, versioningState, policies, addAces, removeAces);

+            }

+            catch (CmisNotSupportedException nse)

+            {

+                newId = CopyViaClient(targetFolderId, properties, versioningState, policies, addAces, removeAces);

+            }

 

             // if no context is provided the object will not be fetched

             if (context == null || newId == null)

@@ -954,6 +988,61 @@
             return Copy(targetFolderId, null, null, null, null, null, Session.DefaultContext);

         }

 

+

+        /// <summary>

+        /// Copies the document manually. The content is streamed from the repository and back.

+        /// </summary>

+        protected IObjectId CopyViaClient(IObjectId targetFolderId, IDictionary<string, object> properties,

+                VersioningState? versioningState, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces)

+        {

+            IDictionary<string, object> newProperties = new Dictionary<string, object>();

+

+            IOperationContext allPropsContext = Session.CreateOperationContext();

+            allPropsContext.FilterString = "*";

+            allPropsContext.IncludeAcls = false;

+            allPropsContext.IncludeAllowableActions = false;

+            allPropsContext.IncludePathSegments = false;

+            allPropsContext.IncludePolicies = false;

+            allPropsContext.IncludeRelationships = IncludeRelationships.None;

+            allPropsContext.RenditionFilterString = "cmis:none";

+

+            IDocument allPropsDoc = (IDocument)Session.GetObject(this, allPropsContext);

+

+            foreach (IProperty prop in allPropsDoc.Properties)

+            {

+                if (prop.PropertyDefinition.Updatability == Updatability.ReadWrite

+                    || prop.PropertyDefinition.Updatability == Updatability.OnCreate)

+                {

+                    newProperties.Add(prop.Id, prop.Value);

+                }

+            }

+

+            if (properties != null)

+            {

+                foreach (KeyValuePair<string, object> prop in properties)

+                {

+                    newProperties[prop.Key] = prop.Value;

+                }

+            }

+

+            IContentStream contentStream = allPropsDoc.GetContentStream();

+            try

+            {

+                return Session.CreateDocument(newProperties, targetFolderId, contentStream, versioningState, policies, addAces, removeAces);

+            }

+            finally

+            {

+                if (contentStream != null)

+                {

+                    Stream stream = contentStream.Stream;

+                    if (stream != null)

+                    {

+                        stream.Dispose();

+                    }

+                }

+            }

+        }

+

         /// <inheritdoc/>

         public virtual void DeleteAllVersions()

         {

@@ -1902,6 +1991,12 @@
 

             return value.ToString();

         }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            return Id + ": " + ValuesAsString;

+        }

     }

 

     /// <summary>

diff --git a/PortCMIS/client/ClientUtils.cs b/PortCMIS/client/ClientUtils.cs
index 2070473..f7f48b9 100644
--- a/PortCMIS/client/ClientUtils.cs
+++ b/PortCMIS/client/ClientUtils.cs
@@ -572,6 +572,59 @@
         {

             Id = id;

         }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            return Id;

+        }

+

+        /// <inheritdoc/>

+        public override int GetHashCode()

+        {

+            return Id.GetHashCode();

+        }

+

+        /// <inheritdoc/>

+        public override bool Equals(object obj)

+        {

+            return this.Equals(obj as ObjectId);

+        }

+

+        public bool Equals(ObjectId oid)

+        {

+            if (Object.ReferenceEquals(oid, null))

+            {

+                return false;

+            }

+

+            if (Object.ReferenceEquals(this, oid))

+            {

+                return true;

+            }

+

+            if (this.GetType() != oid.GetType())

+            {

+                return false;

+            }

+

+            return Id == oid.Id;

+        }

+

+        public static bool operator ==(ObjectId id1, ObjectId id2)

+        {

+            if (object.ReferenceEquals(id1, null))

+            {

+                return object.ReferenceEquals(id2, null);

+            }

+

+            return id1.Id == id2.Id;

+        }

+

+        public static bool operator !=(ObjectId id1, ObjectId id2)

+        {

+            return !(id1 == id2);

+        }

     }

 

     /// <summary>

diff --git a/PortCMIS/const/ClientVersion.cs b/PortCMIS/const/ClientVersion.cs
index 699e796..12625d5 100644
--- a/PortCMIS/const/ClientVersion.cs
+++ b/PortCMIS/const/ClientVersion.cs
@@ -1,8 +1,21 @@
-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-using System.Threading.Tasks;

+/*

+* 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.

+*/

 

 namespace PortCMIS

 {

diff --git a/PortCMIS/data/DataImpl.cs b/PortCMIS/data/DataImpl.cs
index 1e67cfc..e3693dd 100644
--- a/PortCMIS/data/DataImpl.cs
+++ b/PortCMIS/data/DataImpl.cs
@@ -1144,6 +1144,12 @@
 

         /// <inheritdoc/>

         public bool IsDirect { get; set; }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            return PrincipalId + ": " + (Permissions == null ? "?" : String.Join(", ", Permissions));

+        }

     }

 

     /// <summary>

@@ -1156,6 +1162,12 @@
 

         /// <inheritdoc/>

         public bool? IsExact { get; set; }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            return "ACL: " + (Aces == null ? "empty" : String.Join(" | ", Aces));

+        }

     }

 

     /// <summary>

@@ -1174,6 +1186,14 @@
 

         /// <inheritdoc/>

         public Stream Stream { get; set; }

+

+        /// <inheritdoc/>

+        public override string ToString()

+        {

+            return "Content Stream : " + FileName + " (" +MimeType +") " +

+                (Length == null ? "" : Length + " bytes" +

+                (Stream == null ? " no stream" : Stream.ToString()));

+        }

     }

     /// <summary>

     /// Simple Content Stream implementation that indicates a partial stream.

diff --git a/PortCMISTests/SimpleCmisTest.cs b/PortCMISTests/SimpleCmisTest.cs
index d603743..a2b300b 100644
--- a/PortCMISTests/SimpleCmisTest.cs
+++ b/PortCMISTests/SimpleCmisTest.cs
@@ -87,9 +87,9 @@
             Assert.IsNotNull(root.AllowableActions);

             Assert.IsNotNull(root.AllowableActions.Actions);

             Assert.IsTrue(root.AllowableActions.Actions.Count > 0);

-            Assert.IsTrue(root.AllowableActions.Actions.Contains(PortCMIS.Enums.Action.CanGetProperties));

-            Assert.IsFalse(root.AllowableActions.Actions.Contains(PortCMIS.Enums.Action.CanGetFolderParent));

-            Assert.IsFalse(root.AllowableActions.Actions.Contains(PortCMIS.Enums.Action.CanMoveObject));

+            Assert.IsTrue(root.HasAllowableAction(PortCMIS.Enums.Action.CanGetProperties));

+            Assert.IsFalse(root.HasAllowableAction(PortCMIS.Enums.Action.CanGetFolderParent));

+            Assert.IsFalse(root.HasAllowableAction(PortCMIS.Enums.Action.CanMoveObject));

 

             foreach (ICmisObject child in root.GetChildren(oc))

             {

@@ -105,31 +105,31 @@
                 Assert.IsNotNull(child.AllowableActions);

                 Assert.IsNotNull(child.AllowableActions.Actions);

                 Assert.IsTrue(child.AllowableActions.Actions.Count > 0);

-                Assert.IsTrue(child.AllowableActions.Actions.Contains(PortCMIS.Enums.Action.CanGetProperties));

+                Assert.IsTrue(child.HasAllowableAction(PortCMIS.Enums.Action.CanGetProperties));

             }

         }

 

         [TestMethod]

         public void TestCreate()

         {

-            try

+            string testFolderName = "porttest";

+

+            if (Session.ExistsPath("/", testFolderName))

             {

-                ICmisObject obj = Session.GetObjectByPath("/porttest");

-                obj.Delete();

-            }

-            catch (CmisConstraintException)

-            {

-                IFolder folder = Session.GetObjectByPath("/porttest") as IFolder;

-                folder.DeleteTree(true, UnfileObject.Delete, true);

-            }

-            catch (CmisObjectNotFoundException)

-            {

-                // ignore

+                ICmisObject obj = Session.GetObjectByPath("/", testFolderName, OperationContextUtils.CreateMinimumOperationContext());

+                if (obj is IFolder)

+                {

+                    ((IFolder)obj).DeleteTree(true, UnfileObject.Delete, true);

+                }

+                else

+                {

+                    obj.Delete();

+                }

             }

 

             // create folder

             IFolder root = Session.GetRootFolder();

-            IFolder newFolder = CreateFolder(root, "porttest");

+            IFolder newFolder = CreateFolder(root, testFolderName);

 

             Assert.IsNotNull(newFolder);

 

@@ -146,8 +146,7 @@
             Assert.AreEqual(contentString, ConvertStreamToString(newContent.Stream));

 

             // fetch it again to get the updated content stream length property

-            IOperationContext ctxt = Session.CreateOperationContext();

-            ctxt.FilterString = "*";

+            IOperationContext ctxt = OperationContextUtils.CreateMaximumOperationContext();

             ICmisObject newObj = Session.GetObject(newDoc, ctxt);

 

             Assert.IsTrue(newObj is IDocument);

@@ -173,15 +172,7 @@
 

             newFolder.Delete();

 

-            try

-            {

-                Session.GetObject(newFolder);

-                Assert.Fail("Folder still exists.");

-            }

-            catch (CmisObjectNotFoundException)

-            {

-                // expected

-            }

+            Assert.IsFalse(Session.Exists(newFolder));

         }

 

         [TestMethod]

@@ -226,6 +217,7 @@
                 if (newFolder != null)

                 {

                     newFolder.DeleteTree(true, UnfileObject.Delete, true);

+                    Assert.IsFalse(Session.Exists(newFolder));

                 }

             }

         }

@@ -258,16 +250,95 @@
                 Assert.IsNotNull(content2.Stream);

 

                 Assert.AreEqual(contentString2, ConvertStreamToString(content2.Stream));

+

+                // delete the content stream

+                doc.DeleteContentStream(true);

+                Assert.IsNull(doc.ContentStreamLength);

             }

             finally

             {

                 if (doc != null)

                 {

                     doc.Delete();

+                    Assert.IsFalse(Session.Exists(doc));

                 }

             }

         }

 

+        [TestMethod]

+        public void TestVersioning()

+        {

+            IOperationContext noCacheOC = OperationContextUtils.CreateMaximumOperationContext();

+            noCacheOC.CacheEnabled = false;

+

+            IFolder rootFolder = Session.GetRootFolder();

+            IDocument doc = null;

+

+            try

+            {

+                // create document

+                string name1 = "versioned1.txt";

+                IContentStream contentStream1 = ContentStreamUtils.CreateTextContentStream(name1, "v1");

+

+                IDictionary<string, object> props = new Dictionary<string, object>();

+                props[PropertyIds.Name] = name1;

+                props[PropertyIds.ObjectTypeId] = "VersionableType";

+

+                doc = rootFolder.CreateDocument(props, contentStream1, VersioningState.Major);

+

+                // create next version

+                string name2 = "versioned2.txt";

+                IContentStream contentStream2 = ContentStreamUtils.CreateTextContentStream(name2, "v2");

+

+                IObjectId pwcId = doc.CheckOut();

+                IDocument pwc = (IDocument)Session.GetObject(pwcId, noCacheOC);

+

+                pwc.Rename(name2);

+

+                IObjectId newVersId = pwc.CheckIn(true, null, contentStream2, "version 2");

+                IDocument newVers = (IDocument)Session.GetObject(newVersId, noCacheOC);

+

+                Assert.AreEqual(name2, newVers.Name);

+                Assert.AreEqual("v2", ConvertStreamToString(newVers.GetContentStream().Stream));

+

+                IDocument latestVersion = Session.GetLatestDocumentVersion(doc);

+                Assert.AreEqual(newVers.Id, latestVersion.Id);

+

+                // create next version

+                string name3 = "versioned3.txt";

+                IContentStream contentStream3 = ContentStreamUtils.CreateTextContentStream(name3, "v3");

+

+                pwcId = doc.CheckOut();

+                pwc = (IDocument)Session.GetObject(pwcId, noCacheOC);

+

+                pwc.Rename(name3);

+

+                newVersId = pwc.CheckIn(true, null, contentStream3, "version 3");

+                newVers = (IDocument)Session.GetObject(newVersId);

+

+                Assert.AreEqual(name3, newVers.Name);

+                Assert.AreEqual("v3", ConvertStreamToString(newVers.GetContentStream().Stream));

+

+                latestVersion = Session.GetLatestDocumentVersion(doc);

+                Assert.AreEqual(newVers.Id, latestVersion.Id);

+

+                // check version history

+

+                IList<IDocument> versions = doc.GetAllVersions();

+                Assert.AreEqual(3, versions.Count);

+

+                Assert.AreEqual(latestVersion.Id, versions[0].Id);

+                Assert.AreEqual(doc.Id, versions[2].Id);

+            }

+            finally

+            {

+                if (doc != null)

+                {

+                    doc.Delete();

+                    Assert.IsFalse(Session.Exists(doc));

+                }

+            }

+        }

 

         [TestMethod]

         public void TestQuery()

@@ -357,6 +428,94 @@
             Session.Delete(item);

             Session.Delete(folder1);

             Session.Delete(folder2);

+

+            Assert.IsFalse(Session.Exists(item));

+            Assert.IsFalse(Session.Exists(folder1));

+            Assert.IsFalse(Session.Exists(folder2));

+        }

+

+        [TestMethod]

+        public void TestCopy()

+        {

+            IFolder rootFolder = Session.GetRootFolder();

+            IFolder folder1 = null;

+            IFolder folder2 = null;

+            IDocument doc1 = null;

+            IDocument doc2 = null;

+

+            string content = "I'm unique!";

+

+            try

+            {

+                folder1 = CreateFolder(rootFolder, "copy1");

+                folder2 = CreateFolder(rootFolder, "copy2");

+                doc1 = CreateTextDocument(folder1, "copydoc.xt", content);

+

+                doc2 = doc1.Copy(folder2);

+

+                Assert.IsNotNull(doc2);

+                Assert.AreEqual(doc1.Name, doc2.Name);

+                Assert.AreEqual(ConvertStreamToString(doc1.GetContentStream().Stream), ConvertStreamToString(doc2.GetContentStream().Stream));

+                Assert.AreEqual(folder2.Id, doc2.Parents[0].Id);

+            }

+            finally

+            {

+                if (folder1 != null)

+                {

+                    folder1.DeleteTree(true, UnfileObject.Delete, true);

+                    Assert.IsFalse(Session.Exists(folder1));

+                }

+                if (folder2 != null)

+                {

+                    folder2.DeleteTree(true, UnfileObject.Delete, true);

+                    Assert.IsFalse(Session.Exists(folder2));

+                }

+            }

+        }

+

+

+

+        [TestMethod]

+        public void TestAcl()

+        {

+            IDocument doc = null;

+

+            try

+            {

+                doc = CreateTextDocument(Session.GetRootFolder(), "acl.txt", "Hello Joe!");

+

+                Ace joeAce = new Ace()

+                {

+                    Principal = new Principal() { Id = "joe" },

+                    Permissions = new List<string> { "cmis:write" }

+                };

+

+                // apply ACL and test result

+                IAcl newAcl = doc.ApplyAcl(new List<IAce> { joeAce }, null, AclPropagation.RepositoryDetermined);

+                Assert.IsNotNull(newAcl);

+                Assert.IsNotNull(newAcl.Aces);

+                Assert.IsTrue(newAcl.Aces.Count > 0);

+

+                // retrieve ACL and test

+                IAcl acl2 = Session.GetAcl(doc, true);

+                Assert.IsNotNull(acl2);

+                Assert.IsNotNull(acl2.Aces);

+                Assert.IsTrue(acl2.Aces.Count > 0);

+

+                // fetch document and test

+                IDocument doc2 = (IDocument)Session.GetObject(doc, OperationContextUtils.CreateMaximumOperationContext());

+                Assert.IsNotNull(doc2.Acl);

+                Assert.IsNotNull(doc2.Acl.Aces);

+                Assert.IsTrue(doc2.Acl.Aces.Count > 0);

+            }

+            finally

+            {

+                if (doc != null)

+                {

+                    doc.Delete();

+                    Assert.IsFalse(Session.Exists(doc));

+                }

+            }

         }

     }

 }