PortCMIS: more documentation and other stuff

git-svn-id: https://svn.apache.org/repos/asf/chemistry/portcmis/trunk@1743509 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/PortCMIS/PortCMIS.csproj b/PortCMIS/PortCMIS.csproj
index 3969e35..d6c55dd 100644
--- a/PortCMIS/PortCMIS.csproj
+++ b/PortCMIS/PortCMIS.csproj
@@ -58,6 +58,7 @@
     <Compile Include="binding\browser\BrowserConverter.cs" />

     <Compile Include="binding\browser\BrowserUtils.cs" />

     <Compile Include="binding\browser\json\Json.cs" />

+    <Compile Include="const\ClientVersion.cs" />

     <Compile Include="binding\DateTimeHelper.cs" />

     <Compile Include="binding\HttpPortable.cs" />

     <Compile Include="binding\Http.cs" />

diff --git a/PortCMIS/PortCMIS.shfbproj b/PortCMIS/PortCMIS.shfbproj
index 3aea2d3..d8fbde6 100644
--- a/PortCMIS/PortCMIS.shfbproj
+++ b/PortCMIS/PortCMIS.shfbproj
@@ -95,9 +95,14 @@
     <ApiFilter>

       <Filter entryType="Namespace" fullName="PortCMIS.Binding" isExposed="False" xmlns="">

         <Filter entryType="Class" fullName="PortCMIS.Binding.AbstractAuthenticationProvider" filterName="AbstractAuthenticationProvider" isExposed="True" />

+        <Filter entryType="Interface" fullName="PortCMIS.Binding.IPortableAuthenticationProvider" filterName="IPortableAuthenticationProvider" isExposed="True" />

         <Filter entryType="Interface" fullName="PortCMIS.Binding.IAuthenticationProvider" filterName="IAuthenticationProvider" isExposed="True" />

         <Filter entryType="Class" fullName="PortCMIS.Binding.StandardAuthenticationProvider" filterName="StandardAuthenticationProvider" isExposed="True" />

-      </Filter>

+        <Filter entryType="Interface" fullName="PortCMIS.Binding.IBindingSession" filterName="IBindingSession" isExposed="True" />

+        <Filter entryType="Interface" fullName="PortCMIS.Binding.ICmisBinding" filterName="ICmisBinding" isExposed="True" />

+		<Filter entryType="Class" fullName="PortCMIS.Binding.UrlBuilder" filterName="UrlBuilder" isExposed="True" />

+     </Filter>

+      <Filter entryType="Namespace" fullName="PortCMIS.Binding.Http" isExposed="True" xmlns="" />

       <Filter entryType="Namespace" fullName="PortCMIS.Binding.Browser" isExposed="False" xmlns="" />

       <Filter entryType="Namespace" fullName="PortCMIS.Binding.Browser.Json" isExposed="False" xmlns="" />

       <Filter entryType="Namespace" fullName="PortCMIS.Binding.Http" isExposed="False" xmlns="" />

diff --git a/PortCMIS/binding/BindingIntf.cs b/PortCMIS/binding/BindingIntf.cs
index a45431e..5e19fec 100644
--- a/PortCMIS/binding/BindingIntf.cs
+++ b/PortCMIS/binding/BindingIntf.cs
@@ -28,7 +28,6 @@
 using System.Net.Http;

 using System.Net.Http.Headers;

 using System.Text;

-using System.Threading.Tasks;

 

 namespace PortCMIS.Binding

 {

@@ -253,7 +252,7 @@
     public interface IAuthenticationProvider

     {

         /// <value>

-        /// Gets the binding session instance

+        /// Gets the binding session instance.

         /// </value>

         IBindingSession Session { get; set; }

     }

@@ -283,7 +282,7 @@
     }

 

     /// <summary>

-    /// Base implementation of an authentication provider.

+    /// Base implementation of a portable authentication provider.

     /// </summary>

     public abstract class AbstractAuthenticationProvider : IPortableAuthenticationProvider

     {

diff --git a/PortCMIS/binding/HttpPortable.cs b/PortCMIS/binding/HttpPortable.cs
index 44d10af..a9a1276 100644
--- a/PortCMIS/binding/HttpPortable.cs
+++ b/PortCMIS/binding/HttpPortable.cs
@@ -135,7 +135,10 @@
             HttpRequestMessage request = new HttpRequestMessage(method, url.ToString());

 

             // set additional headers

-            request.Headers.UserAgent.Add(new ProductInfoHeaderValue("ApacheChemistryPortCMIS", "0.1"));

+

+            string userAgent = session.GetValue(SessionParameter.UserAgent) as string;

+            request.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(userAgent ?? ClientVersion.UserAgentName));

+

             if (headers != null)

             {

                 foreach (KeyValuePair<string, string> header in headers)

diff --git a/PortCMIS/binding/Services.cs b/PortCMIS/binding/Services.cs
index e96f1f4..63a934b 100644
--- a/PortCMIS/binding/Services.cs
+++ b/PortCMIS/binding/Services.cs
@@ -38,20 +38,42 @@
         /// </remarks>

         IList<IRepositoryInfo> GetRepositoryInfos(IExtensionsData extension);

 

+        /// <summary>

+        /// Returns information about the CMIS repository, the optional capabilities it supports and its

+        /// access control information if applicable.

+        /// </summary>

         IRepositoryInfo GetRepositoryInfo(string repositoryId, IExtensionsData extension);

 

+        /// <summary>

+        /// Returns the list of object types defined for the repository that are children of the specified type.

+        /// </summary>

         ITypeDefinitionList GetTypeChildren(string repositoryId, string typeId, bool? includePropertyDefinitions,

             BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

 

+        /// <summary>

+        /// Returns the set of descendant object type defined for the repository under the specified type.

+        /// </summary>

         IList<ITypeDefinitionContainer> GetTypeDescendants(string repositoryId, string typeId, BigInteger? depth,

             bool? includePropertyDefinitions, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the definition of the specified object type.

+        /// </summary>

         ITypeDefinition GetTypeDefinition(string repositoryId, string typeId, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates a new type.

+        /// </summary>

         ITypeDefinition CreateType(string repositoryId, ITypeDefinition type, IExtensionsData extension);

-        

+

+        /// <summary>

+        /// Updates a type.

+        /// </summary>

         ITypeDefinition UpdateType(string repositoryId, ITypeDefinition type, IExtensionsData extension);

 

+        /// <summary>

+        /// Deletes a type.

+        /// </summary>

         void DeleteType(string repositoryId, string typeId, IExtensionsData extension);

     }

 

@@ -60,24 +82,42 @@
     /// </summary>

     public interface INavigationService

     {

+        /// <summary>

+        /// Gets the list of child objects contained in the specified folder.

+        /// </summary>

         IObjectInFolderList GetChildren(string repositoryId, string folderId, string filter, string orderBy,

             bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

             bool? includePathSegment, BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the set of descendant objects contained in the specified folder or any of its child folders.

+        /// </summary>

         IList<IObjectInFolderContainer> GetDescendants(string repositoryId, string folderId, BigInteger? depth, string filter,

             bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

             bool? includePathSegment, IExtensionsData extension);

 

+        /// <summary>

+        ///  Gets the set of descendant folder objects contained in the specified folder.

+        /// </summary>

         IList<IObjectInFolderContainer> GetFolderTree(string repositoryId, string folderId, BigInteger? depth, string filter,

             bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

             bool? includePathSegment, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the parent folder(s) for the specified non-folder, fileable object.

+        /// </summary>

         IList<IObjectParentData> GetObjectParents(string repositoryId, string objectId, string filter,

             bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

             bool? includeRelativePathSegment, IExtensionsData extension);

 

-        IObjectData GetFolderParent(string repositoryId, string folderId, string filter, ExtensionsData extension);

+        /// <summary>

+        /// Gets the parent folder object for the specified folder object.

+        /// </summary>

+        IObjectData GetFolderParent(string repositoryId, string folderId, string filter, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the list of documents that are checked out that the user has access to.

+        /// </summary>

         IObjectList GetCheckedOutDocs(string repositoryId, string folderId, string filter, string orderBy,

             bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

             BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

@@ -88,62 +128,126 @@
     /// </summary>

     public interface IObjectService

     {

+        /// <summary>

+        /// Creates a document object of the specified type (given by the  cmis:objectTypeId property) in the (optionally) specified location.

+        /// </summary>

         string CreateDocument(string repositoryId, IProperties properties, string folderId, IContentStream contentStream,

             VersioningState? versioningState, IList<string> policies, IAcl addAces, IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates a document object as a copy of the given source document in the (optionally) specified location.

+        /// </summary>

         string CreateDocumentFromSource(string repositoryId, string sourceId, IProperties properties, string folderId,

             VersioningState? versioningState, IList<string> policies, IAcl addAces, IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates a folder object of the specified type (given by the cmis:objectTypeId property) in the specified location.

+        /// </summary>

         string CreateFolder(string repositoryId, IProperties properties, string folderId, IList<string> policies,

             IAcl addAces, IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates a relationship object of the specified type (given by the cmis:objectTypeId property).

+        /// </summary>

         string CreateRelationship(string repositoryId, IProperties properties, IList<string> policies, IAcl addAces,

             IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates a policy object of the specified type (given by the cmis:objectTypeId property).

+        /// </summary>

         string CreatePolicy(string repositoryId, IProperties properties, string folderId, IList<string> policies,

             IAcl addAces, IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Creates an item object of the specified type (given by the cmis:objectTypeId property).

+        /// </summary>

         string CreateItem(string repositoryId, IProperties properties, string folderId, IList<string> policies,

             IAcl addAces, IAcl removeAces, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the list of allowable actions for an object.

+        /// </summary>

         IAllowableActions GetAllowableActions(string repositoryId, string objectId, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the list of properties for an object.

+        /// </summary>

         IProperties GetProperties(string repositoryId, string objectId, string filter, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the list of associated renditions for the specified object.

+        /// </summary>

+        /// <remarks>

+        /// Only rendition attributes are returned, not rendition stream.

+        /// </remarks>

         IList<IRenditionData> GetRenditions(string repositoryId, string objectId, string renditionFilter,

             BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the specified information for the object specified by ID.

+        /// </summary>

         IObjectData GetObject(string repositoryId, string objectId, string filter, bool? includeAllowableActions,

             IncludeRelationships? includeRelationships, string renditionFilter, bool? includePolicyIds,

             bool? includeAcl, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the specified information for the object specified by path.

+        /// </summary>

         IObjectData GetObjectByPath(string repositoryId, string path, string filter, bool? includeAllowableActions,

             IncludeRelationships? includeRelationships, string renditionFilter, bool? includePolicyIds, bool? includeAcl,

             IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the content stream for the specified document object, or gets a rendition stream

+        /// for a specified rendition of a document or folder object.

+        /// </summary>

         IContentStream GetContentStream(string repositoryId, string objectId, string streamId, BigInteger? offset, BigInteger? length,

             IExtensionsData extension);

 

+        /// <summary>

+        /// Updates properties of the specified object.

+        /// </summary>

         void UpdateProperties(string repositoryId, ref string objectId, ref string changeToken, IProperties properties,

             IExtensionsData extension);

 

+        /// <summary>

+        /// Updates properties and secondary types of one or more objects.

+        /// </summary>

         IList<IBulkUpdateObjectIdAndChangeToken> BulkUpdateProperties(string repositoryId,

                 IList<IBulkUpdateObjectIdAndChangeToken> objectIdAndChangeToken, IProperties properties,

                 IList<string> addSecondaryTypeIds, IList<string> removeSecondaryTypeIds, IExtensionsData extension);

 

+        /// <summary>

+        /// Moves the specified file-able object from one folder to another.

+        /// </summary>

         void MoveObject(string repositoryId, ref string objectId, string targetFolderId, string sourceFolderId,

             IExtensionsData extension);

 

+        /// <summary>

+        /// Deletes the specified object.

+        /// </summary>

         void DeleteObject(string repositoryId, string objectId, bool? allVersions, IExtensionsData extension);

 

+        /// <summary>

+        /// Deletes the specified folder object and all of its child- and descendant-objects.

+        /// </summary>

         IFailedToDeleteData DeleteTree(string repositoryId, string folderId, bool? allVersions, UnfileObject? unfileObjects,

-            bool? continueOnFailure, ExtensionsData extension);

+            bool? continueOnFailure, IExtensionsData extension);

 

+        /// <summary>

+        /// Sets the content stream for the specified document object.

+        /// </summary>

         void SetContentStream(string repositoryId, ref string objectId, bool? overwriteFlag, ref string changeToken,

             IContentStream contentStream, IExtensionsData extension);

 

+        /// <summary>

+        /// Deletes the content stream for the specified document object.

+        /// </summary>

         void DeleteContentStream(string repositoryId, ref string objectId, ref string changeToken, IExtensionsData extension);

 

+        /// <summary>

+        /// Appends the content stream to the content of the document.

+        /// </summary>

         void AppendContentStream(string repositoryId, ref string objectId, bool? isLastChunk, ref string changeToken,

             IContentStream contentStream, IExtensionsData extension);

     }

@@ -153,21 +257,39 @@
     /// </summary>

     public interface IVersioningService

     {

+        /// <summary>

+        /// Create a private working copy of the document.

+        /// </summary>

         void CheckOut(string repositoryId, ref string objectId, IExtensionsData extension, out bool? contentCopied);

 

+        /// <summary>

+        /// Reverses the effect of a check-out.

+        /// </summary>

         void CancelCheckOut(string repositoryId, string objectId, IExtensionsData extension);

 

+        /// <summary>

+        /// Checks-in the private working copy (PWC) document.

+        /// </summary>

         void CheckIn(string repositoryId, ref string objectId, bool? major, IProperties properties,

             IContentStream contentStream, string checkinComment, IList<string> policies, IAcl addAces, IAcl removeAces,

             IExtensionsData extension);

 

+        /// <summary>

+        /// Get the latest document object in the version series.

+        /// </summary>

         IObjectData GetObjectOfLatestVersion(string repositoryId, string objectId, string versionSeriesId, bool? major,

             string filter, bool? includeAllowableActions, IncludeRelationships? includeRelationships,

             string renditionFilter, bool? includePolicyIds, bool? includeAcl, IExtensionsData extension);

 

+        /// <summary>

+        /// Get a subset of the properties for the latest document object in the version series.

+        /// </summary>

         IProperties GetPropertiesOfLatestVersion(string repositoryId, string objectId, string versionSeriesId, bool? major,

             string filter, IExtensionsData extension);

 

+        /// <summary>

+        /// Returns the list of all document objects in the specified version series, sorted by the property "cmis:creationDate" descending.

+        /// </summary>

         IList<IObjectData> GetAllVersions(string repositoryId, string objectId, string versionSeriesId, string filter,

             bool? includeAllowableActions, IExtensionsData extension);

     }

@@ -177,6 +299,9 @@
     /// </summary>

     public interface IRelationshipService

     {

+        /// <summary>

+        /// Gets all or a subset of relationships associated with an independent object.

+        /// </summary>

         IObjectList GetObjectRelationships(string repositoryId, string objectId, bool? includeSubRelationshipTypes,

             RelationshipDirection? relationshipDirection, string typeId, string filter, bool? includeAllowableActions,

             BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

@@ -187,10 +312,16 @@
     /// </summary>

     public interface IDiscoveryService

     {

+        /// <summary>

+        /// Executes a CMIS query statement against the contents of the repository.

+        /// </summary>

         IObjectList Query(string repositoryId, string statement, bool? searchAllVersions,

            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,

            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets a list of content changes.

+        /// </summary>

         IObjectList GetContentChanges(string repositoryId, ref string changeLogToken, bool? includeProperties,

            string filter, bool? includePolicyIds, bool? includeAcl, BigInteger? maxItems, IExtensionsData extension);

     }

@@ -200,8 +331,14 @@
     /// </summary>

     public interface IMultiFilingService

     {

+        /// <summary>

+        /// Adds an existing fileable non-folder object to a folder.

+        /// </summary>

         void AddObjectToFolder(string repositoryId, string objectId, string folderId, bool? allVersions, IExtensionsData extension);

 

+        /// <summary>

+        /// Removes an existing fileable non-folder object from a folder.

+        /// </summary>

         void RemoveObjectFromFolder(string repositoryId, string objectId, string folderId, IExtensionsData extension);

     }

 

@@ -210,8 +347,14 @@
     /// </summary>

     public interface IAclService

     {

+        /// <summary>

+        /// Get the ACL currently applied to the specified object.

+        /// </summary>

         IAcl GetAcl(string repositoryId, string objectId, bool? onlyBasicPermissions, IExtensionsData extension);

 

+        /// <summary>

+        /// Adds or removes the given ACEs to or from the ACL of the object.

+        /// </summary>

         IAcl ApplyAcl(string repositoryId, string objectId, IAcl addAces, IAcl removeAces, AclPropagation? aclPropagation,

             IExtensionsData extension);

     }

@@ -221,10 +364,19 @@
     /// </summary>

     public interface IPolicyService

     {

+        /// <summary>

+        ///  Applies a specified policy to an object.

+        /// </summary>

         void ApplyPolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension);

 

+        /// <summary>

+        /// Removes a specified policy from an object.

+        /// </summary>

         void RemovePolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension);

 

+        /// <summary>

+        /// Gets the list of policies currently applied to the specified object.

+        /// </summary>

         IList<IObjectData> GetAppliedPolicies(string repositoryId, string objectId, string filter, IExtensionsData extension);

     }

 }

diff --git a/PortCMIS/binding/atompub/AtomPubBinding.cs b/PortCMIS/binding/atompub/AtomPubBinding.cs
index 61a824b..5ccf7e6 100644
--- a/PortCMIS/binding/atompub/AtomPubBinding.cs
+++ b/PortCMIS/binding/atompub/AtomPubBinding.cs
@@ -1909,7 +1909,7 @@
             return result;

         }

 

-        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, ExtensionsData extension)

+        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, IExtensionsData extension)

         {

             IObjectData result = null;

 

@@ -2683,7 +2683,7 @@
         }

 

         public IFailedToDeleteData DeleteTree(string repositoryId, string folderId, bool? allVersions, UnfileObject? unfileObjects,

-            bool? continueOnFailure, ExtensionsData extension)

+            bool? continueOnFailure, IExtensionsData extension)

         {

             // find the down links

             string link = LoadLink(repositoryId, folderId, BindingConstants.RelDown, null);

diff --git a/PortCMIS/binding/browser/BrowserBinding.cs b/PortCMIS/binding/browser/BrowserBinding.cs
index c746b55..a3de610 100644
--- a/PortCMIS/binding/browser/BrowserBinding.cs
+++ b/PortCMIS/binding/browser/BrowserBinding.cs
@@ -1263,7 +1263,7 @@
             return JsonConverter.ConvertObjectParents(json, typeCache);

         }

 

-        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, ExtensionsData extension)

+        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, IExtensionsData extension)

         {

             // build URL

             UrlBuilder url = GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorParent);

@@ -1722,7 +1722,7 @@
         }

 

         public IFailedToDeleteData DeleteTree(string repositoryId, string folderId, bool? allVersions, UnfileObject? unfileObjects,

-            bool? continueOnFailure, ExtensionsData extension)

+            bool? continueOnFailure, IExtensionsData extension)

         {

             // build URL

             UrlBuilder url = GetObjectUrl(repositoryId, folderId);

diff --git a/PortCMIS/client/ClientImpl.cs b/PortCMIS/client/ClientImpl.cs
index 59d18b7..59abe28 100644
--- a/PortCMIS/client/ClientImpl.cs
+++ b/PortCMIS/client/ClientImpl.cs
@@ -249,6 +249,7 @@
         /// </value>

         public string RepositoryId { get { return RepositoryInfo.Id; } }

 

+        /// <inheritdoc/>

         public IObjectFactory ObjectFactory { get; protected set; }

 

         /// <summary>

@@ -997,6 +998,7 @@
 

         // create

 

+        /// <inheritdoc/>

         public IObjectId CreateDocument(IDictionary<string, object> properties, IObjectId folderId, IContentStream contentStream,

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

         {

diff --git a/PortCMIS/client/ClientIntf.cs b/PortCMIS/client/ClientIntf.cs
index 060a54f..a6c73ff 100644
--- a/PortCMIS/client/ClientIntf.cs
+++ b/PortCMIS/client/ClientIntf.cs
@@ -24,10 +24,7 @@
 using System;

 using System.Collections.Generic;

 using System.IO;

-using System.Linq;

 using System.Numerics;

-using System.Text;

-using System.Threading.Tasks;

 

 namespace PortCMIS.Client

 {

@@ -108,16 +105,27 @@
     /// </summary>

     /// <remarks>

     /// <para>

-    /// Not all operations might be supported by the connected repository. Either PortCMIS or the repository will 

-    /// throw an exception if an unsupported operation is called. 

-    /// The capabilities of the repository can be discovered by evaluating the repository info 

+    /// CMIS itself is stateless. PortCMIS uses the concept of a session to cache 

+    /// data across calls and to deal with user authentication. The session object is

+    /// also used as entry point to all CMIS operations and objects. Because a

+    /// session is only a client side concept, the session object needs not to be

+    /// closed or released when it's not needed anymore.

+    /// </para>

+    /// <para>

+    /// Not all operations provided by this API might be supported by the connected

+    /// repository. Either PortCMIS or the repository will throw an exception if an

+    /// unsupported operation is called. The capabilities of the repository can be

+    /// discovered by evaluating the repository info 

     /// (see <see cref="RepositoryInfo"/>).

     /// </para>

     /// <para>

-    /// Almost all methods might throw exceptions derived from <see cref="PortCMIS.Exceptions.CmisBaseException"/>!

+    /// Almost all methods might throw exceptions derived from <see cref="PortCMIS.Exceptions.CmisBaseException"/>.

+    /// See the CMIS specification for a list of all operations and their exceptions. Note that

+    /// some incompliant repositories might throw other exception than you expect.

     /// </para>

     /// <para>

-    /// (Please refer to the <a href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/">CMIS specification</a>

+    /// (Please 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>

     /// for details about the domain model, terms, concepts, base types, properties, IDs and query names, 

     /// query language, etc.)

     /// </para>

@@ -413,6 +421,16 @@
         /// <returns>query results</returns>

         /// <cmis>1.0</cmis>

         IItemEnumerable<IQueryResult> Query(string statement, bool searchAllVersions);

+

+        /// <summary>

+        /// Performs a query that returns objects.

+        /// </summary>

+        /// <param name="typeId">a type ID</param>

+        /// <param name="where">WHERE part of the query, may be <c>null</c></param>

+        /// <param name="searchAllVersions">indicates whether all versions should searched or not</param>

+        /// <param name="context">the operation context</param>

+        /// <returns>query results</returns>

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

         IItemEnumerable<ICmisObject> QueryObjects(string typeId, string where, bool searchAllVersions, IOperationContext context);

 

         /// <summary>

@@ -438,33 +456,127 @@
         /// Gets the latest change log token from the repository.

         /// </summary>

         /// <returns>the latest change log token</returns>

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

         string GetLatestChangeLogToken();

+

+        /// <summary>

+        /// Gets the change log.

+        /// </summary>

+        /// <param name="changeLogToken">the change log token, may be <c>null</c></param>

+        /// <param name="includeProperties">indicates whether properties should be included or</param>

+        /// <param name="maxNumItems">max number of changes</param>

+        /// <returns>the change events</returns>

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

         IChangeEvents GetContentChanges(string changeLogToken, bool includeProperties, long maxNumItems);

+

+        /// <summary>

+        /// Gets the change log.

+        /// </summary>

+        /// <param name="changeLogToken">the change log token, may be <c>null</c></param>

+        /// <param name="includeProperties">indicates whether properties should be included or</param>

+        /// <param name="maxNumItems">max number of changes</param>

+        /// <param name="context">the operation context</param>

+        /// <returns>the change events</returns>

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

         IChangeEvents GetContentChanges(string changeLogToken, bool includeProperties, long maxNumItems, IOperationContext context);

 

         // create

 

+        /// <summary>

+        /// Creates a new document.

+        /// </summary>

+        /// <returns>the object ID of the new document</returns>

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

         IObjectId CreateDocument(IDictionary<string, object> properties, IObjectId folderId, IContentStream contentStream,

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

+

+        /// <summary>

+        /// Creates a new document.

+        /// </summary>

+        /// <returns>the object ID of the new document</returns>

         IObjectId CreateDocument(IDictionary<string, object> properties, IObjectId folderId, IContentStream contentStream,

                 VersioningState? versioningState);

+

+        /// <summary>

+        /// Creates a new document from a source document.

+        /// </summary>

+        /// <returns>the object ID of the new document</returns>

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

         IObjectId CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, IObjectId folderId,

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

+

+        /// <summary>

+        /// Creates a new document from a source document.

+        /// </summary>

+        /// <returns>the object ID of the new document</returns>

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

         IObjectId CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, IObjectId folderId,

                 VersioningState? versioningState);

+

+        /// <summary>

+        /// Creates a new folder.

+        /// </summary>

+        /// <returns>the object ID of the new folder</returns>

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

         IObjectId CreateFolder(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies, IList<IAce> addAces,

                 IList<IAce> removeAces);

+

+        /// <summary>

+        /// Creates a new folder.

+        /// </summary>

+        /// <returns>the object ID of the new folder</returns>

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

         IObjectId CreateFolder(IDictionary<string, object> properties, IObjectId folderId);

+

+        /// <summary>

+        /// Creates a new policy.

+        /// </summary>

+        /// <returns>the object ID of the new policy</returns>

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

         IObjectId CreatePolicy(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies, IList<IAce> addAces,

                 IList<IAce> removeAces);

+

+        /// <summary>

+        /// Creates a new policy.

+        /// </summary>

+        /// <returns>the object ID of the new policy</returns>

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

         IObjectId CreatePolicy(IDictionary<string, object> properties, IObjectId folderId);

+

+        /// <summary>

+        /// Creates a new relationship.

+        /// </summary>

+        /// <returns>the object ID of the new relationship</returns>

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

         IObjectId CreateRelationship(IDictionary<string, object> properties, IList<IPolicy> policies, IList<IAce> addAces,

                 IList<IAce> removeAces);

+

+        /// <summary>

+        /// Creates a new relationship.

+        /// </summary>

+        /// <returns>the object ID of the new relationship</returns>

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

         IObjectId CreateRelationship(IDictionary<string, object> properties);

+

+        /// <summary>

+        /// Creates a new item.

+        /// </summary>

+        /// <returns>the object ID of the new item</returns>

+        /// <cmis>1.1</cmis>

         IObjectId CreateItem(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies, IList<IAce> addAces,

             IList<IAce> removeAces);

+

+        /// <summary>

+        /// Creates a new item.

+        /// </summary>

+        /// <returns>the object ID of the new item</returns>

+        /// <cmis>1.1</cmis>

         IObjectId CreateItem(IDictionary<string, object> properties, IObjectId folderId);

 

+        /// <summary>

+        /// Fetches the relationships from or to an object from the repository.

+        /// </summary>

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

         IItemEnumerable<IRelationship> GetRelationships(IObjectId objectId, bool includeSubRelationshipTypes,

                 RelationshipDirection? relationshipDirection, IObjectType type, IOperationContext context);

 

@@ -748,6 +860,9 @@
         int MaxItemsPerPage { get; set; }

     }

 

+    /// <summary>

+    /// A tree node.

+    /// </summary>

     public interface ITree<T>

     {

         /// <value>

@@ -766,6 +881,7 @@
     /// Query Statement.

     /// </summary>

     /// <example>

+    /// <code>

     /// DateTime cal = ...

     /// IFolder folder = ...

     /// 

@@ -785,6 +901,7 @@
     /// qs.SetString(8, "bob", "tom", "lisa"); 

     /// 

     /// string statement = qs.ToQueryString();

+    /// </code>

     /// </example>

     public interface IQueryStatement

     {

@@ -856,12 +973,13 @@
         /// *, ? and - are interpreted as text search operators and are not escaped

         /// on first level. If *, ?, - shall be used as literals, they must be passed

         /// escaped with \*, \? and \- to this method.

-        /// <p>

+        /// <para>

         /// For all statements in a CONTAINS() clause it is required to isolate those

         /// from a query statement. Therefore a second level escaping is performed.

         /// On the second level grammar ", ', - and \ are escaped with a \. See the

         /// spec for further details.

-        /// <p>

+        /// </para>

+        /// <para>

         /// Summary:

         /// <table summary="Escaping Summary">

         /// <tr>

@@ -887,7 +1005,7 @@
         /// <tr>

         /// <td>\</td>

         /// <td>\\</td>

-        /// <td>\\\\<br>

+        /// <td>\\\\<br/>

         /// <em>(for any other character following other than///?-)</em></td>

         /// </tr>

         /// <tr>

@@ -916,6 +1034,7 @@
         /// <td>\\\"</td>

         /// </tr>

         /// </table>

+        /// </para>

         /// </remarks>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

         /// <param name='str'>the CONTAINS string</param>

@@ -939,21 +1058,21 @@
         /// Sets the designated parameter to the given boolean.

         /// </summary>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

-        /// <param name='bool'>the boolean</param>

+        /// <param name='boolean'>the boolean</param>

         void SetBoolean(int parameterIndex, params bool[] boolean);

 

         /// <summary>

         /// Sets the designated parameter to the given DateTime value.

         /// </summary>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

-        /// <param name='cal'>the DateTime value as Calendar object</param>

+        /// <param name='dt'>the DateTime value as Calendar object</param>

         void SetDateTime(int parameterIndex, params DateTime[] dt);

 

         /// <summary>

         /// Sets the designated parameter to the given DateTime value.

         /// </summary>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

-        /// <param name='cal'>the DateTime value in milliseconds from midnight, January 1, 1970 UTC.</param>

+        /// <param name='ms'>the DateTime value in milliseconds from midnight, January 1, 1970 UTC.</param>

         void SetDateTime(int parameterIndex, params long[] ms);

 

         /// <summary>

@@ -961,7 +1080,7 @@
         /// 'TIMESTAMP '.

         /// </summary>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

-        /// <param name='cal'>the DateTime value as Calendar object

+        /// <param name='dt'>the DateTime value as Calendar object</param>

         void SetDateTimeTimestamp(int parameterIndex, params DateTime[] dt);

 

         /// <summary>

@@ -969,7 +1088,7 @@
         /// 'TIMESTAMP '.

         /// </summary>

         /// <param name='parameterIndex'>the parameter index (one-based)</param>

-        /// <param name='cal'>the DateTime value in milliseconds from midnight, January 1, 1970 UTC.</param>

+        /// <param name='ms'>the DateTime value in milliseconds from midnight, January 1, 1970 UTC.</param>

         void SetDateTimeTimestamp(int parameterIndex, params long[] ms);

 

         /// <summary>

@@ -1092,6 +1211,9 @@
     {

     }

 

+    /// <summary>

+    /// Enumerable that allows to skip and page.

+    /// </summary>

     public interface IItemEnumerable<T> : IEnumerable<T>

     {

         /// <summary>

@@ -1750,7 +1872,19 @@
         /// <returns>the object ID of the new created document</returns>

         IObjectId CheckIn(bool major, IDictionary<string, object> properties, IContentStream contentStream, string checkinComment);

 

+        /// <summary>

+        /// Fetches the latest major or minor version of this document.

+        /// </summary>

+        /// <param name="major">indicates if the latest major or the very last version should be returned</param>

+        /// <returns>the latest document object</returns>

         IDocument GetObjectOfLatestVersion(bool major);

+

+        /// <summary>

+        /// Fetches the latest major or minor version of this document with the given operation context.

+        /// </summary>

+        /// <param name="major">indicates if the latest major or the very last version should be returned</param>

+        /// <param name="context">the operation context</param>

+        /// <returns>the latest document object</returns>

         IDocument GetObjectOfLatestVersion(bool major, IOperationContext context);

 

         /// <summary>

@@ -1759,11 +1893,20 @@
         IList<IDocument> GetAllVersions();

 

         /// <summary>

-        /// Gets a list of all versions in this version series using the given <see cref="PortCMIS.Client.IOperationContext"/>.

+        /// Gets a list of all versions in this version series using the given operation context.

         /// </summary>

         IList<IDocument> GetAllVersions(IOperationContext context);

 

+        /// <summary>

+        ///  Creates a copy of this document, including content.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument Copy(IObjectId targetFolderId);

+

+        /// <summary>

+        ///  Creates a copy of this document, including content.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument Copy(IObjectId targetFolderId, IDictionary<string, object> properties, VersioningState? versioningState,

             IList<IPolicy> policies, IList<IAce> addACEs, IList<IAce> removeACEs, IOperationContext context);

     }

@@ -1789,20 +1932,69 @@
     /// </summary>

     public interface IFolder : IFileableCmisObject, IFolderProperties

     {

+        /// <summary>

+        /// Creates a new document in this folder.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument CreateDocument(IDictionary<string, object> properties, IContentStream contentStream, VersioningState? versioningState,

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

+

+        /// <summary>

+        /// Creates a new document in this folder.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument CreateDocument(IDictionary<string, object> properties, IContentStream contentStream, VersioningState? versioningState);

+

+        /// <summary>

+        /// Creates a new document from a source document in this folder.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, VersioningState? versioningState,

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

+

+        /// <summary>

+        /// Creates a new document from a source document in this folder.

+        /// </summary>

+        /// <returns>the new document object</returns>

         IDocument CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, VersioningState? versioningState);

+

+        /// <summary>

+        /// Creates a new subfolder in this folder.

+        /// </summary>

+        /// <returns>the new folder object</returns>

         IFolder CreateFolder(IDictionary<string, object> properties, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces,

                 IOperationContext context);

+

+        /// <summary>

+        /// Creates a new subfolder in this folder.

+        /// </summary>

+        /// <returns>the new folder object</returns>

         IFolder CreateFolder(IDictionary<string, object> properties);

+

+        /// <summary>

+        /// Creates a new policy in this folder.

+        /// </summary>

+        /// <returns>the new policy object</returns>

         IPolicy CreatePolicy(IDictionary<string, object> properties, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces,

                 IOperationContext context);

+

+        /// <summary>

+        /// Creates a new policy in this folder.

+        /// </summary>

+        /// <returns>the new policy object</returns>

         IPolicy CreatePolicy(IDictionary<string, object> properties);

+

+        /// <summary>

+        /// Creates a new item in this folder.

+        /// </summary>

+        /// <returns>the new item object</returns>

         IItem CreateItem(IDictionary<string, object> properties, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces,

             IOperationContext context);

+

+        /// <summary>

+        /// Creates a new item in this folder.

+        /// </summary>

+        /// <returns>the new item object</returns>

         IItem CreateItem(IDictionary<string, object> properties);

 

         /// <summary>

@@ -2033,7 +2225,7 @@
         /// <remarks>

         /// Since repositories are not obligated to add property IDs to their

         /// query result properties, this method might not always work as expected with

-        /// some repositories. Use <see cref="P:this[string]"/> instead.

+        /// some repositories. Use <see cref="this[string]"/> instead.

         /// </remarks>

         IPropertyData GetPropertyById(string propertyId);

 

diff --git a/PortCMIS/client/ClientObjects.cs b/PortCMIS/client/ClientObjects.cs
index 0a2afcf..a1ea256 100644
--- a/PortCMIS/client/ClientObjects.cs
+++ b/PortCMIS/client/ClientObjects.cs
@@ -2060,11 +2060,21 @@
         private IDictionary<string, IPropertyData> propertiesById;

         private IDictionary<string, IPropertyData> propertiesByQueryName;

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

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

+        /// <param name="objectData">the query hit</param>

         public QueryResult(ISession session, IObjectData objectData)

         {

             Initialize(session, objectData);

         }

 

+        /// <summary>

+        /// Initializes the query result object.

+        /// </summary>

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

+        /// <param name="objectData">the query hit</param>

         protected void Initialize(ISession session, IObjectData objectData)

         {

             if (objectData != null)

diff --git a/PortCMIS/client/ClientUtils.cs b/PortCMIS/client/ClientUtils.cs
index 03af80d..2070473 100644
--- a/PortCMIS/client/ClientUtils.cs
+++ b/PortCMIS/client/ClientUtils.cs
@@ -26,7 +26,7 @@
 using System.Numerics;

 using System.Text;

 

-namespace PortCMIS.Client.Impl

+namespace PortCMIS.Client

 {

     /// <summary>

     /// Operation context implementation.

@@ -70,8 +70,6 @@
             orderBy = null;

             cacheEnabled = false;

             maxItemsPerPage = 100;

-

-            GenerateCacheKey();

         }

 

         /// <summary>

@@ -89,8 +87,6 @@
             orderBy = source.OrderBy;

             cacheEnabled = source.CacheEnabled;

             maxItemsPerPage = source.MaxItemsPerPage;

-

-            GenerateCacheKey();

         }

 

         /// <summary>

@@ -110,8 +106,6 @@
             this.orderBy = orderBy;

             this.cacheEnabled = cacheEnabled;

             this.maxItemsPerPage = maxItemsPerPage;

-

-            GenerateCacheKey();

         }

 

         /// <inheritdoc/>

@@ -328,7 +322,14 @@
         /// <inheritdoc/>

         public virtual string CacheKey

         {

-            get { return cacheKey; }

+            get

+            {

+                if (cacheKey == null)

+                {

+                    GenerateCacheKey();

+                }

+                return cacheKey;

+            }

         }

 

         /// <inheritdoc/>

@@ -576,7 +577,7 @@
     /// <summary>

     /// Tree implementation.

     /// </summary>

-    public class Tree<T> : ITree<T>

+    internal class Tree<T> : ITree<T>

     {

         /// <inheritdoc/>

         public T Item { get; set; }

@@ -588,9 +589,13 @@
     /// <summary>

     /// Base class for IItemEnumerable's.

     /// </summary>

-    public abstract class AbstractEnumerable<T> : IItemEnumerable<T>

+    internal abstract class AbstractEnumerable<T> : IItemEnumerable<T>

     {

         private AbstractEnumerator<T> enumerator;

+

+        /// <value>

+        /// Gets the enumerator to creates one if it hasn't been set up, yet. 

+        /// </value>

         protected AbstractEnumerator<T> Enumerator

         {

             get

@@ -600,70 +605,106 @@
             }

         }

 

+        /// <value>

+        /// Gets the delegate that fetches a page.

+        /// </value>

         protected PageFetcher<T> PageFetcher { get; set; }

+

+        /// <value>

+        /// Gets the skip count.

+        /// </value>

         protected BigInteger SkipCount { get; private set; }

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="pageFetcher">>the delegate that fetches a page</param>

         public AbstractEnumerable(PageFetcher<T> pageFetcher) :

             this(0, pageFetcher) { }

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="position">the skip count</param>

+        /// <param name="pageFetcher">>the delegate that fetches a page</param>

         protected AbstractEnumerable(BigInteger position, PageFetcher<T> pageFetcher)

         {

             this.PageFetcher = pageFetcher;

             this.SkipCount = position;

         }

 

+        /// <summary>

+        /// Creates an enumerator.

+        /// </summary>

         protected abstract AbstractEnumerator<T> CreateEnumerator();

 

+        /// <inheritdoc/>

         IEnumerator<T> IEnumerable<T>.GetEnumerator()

         {

             return GetEnumerator();

         }

 

+        /// <inheritdoc/>

         IEnumerator IEnumerable.GetEnumerator()

         {

             return GetEnumerator();

         }

 

+        /// <inheritdoc/>

         public IEnumerator<T> GetEnumerator()

         {

             return Enumerator;

         }

 

+        /// <inheritdoc/>

         public IItemEnumerable<T> SkipTo(BigInteger position)

         {

             return new CollectionEnumerable<T>(position, PageFetcher);

         }

 

+        /// <inheritdoc/>

         public IItemEnumerable<T> GetPage()

         {

             return new CollectionPageEnumerable<T>(SkipCount, PageFetcher);

         }

 

+        /// <inheritdoc/>

         public IItemEnumerable<T> GetPage(int maxNumItems)

         {

             PageFetcher.MaxNumItems = maxNumItems;

             return new CollectionPageEnumerable<T>(SkipCount, PageFetcher);

         }

 

+        /// <inheritdoc/>

         public BigInteger PageNumItems { get { return Enumerator.PageNumItems; } }

 

+        /// <inheritdoc/>

         public bool HasMoreItems { get { return Enumerator.HasMoreItems; } }

 

+        /// <inheritdoc/>

         public BigInteger TotalNumItems { get { return Enumerator.TotalNumItems; } }

     }

 

     /// <summary>

     /// Abstract Enumerator implementation.

     /// </summary>

-    public abstract class AbstractEnumerator<T> : IEnumerator<T>

+    internal abstract class AbstractEnumerator<T> : IEnumerator<T>

     {

         private PageFetcher<T> pageFetcher;

         private PageFetcher<T>.Page<T> page = null;

         private BigInteger? totalNumItems = null;

         private bool? hasMoreItems = null;

 

+        /// <summary>

+        /// The current element.

+        /// </summary>

         protected T current;

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="skipCount">the skip count</param>

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public AbstractEnumerator(BigInteger skipCount, PageFetcher<T> pageFetcher)

         {

             this.SkipCount = skipCount;

@@ -702,12 +743,24 @@
         {

         }

 

+        /// <values>

+        /// Gets the skip count.

+        /// </values>

         public BigInteger SkipCount { get; protected set; }

 

+        /// <values>

+        /// Gets the skip offset.

+        /// </values>

         public int SkipOffset { get; protected set; }

 

+        /// <values>

+        /// Gets the current position.

+        /// </values>

         public BigInteger Position { get { return SkipCount + SkipOffset; } }

 

+        /// <values>

+        /// Gets the number of items of the current page.

+        /// </values>

         public BigInteger PageNumItems

         {

             get

@@ -725,6 +778,9 @@
             }

         }

 

+        /// <values>

+        /// Gets the total number of items.

+        /// </values>

         public BigInteger TotalNumItems

         {

             get

@@ -742,6 +798,9 @@
             }

         }

 

+        /// <values>

+        /// Gets whether there are more items or not.

+        /// </values>

         public bool HasMoreItems

         {

             get

@@ -762,11 +821,19 @@
             }

         }

 

+        /// <summary>

+        /// Increments the skip offset.

+        /// </summary>

+        /// <returns>the new offset</returns>

         protected int IncrementSkipOffset()

         {

             return SkipOffset++;

         }

 

+        /// <summary>

+        /// Returns the current page.

+        /// </summary>

+        /// <returns></returns>

         protected PageFetcher<T>.Page<T> GetCurrentPage()

         {

             if (page == null)

@@ -776,6 +843,10 @@
             return page;

         }

 

+        /// <summary>

+        /// Fetches the next page.

+        /// </summary>

+        /// <returns>the next page</returns>

         protected PageFetcher<T>.Page<T> IncrementPage()

         {

             SkipCount += SkipOffset;

@@ -790,27 +861,55 @@
     /// <summary>

     /// Page fetcher.

     /// </summary>

-    public class PageFetcher<T>

+    internal class PageFetcher<T>

     {

+        /// <summary>

+        /// A delegate that fetches a page.

+        /// </summary>

+        /// <param name="maxNumItems">max number of items</param>

+        /// <param name="skipCount">the skip count</param>

+        /// <returns>a page</returns>

         public delegate Page<T> FetchPage(BigInteger maxNumItems, BigInteger skipCount);

 

         private FetchPage fetchPageDelegate;

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="maxNumItems">max number of items</param>

+        /// <param name="fetchPageDelegate">the delegate that fetches a page</param>

         public PageFetcher(BigInteger maxNumItems, FetchPage fetchPageDelegate)

         {

             MaxNumItems = maxNumItems;

             this.fetchPageDelegate = fetchPageDelegate;

         }

 

+        /// <value>

+        /// Gets the max number of items.

+        /// </value>

         public BigInteger MaxNumItems { get; set; }

 

+        /// <summary>

+        /// Fetches the next page.

+        /// </summary>

+        /// <param name="skipCount">the skip count</param>

+        /// <returns>the next page</returns>

         public Page<T> FetchNextPage(BigInteger skipCount)

         {

             return fetchPageDelegate(MaxNumItems, skipCount);

         }

 

+        /// <summary>

+        /// A page.

+        /// </summary>

         public class Page<P>

         {

+            /// <summary>

+            /// Constructor.

+            /// </summary>

+            /// <param name="items">list of items</param>

+            /// <param name="totalNumItems">total number of items, if known</param>

+            /// <param name="hasMoreItems">a flag whether there are more items, if known</param>

             public Page(IList<P> items, BigInteger? totalNumItems, bool? hasMoreItems)

             {

                 Items = items;

@@ -818,8 +917,19 @@
                 HasMoreItems = hasMoreItems;

             }

 

+            /// <values>

+            /// Gets the items of the page.

+            /// </values>

             public IList<P> Items { get; private set; }

+

+            /// <values>

+            /// Gets the total number of items, if known.

+            /// </values>

             public BigInteger? TotalNumItems { get; private set; }

+

+            /// <values>

+            /// Gets whether there are more items or not, if known.

+            /// </values>

             public bool? HasMoreItems { get; private set; }

         }

     }

@@ -827,14 +937,24 @@
     /// <summary>

     /// CMIS Collection Enumerable.

     /// </summary>

-    public class CollectionEnumerable<T> : AbstractEnumerable<T>

+    internal class CollectionEnumerable<T> : AbstractEnumerable<T>

     {

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionEnumerable(PageFetcher<T> pageFetcher) :

             this(0, pageFetcher) { }

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

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

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionEnumerable(BigInteger position, PageFetcher<T> pageFetcher) :

             base(position, pageFetcher) { }

 

+        /// <inheritdoc/>

         protected override AbstractEnumerator<T> CreateEnumerator()

         {

             return new CollectionEnumerator<T>(SkipCount, PageFetcher);

@@ -844,11 +964,20 @@
     /// <summary>

     /// Enumerator for iterating over all items in a CMIS Collection.

     /// </summary>

-    public class CollectionEnumerator<T> : AbstractEnumerator<T>

+    internal class CollectionEnumerator<T> : AbstractEnumerator<T>

     {

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="skipCount">the skip count</param>

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionEnumerator(BigInteger skipCount, PageFetcher<T> pageFetcher) :

             base(skipCount, pageFetcher) { }

 

+        /// <summary>

+        /// Move to the next items.

+        /// </summary>

+        /// <returns><c>true</c> if there is a next item, <c>false</c> otherwise</returns>

         public override bool MoveNext()

         {

             PageFetcher<T>.Page<T> page = GetCurrentPage();

@@ -888,14 +1017,24 @@
     /// <summary>

     /// Enumerable for a CMIS Collection Page.

     /// </summary>

-    public class CollectionPageEnumerable<T> : AbstractEnumerable<T>

+    internal class CollectionPageEnumerable<T> : AbstractEnumerable<T>

     {

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionPageEnumerable(PageFetcher<T> pageFetcher) :

             this(0, pageFetcher) { }

 

+        /// <summary>

+        /// Constructor.

+        /// </summary>

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

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionPageEnumerable(BigInteger position, PageFetcher<T> pageFetcher) :

             base(position, pageFetcher) { }

 

+        /// <inheritdoc/>

         protected override AbstractEnumerator<T> CreateEnumerator()

         {

             return new CollectionPageEnumerator<T>(SkipCount, PageFetcher);

@@ -905,11 +1044,20 @@
     /// <summary>

     /// Enumerator for iterating over a page of items in a CMIS Collection.

     /// </summary>

-    public class CollectionPageEnumerator<T> : AbstractEnumerator<T>

+    internal class CollectionPageEnumerator<T> : AbstractEnumerator<T>

     {

+        /// <summary>

+        /// Constructor.

+        /// </summary>

+        /// <param name="skipCount">the skip count</param>

+        /// <param name="pageFetcher">the delegate that fetches a page</param>

         public CollectionPageEnumerator(BigInteger skipCount, PageFetcher<T> pageFetcher) :

             base(skipCount, pageFetcher) { }

 

+        /// <summary>

+        /// Move to the next items.

+        /// </summary>

+        /// <returns><c>true</c> if there is a next item, <c>false</c> otherwise</returns>

         public override bool MoveNext()

         {

             PageFetcher<T>.Page<T> page = GetCurrentPage();

diff --git a/PortCMIS/client/SessionParameter.cs b/PortCMIS/client/SessionParameter.cs
index fa96d80..2d6080f 100644
--- a/PortCMIS/client/SessionParameter.cs
+++ b/PortCMIS/client/SessionParameter.cs
@@ -87,6 +87,9 @@
         /// <summary>CSRF HTTP header</summary>

         public const string CsrfHeader = "org.apache.chemistry.portcmis.binding.csrfheader";

 

+        /// <summary>User agent</summary>

+        public const string UserAgent = "org.apache.chemistry.portcmis.binding.useragent";

+

         // ---- binding caches ----

 

         /// <summary>Size of the repositories cache</summary>

diff --git a/PortCMIS/client/SessionParameterDefaults.cs b/PortCMIS/client/SessionParameterDefaults.cs
index e781791..b465754 100644
--- a/PortCMIS/client/SessionParameterDefaults.cs
+++ b/PortCMIS/client/SessionParameterDefaults.cs
@@ -17,12 +17,6 @@
 * under the License.

 */

 

-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-using System.Threading.Tasks;

-

 namespace PortCMIS.Client

 {

     /// <summary>

diff --git a/PortCMIS/const/ClientVersion.cs b/PortCMIS/const/ClientVersion.cs
new file mode 100644
index 0000000..699e796
--- /dev/null
+++ b/PortCMIS/const/ClientVersion.cs
@@ -0,0 +1,23 @@
+using System;

+using System.Collections.Generic;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace PortCMIS

+{

+    /// <summary>

+    /// PortCMIS client version.

+    /// </summary>

+    public class ClientVersion

+    {

+        /// <summary>PortCMIS user agent name</summary>

+        public const string UserAgentName = "ApacheChemistryPortCMIS";

+

+        /// <summary>PortCMIS version</summary>

+        public const string Version = "0.1";

+

+        /// <summary>PortCMIS user agent name</summary>

+        public const string UserAgent = UserAgentName + "/" + Version;

+    }

+}
\ No newline at end of file
diff --git a/PortCMISTests/ContentStreamTest.cs b/PortCMISTests/ContentStreamTest.cs
index ee1648f..ae60763 100644
--- a/PortCMISTests/ContentStreamTest.cs
+++ b/PortCMISTests/ContentStreamTest.cs
@@ -1,4 +1,22 @@
-using System;

+/*

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

+*/

+

 using Microsoft.VisualStudio.TestTools.UnitTesting;

 using PortCMIS.Client.Impl;

 

diff --git a/PortCMISTests/JsonTest.cs b/PortCMISTests/JsonTest.cs
index b904852..e6b9b53 100644
--- a/PortCMISTests/JsonTest.cs
+++ b/PortCMISTests/JsonTest.cs
@@ -1,7 +1,26 @@
-using System;

+/*

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

+*/

+

 using Microsoft.VisualStudio.TestTools.UnitTesting;

-using System.IO;

 using PortCMIS.Binding.Browser.Json;

+using System;

+using System.IO;

 using System.Numerics;

 

 namespace PortCMISTests

diff --git a/PortCMISTests/QueryStatementTest.cs b/PortCMISTests/QueryStatementTest.cs
index e955521..2652b17 100644
--- a/PortCMISTests/QueryStatementTest.cs
+++ b/PortCMISTests/QueryStatementTest.cs
@@ -1,4 +1,23 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;

+/*

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

+*/

+

+using Microsoft.VisualStudio.TestTools.UnitTesting;

 using PortCMIS.Binding;

 using PortCMIS.Client;

 using PortCMIS.Client.Impl;

diff --git a/PortCMISTests/SimpleCmisTest.cs b/PortCMISTests/SimpleCmisTest.cs
index 11568af..d603743 100644
--- a/PortCMISTests/SimpleCmisTest.cs
+++ b/PortCMISTests/SimpleCmisTest.cs
@@ -1,17 +1,34 @@
-using System;

+/*

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

+*/

+

 using Microsoft.VisualStudio.TestTools.UnitTesting;

-using PortCMIS.Client.Impl;

-using System.Collections.Generic;

 using PortCMIS;

 using PortCMIS.Client;

-using PortCMIS.Exceptions;

+using PortCMIS.Client.Impl;

 using PortCMIS.Data;

-using System.IO;

 using PortCMIS.Enums;

-using System.Text;

+using PortCMIS.Exceptions;

 using PortCMIS.Utils;

 using PortCMISTests.Framework;

+using System.Collections.Generic;

 using System.Linq;

+using System.Text;

 

 namespace PortCMISTests

 {

diff --git a/PortCMISTests/framework/DefaultTestValues.cs b/PortCMISTests/framework/DefaultTestValues.cs
index a6d3f8c..14a3476 100644
--- a/PortCMISTests/framework/DefaultTestValues.cs
+++ b/PortCMISTests/framework/DefaultTestValues.cs
@@ -19,11 +19,7 @@
 

 using PortCMIS;

 using PortCMIS.Client;

-using System;

 using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-using System.Threading.Tasks;

 

 namespace PortCMISTests.Framework

 {

diff --git a/PortCMISTests/framework/TestFramework.cs b/PortCMISTests/framework/TestFramework.cs
index 3970878..66e9652 100644
--- a/PortCMISTests/framework/TestFramework.cs
+++ b/PortCMISTests/framework/TestFramework.cs
@@ -23,13 +23,9 @@
 using PortCMIS.Client.Impl;

 using PortCMIS.Data;

 using PortCMIS.Enums;

-using PortCMIS.Exceptions;

-using System;

 using System.Collections.Generic;

 using System.IO;

-using System.Linq;

 using System.Text;

-using System.Threading.Tasks;

 

 namespace PortCMISTests.Framework

 {

diff --git a/PortCMISWin/binding/WindowsBindingIntf.cs b/PortCMISWin/binding/WindowsBindingIntf.cs
index b447104..3502510 100644
--- a/PortCMISWin/binding/WindowsBindingIntf.cs
+++ b/PortCMISWin/binding/WindowsBindingIntf.cs
@@ -26,6 +26,9 @@
 

 namespace PortCMIS.Binding

 {

+    /// <summary>

+    /// Authentication provider interface for the Windows HTTP client.

+    /// </summary>

     public interface IWindowsAuthenticationProvider : IAuthenticationProvider

     {

         void PrepareHttpClientFilter(HttpBaseProtocolFilter httpClientFilter);

@@ -33,6 +36,9 @@
         void HandleResponse(HttpResponseMessage httpResponseMessage);

     }

 

+    /// <summary>

+    /// Base implementation of a Windows authentication provider.

+    /// </summary>

     public abstract class AbstractWindowsAuthenticationProvider : IWindowsAuthenticationProvider

     {

         public IBindingSession Session { get; set; }

@@ -63,6 +69,9 @@
         }

     }

 

+    /// <summary>

+    /// Standard Authentication Provider for Windows.

+    /// </summary>

     public class StandardWindowsAuthenticationProvider : AbstractWindowsAuthenticationProvider

     {

         public string BearerToken { get { return Session.GetValue(SessionParameter.OAuthBearerToken) as string; } }

diff --git a/PortCMISWin/binding/WindowsHttp.cs b/PortCMISWin/binding/WindowsHttp.cs
index 3b89030..3bc588c 100644
--- a/PortCMISWin/binding/WindowsHttp.cs
+++ b/PortCMISWin/binding/WindowsHttp.cs
@@ -36,6 +36,9 @@
 

 namespace PortCMIS.Binding.Http

 {

+    /// <summary>

+    /// Windows HTTP invoker.

+    /// </summary>

     public class WindowsHttpInvoker : IHttpInvoker

     {

         private const string InvokerHttpClient = "org.apache.chemistry.portcmis.invoker.httpclient";

@@ -122,7 +125,10 @@
             HttpRequestMessage request = new HttpRequestMessage(method, new Uri(url.ToString()));

 

             // set additional headers

-            request.Headers.UserAgent.Add(new HttpProductInfoHeaderValue("ApacheChemistryPortCMIS", "0.1"));

+

+            string userAgent = session.GetValue(SessionParameter.UserAgent) as string;

+            request.Headers.UserAgent.Add(HttpProductInfoHeaderValue.Parse(userAgent ?? ClientVersion.UserAgentName));

+

             if (headers != null)

             {

                 foreach (KeyValuePair<string, string> header in headers)