- 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);
+ }
+ }
+}