- more client layer code

git-svn-id: https://svn.apache.org/repos/asf/incubator/chemistry/dotcmis/trunk@1063802 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/DotCMIS/DotCMIS.csproj b/DotCMIS/DotCMIS.csproj
index 6aef5f1..a8f17c6 100644
--- a/DotCMIS/DotCMIS.csproj
+++ b/DotCMIS/DotCMIS.csproj
@@ -56,6 +56,7 @@
     <Compile Include="client\client-caches.cs" />

     <Compile Include="client\client-intf.cs" />

     <Compile Include="client\client-impl.cs" />

+    <Compile Include="client\client-objects.cs" />

     <Compile Include="const.cs" />

     <Compile Include="data\data-impl.cs" />

     <Compile Include="data\data-intf.cs" />

diff --git a/DotCMIS/binding/binding-intf.cs b/DotCMIS/binding/binding-intf.cs
index 4efef7c..9b38241 100644
--- a/DotCMIS/binding/binding-intf.cs
+++ b/DotCMIS/binding/binding-intf.cs
@@ -30,38 +30,24 @@
     public interface ICmisBinding

     {

         IRepositoryService GetRepositoryService();

-

         INavigationService GetNavigationService();

-

         IObjectService GetObjectService();

-

         IVersioningService GetVersioningService();

-

         IRelationshipService GetRelationshipService();

-

         IDiscoveryService GetDiscoveryService();

-

         IMultiFilingService GetMultiFilingService();

-

         IAclService GetAclService();

-

         IPolicyService GetPolicyService();

-

         IBindingsObjectFactory GetObjectFactory();

-

         void ClearAllCaches();

-

         void ClearRepositoryCache(string repositoryId);

-

         void Close();

     }

 

     public interface IBindingSession

     {

         object GetValue(string key);

-

         object GetValue(string key, object defValue);

-

         int GetValue(string key, int defValue);

     }

 

diff --git a/DotCMIS/client/client-impl.cs b/DotCMIS/client/client-impl.cs
index 42fa223..da9c2fe 100644
--- a/DotCMIS/client/client-impl.cs
+++ b/DotCMIS/client/client-impl.cs
@@ -25,6 +25,7 @@
 using DotCMIS.Exceptions;

 using System.Threading;

 using DotCMIS.Enums;

+using DotCMIS.Data.Extensions;

 

 namespace DotCMIS.Client

 {

@@ -463,6 +464,22 @@
             GenerateCacheKey();

         }

 

+        public OperationContext(IOperationContext source)

+        {

+            filter = new HashSet<string>(source.Filter);

+            includeAcls = source.IncludeAcls;

+            includeAllowableActions = source.IncludeAllowableActions;

+            includePolicies = source.IncludePolicies;

+            includeRelationships = source.IncludeRelationships;

+            renditionFilter = new HashSet<string>(source.RenditionFilter);

+            includePathSegments = source.IncludePathSegments;

+            orderBy = source.OrderBy;

+            cacheEnabled = source.CacheEnabled;

+            maxItemsPerPage = source.MaxItemsPerPage;

+

+            GenerateCacheKey();

+        }

+

         public OperationContext(HashSet<string> filter, bool includeAcls, bool includeAllowableActions,

             bool includePolicies, IncludeRelationshipsFlag includeRelationships, HashSet<string> renditionFilter,

             bool includePathSegments, String orderBy, bool cacheEnabled, int maxItemsPerPage)

diff --git a/DotCMIS/client/client-intf.cs b/DotCMIS/client/client-intf.cs
index e7612b1..9bc7d8d 100644
--- a/DotCMIS/client/client-intf.cs
+++ b/DotCMIS/client/client-intf.cs
@@ -18,12 +18,11 @@
  */

 using System;

 using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-using DotCMIS.Data;

-using DotCMIS.Enums;

-using DotCMIS.Data.Extensions;

 using DotCMIS.Binding;

+using DotCMIS.Data;

+using DotCMIS.Data.Extensions;

+using DotCMIS.Enums;

+using System.IO;

 

 namespace DotCMIS.Client

 {

@@ -49,7 +48,7 @@
         IOperationContext DefaultContext { get; set; }

         IOperationContext CreateOperationContext();

         IOperationContext CreateOperationContext(HashSet<string> filter, bool includeAcls, bool includeAllowableActions, bool includePolicies,

-            IncludeRelationshipsFlag includeRelationships, HashSet<string> renditionFilter, bool includePathSegments, string orderBy, 

+            IncludeRelationshipsFlag includeRelationships, HashSet<string> renditionFilter, bool includePathSegments, string orderBy,

             bool cacheEnabled, int maxItemsPerPage);

         IObjectId CreateObjectId(string id);

 

@@ -114,7 +113,41 @@
         void RemovePolicy(IObjectId objectId, IObjectId policyIds);

     }

 

-    public interface IObjectFactory { }

+    public interface IObjectFactory

+    {

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

+

+        // ACL and ACE

+        IAcl ConvertAces(IList<IAce> aces);

+        IAcl CreateAcl(IList<IAce> aces);

+        IAce CreateAce(string principal, List<string> permissions);

+

+        // policies

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

+

+        // renditions

+        IRendition ConvertRendition(string objectId, IRenditionData rendition);

+

+        // content stream

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

+        IContentStream ConvertContentStream(IContentStream contentStream);

+

+        // types

+        IObjectType ConvertTypeDefinition(ITypeDefinition typeDefinition);

+        IObjectType GetTypeFromObjectData(IObjectData objectData);

+

+        // properties

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

+        IDictionary<string, IProperty> ConvertProperties(IObjectType objectType, IProperties properties);

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

+        IList<IPropertyData> ConvertQueryProperties(IProperties properties);

+

+        // objects

+        ICmisObject ConvertObject(IObjectData objectData, IOperationContext context);

+        IQueryResult ConvertQueryResult(IObjectData objectData);

+        IChangeEvent ConvertChangeEvent(IObjectData objectData);

+        IChangeEvents ConvertChangeEvents(String changeLogToken, IObjectList objectList);

+    }

 

     public interface IOperationContext

     {

@@ -175,23 +208,23 @@
         bool IsMultiValued { get; }

         PropertyType PropertyType { get; }

         PropertyDefinition PropertyDefinition { get; }

-        V GetValue<V>();

-        string GetValueAsString();

-        string GetValuesAsString();

+        object Value { get; }

+        string ValueAsString { get; }

+        string ValuesAsString { get; }

     }

 

     public interface ICmisObjectProperties

     {

         IList<IProperty> Properties { get; }

-        IProperty GetProperty(string id);

-        T GetPropertyValue<T>(string id);

+        IProperty this[string propertyId] { get; }

+        object GetPropertyValue(string propertyId);

 

         // convenience accessors

         string Name { get; }

         string CreatedBy { get; }

-        DateTime CreationDate { get; }

+        DateTime? CreationDate { get; }

         string LastModifiedBy { get; }

-        DateTime LastModificationDate { get; }

+        DateTime? LastModificationDate { get; }

         BaseTypeId BaseTypeId { get; }

         IObjectType BaseType { get; }

         IObjectType Type { get; }

@@ -207,9 +240,9 @@
     public interface ICmisObject : IObjectId, ICmisObjectProperties

     {

         // object

-        IAllowableActions GetAllowableActions();

-        IList<IRelationship> GetRelationships();

-        IAcl GetAcl();

+        IAllowableActions AllowableActions { get; }

+        IList<IRelationship> Relationships { get; }

+        IAcl Acl { get; }

 

         // object service

         void Delete(bool allVersions);

@@ -217,22 +250,22 @@
         IObjectId UpdateProperties(IDictionary<string, object> properties, bool refresh);

 

         // renditions

-        IList<IRendition> GetRenditions();

+        IList<IRendition> Renditions { get; }

 

         // policy service

         void ApplyPolicy(IObjectId policyId);

-        void RemovePolicy(IObjectId policyIds);

-        IList<IPolicy> GetPolicies();

+        void RemovePolicy(IObjectId policyId);

+        IList<IPolicy> Policies { get; }

 

         // ACL service

-        IAcl applyAcl(IList<IAce> AddAces, IList<IAce> removeAces, AclPropagation? aclPropagation);

-        IAcl addAcl(IList<IAce> AddAces, AclPropagation? aclPropagation);

-        IAcl removeAcl(IList<IAce> RemoveAces, AclPropagation? aclPropagation);

+        IAcl ApplyAcl(IList<IAce> AddAces, IList<IAce> removeAces, AclPropagation? aclPropagation);

+        IAcl AddAcl(IList<IAce> AddAces, AclPropagation? aclPropagation);

+        IAcl RemoveAcl(IList<IAce> RemoveAces, AclPropagation? aclPropagation);

 

         // extensions

         IList<ICmisExtensionElement> GetExtensions(ExtensionLevel level);

 

-        long GetRefreshTimestamp();

+        DateTime RefreshTimestamp { get; }

         void Refresh();

         void RefreshIfOld(long durationInMillis);

     }

@@ -352,6 +385,10 @@
     {

     }

 

+    public interface IChangeEvent

+    {

+    }

+

     public interface IChangeEvents

     {

     }

diff --git a/DotCMIS/client/client-objects.cs b/DotCMIS/client/client-objects.cs
new file mode 100644
index 0000000..c77d8bb
--- /dev/null
+++ b/DotCMIS/client/client-objects.cs
@@ -0,0 +1,558 @@
+/*

+ * 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 System;

+using System.Collections.Generic;

+using System.Linq;

+using System.Text;

+using System.Threading;

+using DotCMIS.Binding;

+using DotCMIS.Client;

+using DotCMIS.Data;

+using DotCMIS.Data.Extensions;

+using DotCMIS.Enums;

+using DotCMIS.Exceptions;

+

+namespace DotCMIS.Client

+{

+    internal abstract class AbstractCmisObject : ICmisObject

+    {

+        protected ISession Session { get; private set; }

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

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

+

+        private IObjectType objectType;

+        protected IObjectType ObjectType

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return objectType;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        protected string ObjectId

+        {

+            get

+            {

+                string objectId = Id;

+                if (objectId == null)

+                {

+                    throw new CmisRuntimeException("Object Id is unknown!");

+                }

+

+                return objectId;

+            }

+        }

+

+        protected IOperationContext CreationContext { get; private set; }

+

+        private IDictionary<string, IProperty> properties;

+        private IAllowableActions allowableActions;

+        private IList<IRendition> renditions;

+        private IAcl acl;

+        private IList<IPolicy> policies;

+        private IList<IRelationship> relationships;

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

+

+

+        private object objectLock = new object();

+

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

+        {

+            if (session == null)

+            {

+                throw new ArgumentNullException("session");

+            }

+

+            if (objectType == null)

+            {

+                throw new ArgumentNullException("objectType");

+            }

+

+            if (objectType.PropertyDefintions == null || objectType.PropertyDefintions.Count < 9)

+            {

+                // there must be at least the 9 standard properties that all objects have

+                throw new ArgumentException("Object type must have property defintions!");

+            }

+

+            this.Session = session;

+            this.objectType = objectType;

+            this.extensions = new Dictionary<ExtensionLevel, IList<ICmisExtensionElement>>();

+            this.CreationContext = new OperationContext(context);

+            this.RefreshTimestamp = DateTime.UtcNow;

+

+

+            IObjectFactory of = Session.ObjectFactory;

+

+            if (objectData != null)

+            {

+                // handle properties

+                if (objectData.Properties != null)

+                {

+                    properties = of.ConvertProperties(objectType, objectData.Properties);

+                    extensions[ExtensionLevel.Properties] = objectData.Properties.Extensions;

+                }

+

+                // handle allowable actions

+                if (objectData.AllowableActions != null)

+                {

+                    allowableActions = objectData.AllowableActions;

+                    extensions[ExtensionLevel.AllowableActions] = objectData.AllowableActions.Extensions;

+                }

+

+                // handle renditions

+                if (objectData.Renditions != null)

+                {

+                    renditions = new List<IRendition>();

+                    foreach (IRenditionData rd in objectData.Renditions)

+                    {

+                        renditions.Add(of.ConvertRendition(Id, rd));

+                    }

+                }

+

+                // handle ACL

+                if (objectData.Acl != null)

+                {

+                    acl = objectData.Acl;

+                    extensions[ExtensionLevel.Acl] = objectData.Acl.Extensions;

+                }

+

+                // handle policies

+                if (objectData.PolicyIds != null && objectData.PolicyIds.PolicyIds != null)

+                {

+                    policies = new List<IPolicy>();

+                    foreach (string pid in objectData.PolicyIds.PolicyIds)

+                    {

+                        ICmisObject policy = Session.GetObject(Session.CreateObjectId(pid));

+                        if (policy is IPolicy)

+                        {

+                            policies.Add((IPolicy)policy);

+                        }

+                    }

+                    extensions[ExtensionLevel.Policies] = objectData.PolicyIds.Extensions;

+                }

+

+                // handle relationships

+                if (objectData.Relationships != null)

+                {

+                    relationships = new List<IRelationship>();

+                    foreach (IObjectData rod in objectData.Relationships)

+                    {

+                        ICmisObject relationship = of.ConvertObject(rod, CreationContext);

+                        if (relationship is IRelationship)

+                        {

+                            relationships.Add((IRelationship)relationship);

+                        }

+                    }

+                }

+

+                extensions[ExtensionLevel.Object] = objectData.Extensions;

+            }

+        }

+

+        protected string GetPropertyQueryName(string propertyId)

+        {

+            Lock();

+            try

+            {

+                IPropertyDefinition propDef = objectType[propertyId];

+                if (propDef == null)

+                {

+                    return null;

+                }

+

+                return propDef.QueryName;

+            }

+            finally

+            {

+                Unlock();

+            }

+        }

+

+        // --- object ---

+

+        public void Delete(bool allVersions)

+        {

+            Lock();

+            try

+            {

+                Binding.GetObjectService().DeleteObject(RepositoryId, ObjectId, allVersions, null);

+            }

+            finally

+            {

+                Unlock();

+            }

+        }

+

+        public ICmisObject UpdateProperties(IDictionary<string, object> properties)

+        {

+            IObjectId objectId = UpdateProperties(properties, true);

+            if (objectId == null)

+            {

+                return null;

+            }

+

+            if (ObjectId != objectId.Id)

+            {

+                return Session.GetObject(objectId, CreationContext);

+            }

+

+            return this;

+        }

+

+        public IObjectId UpdateProperties(IDictionary<String, object> properties, bool refresh)

+        {

+            if (properties == null || properties.Count == 0)

+            {

+                throw new ArgumentException("Properties must not be empty!");

+            }

+

+            string newObjectId = null;

+

+            Lock();

+            try

+            {

+                string objectId = ObjectId;

+                string changeToken = ChangeToken;

+

+                HashSet<Updatability> updatebility = new HashSet<Updatability>();

+                updatebility.Add(Updatability.ReadWrite);

+

+                // check if checked out

+                bool? isCheckedOut = GetPropertyValue(PropertyIds.IsVersionSeriesCheckedOut) as bool?;

+                if (isCheckedOut.HasValue && isCheckedOut.Value)

+                {

+                    updatebility.Add(Updatability.WhenCheckedOut);

+                }

+

+                // it's time to update

+                Binding.GetObjectService().UpdateProperties(RepositoryId, ref objectId, ref changeToken,

+                        Session.ObjectFactory.ConvertProperties(properties, this.objectType, updatebility), null);

+

+                newObjectId = objectId;

+            }

+            finally

+            {

+                Unlock();

+            }

+

+            if (refresh)

+            {

+                Refresh();

+            }

+

+            if (newObjectId == null)

+            {

+                return null;

+            }

+

+            return Session.CreateObjectId(newObjectId);

+        }

+

+        // --- properties ---

+

+        public IObjectType BaseType { get { return Session.GetTypeDefinition(BaseTypeId.GetCmisValue()); } }

+

+        public BaseTypeId BaseTypeId

+        {

+            get

+            {

+                string baseType = GetPropertyValue(PropertyIds.BaseTypeId) as string;

+                if (baseType == null) { throw new CmisRuntimeException("Base type not set!"); }

+

+                return baseType.GetCmisEnum<BaseTypeId>();

+            }

+        }

+

+        public string Id { get { return GetPropertyValue(PropertyIds.ObjectId) as string; } }

+

+        public string Name { get { return GetPropertyValue(PropertyIds.Name) as string; } }

+

+        public string CreatedBy { get { return GetPropertyValue(PropertyIds.CreatedBy) as string; } }

+

+        public DateTime? CreationDate { get { return GetPropertyValue(PropertyIds.CreationDate) as DateTime?; } }

+

+        public string LastModifiedBy { get { return GetPropertyValue(PropertyIds.LastModifiedBy) as string; } }

+

+        public DateTime? LastModificationDate { get { return GetPropertyValue(PropertyIds.LastModificationDate) as DateTime?; } }

+

+        public string ChangeToken { get { return GetPropertyValue(PropertyIds.ChangeToken) as string; } }

+

+        public IObjectType Type { get { return ObjectType; } }

+

+        public IList<IProperty> Properties

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return new List<IProperty>(properties.Values);

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        public IProperty this[string propertyId]

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    IProperty property;

+                    if (properties.TryGetValue(propertyId, out property))

+                    {

+                        return property;

+                    }

+                    return null;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        public object GetPropertyValue(string propertyId)

+        {

+            IProperty property = this[propertyId];

+            if (property == null) { return null; }

+

+            return property.Value;

+        }

+

+        // --- allowable actions ---

+

+        public IAllowableActions AllowableActions

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return allowableActions;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        // --- renditions ---

+

+        public IList<IRendition> Renditions

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return renditions;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        // --- ACL ---

+

+        public IAcl getAcl(bool onlyBasicPermissions)

+        {

+            return Binding.GetAclService().GetAcl(RepositoryId, ObjectId, onlyBasicPermissions, null);

+        }

+

+        public IAcl ApplyAcl(IList<IAce> addAces, IList<IAce> removeAces, AclPropagation? aclPropagation)

+        {

+            IAcl result = Session.ApplyAcl(this, addAces, removeAces, aclPropagation);

+

+            Refresh();

+

+            return result;

+        }

+

+        public IAcl AddAcl(IList<IAce> addAces, AclPropagation? aclPropagation)

+        {

+            return ApplyAcl(addAces, null, aclPropagation);

+        }

+

+        public IAcl RemoveAcl(IList<IAce> removeAces, AclPropagation? aclPropagation)

+        {

+            return ApplyAcl(null, removeAces, aclPropagation);

+        }

+

+        public IAcl Acl

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return acl;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        // --- policies ---

+

+        public void ApplyPolicy(IObjectId policyId)

+        {

+            Lock();

+            try

+            {

+                Session.ApplyPolicy(this, policyId);

+            }

+            finally

+            {

+                Unlock();

+            }

+

+            Refresh();

+        }

+

+        public void RemovePolicy(IObjectId policyId)

+        {

+            Lock();

+            try

+            {

+                Session.RemovePolicy(this, policyId);

+            }

+            finally

+            {

+                Unlock();

+            }

+

+            Refresh();

+        }

+

+        public IList<IPolicy> Policies

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return policies;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        // --- relationships ---

+

+        public IList<IRelationship> Relationships

+        {

+            get

+            {

+                Lock();

+                try

+                {

+                    return relationships;

+                }

+                finally

+                {

+                    Unlock();

+                }

+            }

+        }

+

+        // --- extensions ---

+

+        public IList<ICmisExtensionElement> GetExtensions(ExtensionLevel level)

+        {

+            IList<ICmisExtensionElement> ext;

+            if (extensions.TryGetValue(level, out ext))

+            {

+                return ext;

+            }

+

+            return null;

+        }

+

+        // --- other ---

+

+        public DateTime RefreshTimestamp { get; private set; }

+

+        public void Refresh()

+        {

+            Lock();

+            try

+            {

+                IOperationContext oc = CreationContext;

+

+                // get the latest data from the repository

+                IObjectData objectData = Binding.GetObjectService().GetObject(RepositoryId, ObjectId, oc.FilterString, oc.IncludeAllowableActions,

+                    oc.IncludeRelationships, oc.RenditionFilterString, oc.IncludePolicies, oc.IncludeAcls, null);

+

+                // reset this object

+                initialize(Session, ObjectType, objectData, CreationContext);

+            }

+            finally

+            {

+                Unlock();

+            }

+        }

+

+        public void RefreshIfOld(long durationInMillis)

+        {

+            Lock();

+            try

+            {

+                if (((DateTime.UtcNow - RefreshTimestamp).Ticks / 10000) > durationInMillis)

+                {

+                    Refresh();

+                }

+            }

+            finally

+            {

+                Unlock();

+            }

+        }

+

+        protected void Lock()

+        {

+            Monitor.Enter(objectLock);

+        }

+

+        protected void Unlock()

+        {

+            Monitor.Exit(objectLock);

+        }

+    }

+}