PortCMIS: more stuff (documentation, tests, fixes, ...)
git-svn-id: https://svn.apache.org/repos/asf/chemistry/portcmis/trunk@1742265 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/PortCMIS/binding/atompub/XmlWalker.cs b/PortCMIS/binding/atompub/XmlWalker.cs
index 9b72975..4293773 100644
--- a/PortCMIS/binding/atompub/XmlWalker.cs
+++ b/PortCMIS/binding/atompub/XmlWalker.cs
@@ -105,7 +105,7 @@
if (extensions.Count + 1 > XmlConstraints.MaxExtensionsWidth)
{
- throw new CmisInvalidArgumentException("Too many extensions!");
+ throw new CmisInvalidArgumentException("Too many extensions! (More than " + XmlConstraints.MaxExtensionsWidth + " extensions.)");
}
extensions.Add(HandleExtensionLevel(parser, 0));
@@ -145,7 +145,7 @@
{
if (sb.Length + s.Length > XmlConstraints.MaxStringLength)
{
- throw new CmisInvalidArgumentException("String limit exceeded!");
+ throw new CmisInvalidArgumentException("String limit exceeded! (String is longer than " + XmlConstraints.MaxStringLength + " characters.)");
}
sb.Append(s);
}
@@ -154,7 +154,7 @@
{
if (level + 1 > XmlConstraints.MaxExtensionsDepth)
{
- throw new CmisInvalidArgumentException("Extensions tree too deep!");
+ throw new CmisInvalidArgumentException("Extensions tree too deep! (More than " + XmlConstraints.MaxExtensionsDepth + " levels.)");
}
if (children == null)
@@ -164,7 +164,7 @@
if (children.Count + 1 > XmlConstraints.MaxExtensionsWidth)
{
- throw new CmisInvalidArgumentException("Extensions tree too wide!");
+ throw new CmisInvalidArgumentException("Extensions tree too wide! (More than " + XmlConstraints.MaxExtensionsWidth + " extensions on one level.)");
}
children.Add(HandleExtensionLevel(parser, level + 1));
@@ -288,7 +288,7 @@
{
public const int MaxStringLength = 100 * 1024;
- public const int MaxExtensionsWidth = 500;
- public const int MaxExtensionsDepth = 20;
+ public const int MaxExtensionsWidth = 1000;
+ public const int MaxExtensionsDepth = 100;
}
}
\ No newline at end of file
diff --git a/PortCMIS/binding/browser/BrowserConverter.cs b/PortCMIS/binding/browser/BrowserConverter.cs
index 03aeee3..5adaa0b 100644
--- a/PortCMIS/binding/browser/BrowserConverter.cs
+++ b/PortCMIS/binding/browser/BrowserConverter.cs
@@ -2100,7 +2100,7 @@
Ace ace = new Ace();
bool? isDirect = GetBoolean(entry, BrowserConstants.JsonAceIsDirect);
- ace.IsDirect = (isDirect != null ? (bool) isDirect : true);
+ ace.IsDirect = (isDirect != null ? (bool)isDirect : true);
JsonArray jsonPermissions = GetJsonArray(entry, BrowserConstants.JsonAcePermissions);
if (jsonPermissions != null)
@@ -2314,9 +2314,15 @@
}
ITypeDefinition typeDef = null;
- if (json[PropertyIds.ObjectTypeId] is string)
+ // TODO: try....
+
+ object objectTypeId;
+ if (json.TryGetValue(PropertyIds.ObjectTypeId, out objectTypeId))
{
- typeDef = typeCache.GetTypeDefinition((string)json[PropertyIds.ObjectTypeId]);
+ if (objectTypeId is string)
+ {
+ typeDef = typeCache.GetTypeDefinition((string)objectTypeId);
+ }
}
JsonArray secTypeIds = GetJsonArray(json, PropertyIds.SecondaryObjectTypeIds);
diff --git a/PortCMIS/client/ClientImpl.cs b/PortCMIS/client/ClientImpl.cs
index 55e0fe5..93108c0 100644
--- a/PortCMIS/client/ClientImpl.cs
+++ b/PortCMIS/client/ClientImpl.cs
@@ -80,7 +80,7 @@
/// <param name="authenticationProvider">Authentication provider.</param>
/// <param name="cache">Client object cache.</param>
/// <returns>a list of all available repositories</returns>
- /// <seealso cref="PortCMIS.SessionParameter"/>
+ /// <seealso cref="PortCMIS.Client.SessionParameter"/>
public IList<IRepository> GetRepositories(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
{
ICmisBinding binding = CmisBindingHelper.CreateBinding(parameters);
@@ -179,6 +179,15 @@
private IAuthenticationProvider authenticationProvider;
private ICache cache;
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="info">the low-level repository info object</param>
+ /// <param name="parameters">the session parameters</param>
+ /// <param name="sessionFactory">the session factory</param>
+ /// <param name="objectFactory">the object factory (may be <c>null</c>)</param>
+ /// <param name="authenticationProvider">the authentication provider (may be <c>null</c>)</param>
+ /// <param name="cache">the cache (may be <c>null</c>)</param>
public Repository(IRepositoryInfo info, IDictionary<string, string> parameters, SessionFactory sessionFactory, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
: base(info)
{
diff --git a/PortCMIS/client/ClientIntf.cs b/PortCMIS/client/ClientIntf.cs
index 1bbf4cd..b04d435 100644
--- a/PortCMIS/client/ClientIntf.cs
+++ b/PortCMIS/client/ClientIntf.cs
@@ -554,38 +554,110 @@
void RemovePolicy(IObjectId objectId, params IObjectId[] policyIds);
}
+ /// <summary>
+ /// Object Factory implementations convert low-level objects to high-level objects.
+ /// </summary>
public interface IObjectFactory
{
+ /// <summary>
+ /// Initializes the factory.
+ /// </summary>
+ /// <param name="session">the session</param>
+ /// <param name="parameters">some parameters</param>
void Initialize(ISession session, IDictionary<string, string> parameters);
// Acl and ACE
+
+ /// <summary>
+ /// Converts ACEs into an ACL.
+ /// </summary>
IAcl ConvertAces(IList<IAce> aces);
+
+ /// <summary>
+ /// Creates an ACL from the given ACEs.
+ /// </summary>
IAcl CreateAcl(IList<IAce> aces);
+
+ /// <summary>
+ /// Converts ACEs into an ACL.
+ /// </summary>
IAce CreateAce(string principal, IList<string> permissions);
// policies
+
+ /// <summary>
+ /// Converts policies.
+ /// </summary>
IList<string> ConvertPolicies(IList<IPolicy> policies);
// renditions
+
+ /// <summary>
+ /// Converts renditions.
+ /// </summary>
IRendition ConvertRendition(string objectId, IRenditionData rendition);
// content stream
+
+ /// <summary>
+ /// Creates a new Content Stream object.
+ /// </summary>
IContentStream CreateContentStream(string filename, long length, string mimetype, Stream stream);
// types
+
+ /// <summary>
+ /// Converts a type definition.
+ /// </summary>
IObjectType ConvertTypeDefinition(ITypeDefinition typeDefinition);
+
+ /// <summary>
+ /// Gets the type from a low-level object.
+ /// </summary>
IObjectType GetTypeFromObjectData(IObjectData objectData);
// properties
+
+ /// <summary>
+ /// Creates a property object.
+ /// </summary>
IProperty CreateProperty<T>(IPropertyDefinition type, IList<T> values);
+
+ /// <summary>
+ /// Converts properties.
+ /// </summary>
IDictionary<string, IProperty> ConvertProperties(IObjectType objectType, IList<ISecondaryType> secondaryTypes, IProperties properties);
+
+ /// <summary>
+ /// Converts properties.
+ /// </summary>
IProperties ConvertProperties(IDictionary<string, object> properties, IObjectType type, IList<ISecondaryType> secondaryTypes, HashSet<Updatability> updatabilityFilter);
+
+ /// <summary>
+ /// Converts properties from a query result.
+ /// </summary>
IList<IPropertyData> ConvertQueryProperties(IProperties properties);
// objects
+
+ /// <summary>
+ /// Converts a low-level object into a hig-level object.
+ /// </summary>
ICmisObject ConvertObject(IObjectData objectData, IOperationContext context);
+
+ /// <summary>
+ /// Converts a query result.
+ /// </summary>
IQueryResult ConvertQueryResult(IObjectData objectData);
+
+ /// <summary>
+ /// Converts a change event.
+ /// </summary>
IChangeEvent ConvertChangeEvent(IObjectData objectData);
+
+ /// <summary>
+ /// Converts a collection of change events.
+ /// </summary>
IChangeEvents ConvertChangeEvents(string changeLogToken, IObjectList objectList);
}
@@ -1006,7 +1078,7 @@
/// Gets whether the repository contains additional items beyond the page of items already fetched.
/// </value>
bool HasMoreItems { get; }
-
+
/// <value>
/// Gets the total number of items. If the repository knows the total number of items
/// in a result set, the repository SHOULD include the number here.
@@ -1291,6 +1363,14 @@
/// <summary>
/// Deletes this object.
/// </summary>
+ /// <remarks>
+ /// If this object is a document, the whole version series is deleted.
+ /// </remarks>
+ void Delete();
+
+ /// <summary>
+ /// Deletes this object.
+ /// </summary>
/// <param name="allVersions">if this object is a document this parameter defines if just this version or all versions should be deleted</param>
void Delete(bool allVersions);
diff --git a/PortCMIS/client/ClientObjects.cs b/PortCMIS/client/ClientObjects.cs
index eb9d39d..d5bca43 100644
--- a/PortCMIS/client/ClientObjects.cs
+++ b/PortCMIS/client/ClientObjects.cs
@@ -35,11 +35,24 @@
/// </summary>
public abstract class AbstractCmisObject : ICmisObject
{
+ /// <value>
+ /// Gets the current session.
+ /// </value>
protected ISession Session { get; private set; }
+
+ /// <value>
+ /// Gets the current repository ID.
+ /// </value>
protected string RepositoryId { get { return Session.RepositoryInfo.Id; } }
+
+ /// <value>
+ /// Gets the current binding.
+ /// </value>
protected ICmisBinding Binding { get { return Session.Binding; } }
private IObjectType objectType;
+
+ /// <inheritdoc/>
public virtual IObjectType ObjectType
{
get
@@ -51,6 +64,7 @@
}
}
+ /// <inheritdoc/>
public virtual IList<ISecondaryType> SecondaryTypes
{
get
@@ -62,6 +76,7 @@
}
}
+ /// <inheritdoc/>
protected virtual string ObjectId
{
get
@@ -76,6 +91,9 @@
}
}
+ /// <summary>
+ /// Gets the operation context that was used to fetch this object.
+ /// </summary>
protected virtual IOperationContext CreationContext { get; private set; }
private IDictionary<string, IProperty> properties;
@@ -86,8 +104,19 @@
private IList<IRelationship> relationships;
private IDictionary<ExtensionLevel, IList<ICmisExtensionElement>> extensions;
private IList<ISecondaryType> secondaryTypes;
+
+ /// <summary>
+ /// An object used for locking.
+ /// </summary>
protected object objectLock = new object();
+ /// <summary>
+ /// Initializes the object.
+ /// </summary>
+ /// <param name="session">the current session</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level object data</param>
+ /// <param name="context">the operation context that was used to fetch this object</param>
protected void Initialize(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
if (session == null)
@@ -241,6 +270,11 @@
}
}
+ /// <summary>
+ /// Returns the query name of a property.
+ /// </summary>
+ /// <param name="propertyId">the property ID</param>
+ /// <returns>the query name or <c>null</c> if the property doesn't exist or the property has no query name</returns>
protected virtual string GetPropertyQueryName(string propertyId)
{
lock (objectLock)
@@ -258,6 +292,12 @@
// --- object ---
/// <inheritdoc/>
+ public virtual void Delete()
+ {
+ Delete(true);
+ }
+
+ /// <inheritdoc/>
public virtual void Delete(bool allVersions)
{
lock (objectLock)
@@ -1728,6 +1768,9 @@
}
}
+ /// <summary>
+ /// Property implementation.
+ /// </summary>
public class Property : IProperty
{
public Property(IPropertyDefinition propertyDefinition, IList<object> values)
@@ -1822,6 +1865,9 @@
}
}
+ /// <summary>
+ /// Rendition implementation.
+ /// </summary>
public class Rendition : RenditionData, IRendition
{
private ISession session;
@@ -1872,6 +1918,9 @@
}
}
+ /// <summary>
+ /// Content Stream Hash implementation.
+ /// </summary>
public class ContentStreamHash : IContentStreamHash
{
/// <inheritdoc/>
@@ -1921,6 +1970,9 @@
}
}
+ /// <summary>
+ /// Query Result implementation.
+ /// </summary>
public class QueryResult : IQueryResult
{
private IDictionary<string, IPropertyData> propertiesById;
@@ -2087,6 +2139,9 @@
public IList<IRendition> Renditions { get; protected set; }
}
+ /// <summary>
+ /// Change Event implementation.
+ /// </summary>
public class ChangeEvent : ChangeEventInfo, IChangeEvent
{
/// <inheritdoc/>
@@ -2102,6 +2157,9 @@
public virtual IAcl Acl { get; set; }
}
+ /// <summary>
+ /// Change Events implementation.
+ /// </summary>
public class ChangeEvents : IChangeEvents
{
/// <inheritdoc/>
diff --git a/PortCMIS/client/ClientUtils.cs b/PortCMIS/client/ClientUtils.cs
index 62685ef..43e1010 100644
--- a/PortCMIS/client/ClientUtils.cs
+++ b/PortCMIS/client/ClientUtils.cs
@@ -351,6 +351,8 @@
public class ObjectId : IObjectId
{
private string id;
+
+ /// <inheritdoc/>
public string Id
{
get { return id; }
@@ -365,6 +367,10 @@
}
}
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="id">the object ID as a string</param>
public ObjectId(string id)
{
Id = id;
@@ -376,7 +382,10 @@
/// </summary>
public class Tree<T> : ITree<T>
{
+ /// <inheritdoc/>
public T Item { get; set; }
+
+ /// <inheritdoc/>
public IList<ITree<T>> Children { get; set; }
}
@@ -465,23 +474,34 @@
this.pageFetcher = pageFetcher;
}
+ /// <inheritdoc/>
T IEnumerator<T>.Current { get { return Current; } }
+
+ /// <inheritdoc/>
object IEnumerator.Current { get { return Current; } }
+
+ /// <inheritdoc/>
public T Current { get { return current; } }
+ /// <summary>
+ /// Reset is not supported.
+ /// </summary>
public void Reset()
{
throw new NotSupportedException();
}
+ /// <inheritdoc/>
public abstract bool MoveNext();
+ /// <inheritdoc/>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
+ /// <inheritdoc/>
protected virtual void Dispose(bool disposing)
{
}
diff --git a/PortCMIS/data/DataImpl.cs b/PortCMIS/data/DataImpl.cs
index 6fa7ac4..06da0b5 100644
--- a/PortCMIS/data/DataImpl.cs
+++ b/PortCMIS/data/DataImpl.cs
@@ -27,11 +27,21 @@
namespace PortCMIS.Data
{
+ /// <summary>
+ /// Repository Info implementation.
+ /// </summary>
public class RepositoryInfo : ExtensionsData, IRepositoryInfo
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
public RepositoryInfo()
{
}
+
+ /// <summary>
+ /// Copy Constructor.
+ /// </summary>
public RepositoryInfo(IRepositoryInfo source)
{
Id = source.Id;
@@ -129,12 +139,16 @@
/// <inheritdoc/>
public IList<IExtensionFeature> ExtensionFeatures { get; set; }
+ /// <inheritdoc/>
public override string ToString()
{
return "RepositoryInfo: " + Id;
}
}
+ /// <summary>
+ /// Repository Capabilities implementation.
+ /// </summary>
internal class RepositoryCapabilities : ExtensionsData, IRepositoryCapabilities
{
/// <inheritdoc/>
diff --git a/PortCMISTests/SimpleCmisTest.cs b/PortCMISTests/SimpleCmisTest.cs
index be55f8b..0670c24 100644
--- a/PortCMISTests/SimpleCmisTest.cs
+++ b/PortCMISTests/SimpleCmisTest.cs
@@ -11,6 +11,7 @@
using System.Text;
using PortCMIS.Utils;
using PortCMISTests.Framework;
+using System.Linq;
namespace PortCMISTests
{
@@ -97,7 +98,7 @@
try
{
ICmisObject obj = Session.GetObjectByPath("/porttest");
- obj.Delete(true);
+ obj.Delete();
}
catch (CmisConstraintException)
{
@@ -156,6 +157,33 @@
Assert.AreEqual(newDoc.Name, newDoc2.Name);
Assert.AreEqual(contentBytes.Length, newDoc2.ContentStreamLength);
+
+ // delete document
+ newDoc.Delete();
+
+ try
+ {
+ Session.GetObject(newDoc);
+ Assert.Fail("Document still exists.");
+ }
+ catch (CmisObjectNotFoundException)
+ {
+ // expected
+ }
+
+ // delete folder
+
+ newFolder.Delete();
+
+ try
+ {
+ Session.GetObject(newFolder);
+ Assert.Fail("Folder still exists.");
+ }
+ catch (CmisObjectNotFoundException)
+ {
+ // expected
+ }
}
[TestMethod]
@@ -233,6 +261,70 @@
}
Assert.IsTrue(count > 0);
+
+ IOperationContext oc = Session.CreateOperationContext();
+ oc.FilterString = "cmis:objectId,cmis:name";
+
+ IFolder rootFolder = Session.GetRootFolder(oc);
+ bool found = false;
+
+ foreach (ICmisObject obj in Session.QueryObjects("cmis:folder", null, false, oc))
+ {
+ Assert.IsNotNull(obj.Id);
+ Assert.IsNotNull(obj.Name);
+
+ if (obj.Id == rootFolder.Id)
+ {
+ found = true;
+ }
+ }
+
+ Assert.IsTrue(found);
+ }
+
+ [TestMethod]
+ public void TestMove()
+ {
+ // create folder 1
+ IDictionary<string, object> folder1prop = new Dictionary<string, object>();
+ folder1prop[PropertyIds.Name] = "movefolder1";
+ folder1prop[PropertyIds.ObjectTypeId] = "cmis:folder";
+
+ IObjectId folder1 = Session.CreateFolder(folder1prop, Session.GetRootFolder());
+
+ // create folder2
+ IDictionary<string, object> folder2prop = new Dictionary<string, object>();
+ folder2prop[PropertyIds.Name] = "movefolder2";
+ folder2prop[PropertyIds.ObjectTypeId] = "cmis:folder";
+
+ IObjectId folder2 = Session.CreateFolder(folder2prop, Session.GetRootFolder());
+
+ // create item
+ IDictionary<string, object> itemProp = new Dictionary<string, object>();
+ itemProp[PropertyIds.Name] = "movee";
+ itemProp[PropertyIds.ObjectTypeId] = "cmis:item";
+
+ IObjectId item = Session.CreateItem(itemProp, folder1);
+
+ // move
+ IItem itemObj = Session.GetObject(item) as IItem;
+ itemObj.Move(folder1, folder2);
+
+ itemObj.Refresh();
+
+ // test
+ Assert.AreEqual(folder2.Id, itemObj.Parents[0].Id);
+
+ int folderSize1 = Enumerable.Count<ICmisObject>((Session.GetObject(folder1) as IFolder).GetChildren());
+ Assert.AreEqual(0, folderSize1);
+
+ int folderSize2 = Enumerable.Count<ICmisObject>((Session.GetObject(folder2) as IFolder).GetChildren());
+ Assert.AreEqual(1, folderSize2);
+
+ // clean up
+ Session.Delete(item);
+ Session.Delete(folder1);
+ Session.Delete(folder2);
}
}
}