PortCMIS: more stuff (documentation, tests, fixes, ...)

git-svn-id: https://svn.apache.org/repos/asf/chemistry/portcmis/trunk@1742265 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/PortCMIS/binding/atompub/XmlWalker.cs b/PortCMIS/binding/atompub/XmlWalker.cs
index 9b72975..4293773 100644
--- a/PortCMIS/binding/atompub/XmlWalker.cs
+++ b/PortCMIS/binding/atompub/XmlWalker.cs
@@ -105,7 +105,7 @@
 

             if (extensions.Count + 1 > XmlConstraints.MaxExtensionsWidth)

             {

-                throw new CmisInvalidArgumentException("Too many extensions!");

+                throw new CmisInvalidArgumentException("Too many extensions! (More than " + XmlConstraints.MaxExtensionsWidth + " extensions.)");

             }

 

             extensions.Add(HandleExtensionLevel(parser, 0));

@@ -145,7 +145,7 @@
                     {

                         if (sb.Length + s.Length > XmlConstraints.MaxStringLength)

                         {

-                            throw new CmisInvalidArgumentException("String limit exceeded!");

+                            throw new CmisInvalidArgumentException("String limit exceeded! (String is longer than " + XmlConstraints.MaxStringLength + " characters.)");

                         }

                         sb.Append(s);

                     }

@@ -154,7 +154,7 @@
                 {

                     if (level + 1 > XmlConstraints.MaxExtensionsDepth)

                     {

-                        throw new CmisInvalidArgumentException("Extensions tree too deep!");

+                        throw new CmisInvalidArgumentException("Extensions tree too deep! (More than " + XmlConstraints.MaxExtensionsDepth + " levels.)");

                     }

 

                     if (children == null)

@@ -164,7 +164,7 @@
 

                     if (children.Count + 1 > XmlConstraints.MaxExtensionsWidth)

                     {

-                        throw new CmisInvalidArgumentException("Extensions tree too wide!");

+                        throw new CmisInvalidArgumentException("Extensions tree too wide! (More than " + XmlConstraints.MaxExtensionsWidth + " extensions on one level.)");

                     }

 

                     children.Add(HandleExtensionLevel(parser, level + 1));

@@ -288,7 +288,7 @@
     {

         public const int MaxStringLength = 100 * 1024;

 

-        public const int MaxExtensionsWidth = 500;

-        public const int MaxExtensionsDepth = 20;

+        public const int MaxExtensionsWidth = 1000;

+        public const int MaxExtensionsDepth = 100;

     }

 }
\ No newline at end of file
diff --git a/PortCMIS/binding/browser/BrowserConverter.cs b/PortCMIS/binding/browser/BrowserConverter.cs
index 03aeee3..5adaa0b 100644
--- a/PortCMIS/binding/browser/BrowserConverter.cs
+++ b/PortCMIS/binding/browser/BrowserConverter.cs
@@ -2100,7 +2100,7 @@
                         Ace ace = new Ace();

 

                         bool? isDirect = GetBoolean(entry, BrowserConstants.JsonAceIsDirect);

-                        ace.IsDirect = (isDirect != null ? (bool) isDirect : true);

+                        ace.IsDirect = (isDirect != null ? (bool)isDirect : true);

 

                         JsonArray jsonPermissions = GetJsonArray(entry, BrowserConstants.JsonAcePermissions);

                         if (jsonPermissions != null)

@@ -2314,9 +2314,15 @@
             }

 

             ITypeDefinition typeDef = null;

-            if (json[PropertyIds.ObjectTypeId] is string)

+            // TODO: try....

+

+            object objectTypeId;

+            if (json.TryGetValue(PropertyIds.ObjectTypeId, out objectTypeId))

             {

-                typeDef = typeCache.GetTypeDefinition((string)json[PropertyIds.ObjectTypeId]);

+                if (objectTypeId is string)

+                {

+                    typeDef = typeCache.GetTypeDefinition((string)objectTypeId);

+                }

             }

 

             JsonArray secTypeIds = GetJsonArray(json, PropertyIds.SecondaryObjectTypeIds);

diff --git a/PortCMIS/client/ClientImpl.cs b/PortCMIS/client/ClientImpl.cs
index 55e0fe5..93108c0 100644
--- a/PortCMIS/client/ClientImpl.cs
+++ b/PortCMIS/client/ClientImpl.cs
@@ -80,7 +80,7 @@
         /// <param name="authenticationProvider">Authentication provider.</param>

         /// <param name="cache">Client object cache.</param>

         /// <returns>a list of all available repositories</returns>

-        /// <seealso cref="PortCMIS.SessionParameter"/>

+        /// <seealso cref="PortCMIS.Client.SessionParameter"/>

         public IList<IRepository> GetRepositories(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)

         {

             ICmisBinding binding = CmisBindingHelper.CreateBinding(parameters);

@@ -179,6 +179,15 @@
         private IAuthenticationProvider authenticationProvider;

         private ICache cache;

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="info">the low-level repository info object</param>

+        /// <param name="parameters">the session parameters</param>

+        /// <param name="sessionFactory">the session factory</param>

+        /// <param name="objectFactory">the object factory (may be <c>null</c>)</param>

+        /// <param name="authenticationProvider">the authentication provider (may be <c>null</c>)</param>

+        /// <param name="cache">the cache (may be <c>null</c>)</param>

         public Repository(IRepositoryInfo info, IDictionary<string, string> parameters, SessionFactory sessionFactory, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)

             : base(info)

         {

diff --git a/PortCMIS/client/ClientIntf.cs b/PortCMIS/client/ClientIntf.cs
index 1bbf4cd..b04d435 100644
--- a/PortCMIS/client/ClientIntf.cs
+++ b/PortCMIS/client/ClientIntf.cs
@@ -554,38 +554,110 @@
         void RemovePolicy(IObjectId objectId, params IObjectId[] policyIds);

     }

 

+    /// <summary>

+    /// Object Factory implementations convert low-level objects to high-level objects.

+    /// </summary>

     public interface IObjectFactory

     {

+        /// <summary>

+        /// Initializes the factory.

+        /// </summary>

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

+        /// <param name="parameters">some parameters</param>

         void Initialize(ISession session, IDictionary<string, string> parameters);

 

         // Acl and ACE

+

+        /// <summary>

+        /// Converts ACEs into an ACL.

+        /// </summary>

         IAcl ConvertAces(IList<IAce> aces);

+

+        /// <summary>

+        /// Creates an ACL from the given ACEs.

+        /// </summary>

         IAcl CreateAcl(IList<IAce> aces);

+

+        /// <summary>

+        /// Converts ACEs into an ACL.

+        /// </summary>

         IAce CreateAce(string principal, IList<string> permissions);

 

         // policies

+

+        /// <summary>

+        /// Converts policies.

+        /// </summary>

         IList<string> ConvertPolicies(IList<IPolicy> policies);

 

         // renditions

+

+        /// <summary>

+        /// Converts renditions.

+        /// </summary>

         IRendition ConvertRendition(string objectId, IRenditionData rendition);

 

         // content stream

+

+        /// <summary>

+        /// Creates a new Content Stream object.

+        /// </summary>

         IContentStream CreateContentStream(string filename, long length, string mimetype, Stream stream);

 

         // types

+

+        /// <summary>

+        /// Converts a type definition.

+        /// </summary>

         IObjectType ConvertTypeDefinition(ITypeDefinition typeDefinition);

+

+        /// <summary>

+        /// Gets the type from a low-level object.

+        /// </summary>

         IObjectType GetTypeFromObjectData(IObjectData objectData);

 

         // properties

+

+        /// <summary>

+        /// Creates a property object.

+        /// </summary>

         IProperty CreateProperty<T>(IPropertyDefinition type, IList<T> values);

+

+        /// <summary>

+        /// Converts properties.

+        /// </summary>

         IDictionary<string, IProperty> ConvertProperties(IObjectType objectType, IList<ISecondaryType> secondaryTypes, IProperties properties);

+

+        /// <summary>

+        /// Converts properties.

+        /// </summary>

         IProperties ConvertProperties(IDictionary<string, object> properties, IObjectType type, IList<ISecondaryType> secondaryTypes, HashSet<Updatability> updatabilityFilter);

+

+        /// <summary>

+        /// Converts properties from a query result.

+        /// </summary>

         IList<IPropertyData> ConvertQueryProperties(IProperties properties);

 

         // objects

+

+        /// <summary>

+        /// Converts a low-level object into a hig-level object.

+        /// </summary>

         ICmisObject ConvertObject(IObjectData objectData, IOperationContext context);

+

+        /// <summary>

+        /// Converts a query result.

+        /// </summary>

         IQueryResult ConvertQueryResult(IObjectData objectData);

+

+        /// <summary>

+        /// Converts a change event.

+        /// </summary>

         IChangeEvent ConvertChangeEvent(IObjectData objectData);

+

+        /// <summary>

+        /// Converts a collection of change events.

+        /// </summary>

         IChangeEvents ConvertChangeEvents(string changeLogToken, IObjectList objectList);

     }

 

@@ -1006,7 +1078,7 @@
         /// Gets whether the repository contains additional items beyond the page of items already fetched.

         /// </value>

         bool HasMoreItems { get; }

-        

+

         /// <value>

         /// Gets the total number of items. If the repository knows the total number of items

         /// in a result set, the repository SHOULD include the number here.

@@ -1291,6 +1363,14 @@
         /// <summary>

         /// Deletes this object.

         /// </summary>

+        /// <remarks>

+        /// If this object is a document, the whole version series is deleted.

+        /// </remarks>

+        void Delete();

+

+        /// <summary>

+        /// Deletes this object.

+        /// </summary>

         /// <param name="allVersions">if this object is a document this parameter defines if just this version or all versions should be deleted</param>

         void Delete(bool allVersions);

 

diff --git a/PortCMIS/client/ClientObjects.cs b/PortCMIS/client/ClientObjects.cs
index eb9d39d..d5bca43 100644
--- a/PortCMIS/client/ClientObjects.cs
+++ b/PortCMIS/client/ClientObjects.cs
@@ -35,11 +35,24 @@
     /// </summary>

     public abstract class AbstractCmisObject : ICmisObject

     {

+        /// <value>

+        /// Gets the current session.

+        /// </value>

         protected ISession Session { get; private set; }

+

+        /// <value>

+        /// Gets the current repository ID.

+        /// </value>

         protected string RepositoryId { get { return Session.RepositoryInfo.Id; } }

+

+        /// <value>

+        /// Gets the current binding.

+        /// </value>

         protected ICmisBinding Binding { get { return Session.Binding; } }

 

         private IObjectType objectType;

+

+        /// <inheritdoc/>

         public virtual IObjectType ObjectType

         {

             get

@@ -51,6 +64,7 @@
             }

         }

 

+        /// <inheritdoc/>

         public virtual IList<ISecondaryType> SecondaryTypes

         {

             get

@@ -62,6 +76,7 @@
             }

         }

 

+        /// <inheritdoc/>

         protected virtual string ObjectId

         {

             get

@@ -76,6 +91,9 @@
             }

         }

 

+        /// <summary>

+        /// Gets the operation context that was used to fetch this object.

+        /// </summary>

         protected virtual IOperationContext CreationContext { get; private set; }

 

         private IDictionary<string, IProperty> properties;

@@ -86,8 +104,19 @@
         private IList<IRelationship> relationships;

         private IDictionary<ExtensionLevel, IList<ICmisExtensionElement>> extensions;

         private IList<ISecondaryType> secondaryTypes;

+

+        /// <summary>

+        /// An object used for locking.

+        /// </summary>

         protected object objectLock = new object();

 

+        /// <summary>

+        /// Initializes the object.

+        /// </summary>

+        /// <param name="session">the current session</param>

+        /// <param name="objectType">the object type</param>

+        /// <param name="objectData">the low-level object data</param>

+        /// <param name="context">the operation context that was used to fetch this object</param>

         protected void Initialize(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)

         {

             if (session == null)

@@ -241,6 +270,11 @@
             }

         }

 

+        /// <summary>

+        /// Returns the query name of a property.

+        /// </summary>

+        /// <param name="propertyId">the property ID</param>

+        /// <returns>the query name or <c>null</c> if the property doesn't exist or the property has no query name</returns>

         protected virtual string GetPropertyQueryName(string propertyId)

         {

             lock (objectLock)

@@ -258,6 +292,12 @@
         // --- object ---

 

         /// <inheritdoc/>

+        public virtual void Delete()

+        {

+            Delete(true);

+        }

+

+        /// <inheritdoc/>

         public virtual void Delete(bool allVersions)

         {

             lock (objectLock)

@@ -1728,6 +1768,9 @@
         }

     }

 

+    /// <summary>

+    /// Property implementation.

+    /// </summary>

     public class Property : IProperty

     {

         public Property(IPropertyDefinition propertyDefinition, IList<object> values)

@@ -1822,6 +1865,9 @@
         }

     }

 

+    /// <summary>

+    /// Rendition implementation.

+    /// </summary>

     public class Rendition : RenditionData, IRendition

     {

         private ISession session;

@@ -1872,6 +1918,9 @@
         }

     }

 

+    /// <summary>

+    /// Content Stream Hash implementation.

+    /// </summary>

     public class ContentStreamHash : IContentStreamHash

     {

         /// <inheritdoc/>

@@ -1921,6 +1970,9 @@
         }

     }

 

+    /// <summary>

+    /// Query Result implementation.

+    /// </summary>

     public class QueryResult : IQueryResult

     {

         private IDictionary<string, IPropertyData> propertiesById;

@@ -2087,6 +2139,9 @@
         public IList<IRendition> Renditions { get; protected set; }

     }

 

+    /// <summary>

+    /// Change Event implementation.

+    /// </summary>

     public class ChangeEvent : ChangeEventInfo, IChangeEvent

     {

         /// <inheritdoc/>

@@ -2102,6 +2157,9 @@
         public virtual IAcl Acl { get; set; }

     }

 

+    /// <summary>

+    /// Change Events implementation.

+    /// </summary>

     public class ChangeEvents : IChangeEvents

     {

         /// <inheritdoc/>

diff --git a/PortCMIS/client/ClientUtils.cs b/PortCMIS/client/ClientUtils.cs
index 62685ef..43e1010 100644
--- a/PortCMIS/client/ClientUtils.cs
+++ b/PortCMIS/client/ClientUtils.cs
@@ -351,6 +351,8 @@
     public class ObjectId : IObjectId

     {

         private string id;

+

+        /// <inheritdoc/>

         public string Id

         {

             get { return id; }

@@ -365,6 +367,10 @@
             }

         }

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="id">the object ID as a string</param>

         public ObjectId(string id)

         {

             Id = id;

@@ -376,7 +382,10 @@
     /// </summary>

     public class Tree<T> : ITree<T>

     {

+        /// <inheritdoc/>

         public T Item { get; set; }

+

+        /// <inheritdoc/>

         public IList<ITree<T>> Children { get; set; }

     }

 

@@ -465,23 +474,34 @@
             this.pageFetcher = pageFetcher;

         }

 

+        /// <inheritdoc/>

         T IEnumerator<T>.Current { get { return Current; } }

+

+        /// <inheritdoc/>

         object IEnumerator.Current { get { return Current; } }

+

+        /// <inheritdoc/>

         public T Current { get { return current; } }

 

+        /// <summary>

+        /// Reset is not supported.

+        /// </summary>

         public void Reset()

         {

             throw new NotSupportedException();

         }

 

+        /// <inheritdoc/>

         public abstract bool MoveNext();

 

+        /// <inheritdoc/>

         public void Dispose()

         {

             Dispose(true);

             GC.SuppressFinalize(this);

         }

 

+        /// <inheritdoc/>

         protected virtual void Dispose(bool disposing)

         {

         }

diff --git a/PortCMIS/data/DataImpl.cs b/PortCMIS/data/DataImpl.cs
index 6fa7ac4..06da0b5 100644
--- a/PortCMIS/data/DataImpl.cs
+++ b/PortCMIS/data/DataImpl.cs
@@ -27,11 +27,21 @@
 

 namespace PortCMIS.Data

 {

+    /// <summary>

+    /// Repository Info implementation.

+    /// </summary>

     public class RepositoryInfo : ExtensionsData, IRepositoryInfo

     {

+        /// <summary>

+        /// Constructor.

+        /// </summary>

         public RepositoryInfo()

         {

         }

+

+        /// <summary>

+        /// Copy Constructor.

+        /// </summary>

         public RepositoryInfo(IRepositoryInfo source)

         {

             Id = source.Id;

@@ -129,12 +139,16 @@
         /// <inheritdoc/>

         public IList<IExtensionFeature> ExtensionFeatures { get; set; }

 

+        /// <inheritdoc/>

         public override string ToString()

         {

             return "RepositoryInfo: " + Id;

         }

     }

 

+    /// <summary>

+    /// Repository Capabilities implementation.

+    /// </summary>

     internal class RepositoryCapabilities : ExtensionsData, IRepositoryCapabilities

     {

         /// <inheritdoc/>

diff --git a/PortCMISTests/SimpleCmisTest.cs b/PortCMISTests/SimpleCmisTest.cs
index be55f8b..0670c24 100644
--- a/PortCMISTests/SimpleCmisTest.cs
+++ b/PortCMISTests/SimpleCmisTest.cs
@@ -11,6 +11,7 @@
 using System.Text;

 using PortCMIS.Utils;

 using PortCMISTests.Framework;

+using System.Linq;

 

 namespace PortCMISTests

 {

@@ -97,7 +98,7 @@
             try

             {

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

-                obj.Delete(true);

+                obj.Delete();

             }

             catch (CmisConstraintException)

             {

@@ -156,6 +157,33 @@
 

             Assert.AreEqual(newDoc.Name, newDoc2.Name);

             Assert.AreEqual(contentBytes.Length, newDoc2.ContentStreamLength);

+

+            // delete document

+            newDoc.Delete();

+

+            try

+            {

+                Session.GetObject(newDoc);

+                Assert.Fail("Document still exists.");

+            }

+            catch (CmisObjectNotFoundException)

+            {

+                // expected

+            }

+

+            // delete folder

+

+            newFolder.Delete();

+

+            try

+            {

+                Session.GetObject(newFolder);

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

+            }

+            catch (CmisObjectNotFoundException)

+            {

+                // expected

+            }

         }

 

         [TestMethod]

@@ -233,6 +261,70 @@
             }

 

             Assert.IsTrue(count > 0);

+

+            IOperationContext oc = Session.CreateOperationContext();

+            oc.FilterString = "cmis:objectId,cmis:name";

+

+            IFolder rootFolder = Session.GetRootFolder(oc);

+            bool found = false;

+

+            foreach (ICmisObject obj in Session.QueryObjects("cmis:folder", null, false, oc))

+            {

+                Assert.IsNotNull(obj.Id);

+                Assert.IsNotNull(obj.Name);

+

+                if (obj.Id == rootFolder.Id)

+                {

+                    found = true;

+                }

+            }

+

+            Assert.IsTrue(found);

+        }

+

+        [TestMethod]

+        public void TestMove()

+        {

+            // create folder 1

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

+            folder1prop[PropertyIds.Name] = "movefolder1";

+            folder1prop[PropertyIds.ObjectTypeId] = "cmis:folder";

+

+            IObjectId folder1 = Session.CreateFolder(folder1prop, Session.GetRootFolder());

+

+            // create folder2

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

+            folder2prop[PropertyIds.Name] = "movefolder2";

+            folder2prop[PropertyIds.ObjectTypeId] = "cmis:folder";

+

+            IObjectId folder2 = Session.CreateFolder(folder2prop, Session.GetRootFolder());

+

+            // create item

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

+            itemProp[PropertyIds.Name] = "movee";

+            itemProp[PropertyIds.ObjectTypeId] = "cmis:item";

+

+            IObjectId item = Session.CreateItem(itemProp, folder1);

+

+            // move

+            IItem itemObj = Session.GetObject(item) as IItem;

+            itemObj.Move(folder1, folder2);

+

+            itemObj.Refresh();

+

+            // test

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

+

+            int folderSize1 = Enumerable.Count<ICmisObject>((Session.GetObject(folder1) as IFolder).GetChildren());

+            Assert.AreEqual(0, folderSize1);

+

+            int folderSize2 = Enumerable.Count<ICmisObject>((Session.GetObject(folder2) as IFolder).GetChildren());

+            Assert.AreEqual(1, folderSize2);

+

+            // clean up

+            Session.Delete(item);

+            Session.Delete(folder1);

+            Session.Delete(folder2);

         }

     }

 }