PortCMIS: more stuff
git-svn-id: https://svn.apache.org/repos/asf/chemistry/portcmis/trunk@1742546 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/PortCMIS/binding/HttpPortable.cs b/PortCMIS/binding/HttpPortable.cs
index ef44fe5..44d10af 100644
--- a/PortCMIS/binding/HttpPortable.cs
+++ b/PortCMIS/binding/HttpPortable.cs
@@ -140,7 +140,7 @@
{
foreach (KeyValuePair<string, string> header in headers)
{
- request.Headers.Add(header.Key, header.Value);
+ request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
diff --git a/PortCMIS/binding/IOUtils.cs b/PortCMIS/binding/IOUtils.cs
index b07f416..bfd37b8 100644
--- a/PortCMIS/binding/IOUtils.cs
+++ b/PortCMIS/binding/IOUtils.cs
@@ -17,14 +17,9 @@
* under the License.
*/
-using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-namespace PortCMIS.binding
+namespace PortCMIS.Binding
{
class IOUtils
{
diff --git a/PortCMIS/binding/atompub/AtomPubBinding.cs b/PortCMIS/binding/atompub/AtomPubBinding.cs
index d94febe..61a824b 100644
--- a/PortCMIS/binding/atompub/AtomPubBinding.cs
+++ b/PortCMIS/binding/atompub/AtomPubBinding.cs
@@ -17,7 +17,7 @@
* under the License.
*/
-using PortCMIS.binding;
+using PortCMIS.Binding;
using PortCMIS.Binding.Http;
using PortCMIS.Binding.Impl;
using PortCMIS.Binding.Services;
diff --git a/PortCMIS/binding/atompub/AtomPubUtils.cs b/PortCMIS/binding/atompub/AtomPubUtils.cs
index 05510b2..3114df5 100644
--- a/PortCMIS/binding/atompub/AtomPubUtils.cs
+++ b/PortCMIS/binding/atompub/AtomPubUtils.cs
@@ -17,7 +17,7 @@
* under the License.
*/
-using PortCMIS.binding;
+using PortCMIS.Binding;
using PortCMIS.Binding.Impl;
using PortCMIS.Client;
using PortCMIS.Data;
diff --git a/PortCMIS/binding/browser/BrowserBinding.cs b/PortCMIS/binding/browser/BrowserBinding.cs
index dc196fc..c746b55 100644
--- a/PortCMIS/binding/browser/BrowserBinding.cs
+++ b/PortCMIS/binding/browser/BrowserBinding.cs
@@ -17,7 +17,7 @@
* under the License.
*/
-using PortCMIS.binding;
+using PortCMIS.Binding;
using PortCMIS.Binding.Browser.Json;
using PortCMIS.Binding.Http;
using PortCMIS.Binding.Impl;
@@ -295,7 +295,7 @@
if (Stream.Stream != null)
{
StreamContent streamContent = new StreamContent(Stream.Stream);
- streamContent.Headers.ContentType = new MediaTypeHeaderValue(Stream.MimeType ?? "application/octet-stream");
+ streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(Stream.MimeType ?? "application/octet-stream");
content.Add(streamContent, "content", Stream.FileName ?? "content");
}
diff --git a/PortCMIS/client/ClientImpl.cs b/PortCMIS/client/ClientImpl.cs
index 93108c0..59d18b7 100644
--- a/PortCMIS/client/ClientImpl.cs
+++ b/PortCMIS/client/ClientImpl.cs
@@ -223,21 +223,52 @@
CreateAndCheckoutUpdatability.Add(Updatability.WhenCheckedOut);
}
+ /// <summary>
+ /// Initial default operation context.
+ /// </summary>
protected static IOperationContext FallbackContext = new OperationContext(null, false, true, false, IncludeRelationships.None, null, true, null, true, 100);
+ /// <summary>
+ /// Session parameters
+ /// </summary>
protected IDictionary<string, string> parameters;
private object sessionLock = new object();
+ /// <value>
+ /// Gets the low-level binding.
+ /// </value>
public ICmisBinding Binding { get; protected set; }
+
+ /// <value>
+ /// Gets the repository info.
+ /// </value>
public IRepositoryInfo RepositoryInfo { get; protected set; }
+
+ /// <value>
+ /// Gets the repository ID.
+ /// </value>
public string RepositoryId { get { return RepositoryInfo.Id; } }
public IObjectFactory ObjectFactory { get; protected set; }
+
+ /// <summary>
+ /// Authentication provider.
+ /// </summary>
protected IAuthenticationProvider AuthenticationProvider { get; set; }
+
+ /// <summary>
+ /// Object and path cache.
+ /// </summary>
protected ICache Cache { get; set; }
+
+ /// <summary>
+ /// Indicating if the path cache should be used.
+ /// </summary>
protected bool cachePathOmit;
private IOperationContext context = FallbackContext;
+
+ /// <inheritdoc/>
public IOperationContext DefaultContext
{
get
@@ -256,6 +287,13 @@
}
}
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="parameters">the session parameters</param>
+ /// <param name="objectFactory">an object factory, if available</param>
+ /// <param name="authenticationProvider">an authentication provider, if available</param>
+ /// <param name="cache">a cache, if available</param>
public Session(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
{
if (parameters == null)
@@ -299,6 +337,10 @@
}
}
+ /// <summary>
+ /// Create the cache.
+ /// </summary>
+ /// <returns>the cache object</returns>
protected ICache CreateCache()
{
try
@@ -331,6 +373,10 @@
}
}
+ /// <summary>
+ /// Creates the object factory.
+ /// </summary>
+ /// <returns>the object factory</returns>
protected IObjectFactory CreateObjectFactory()
{
try
diff --git a/PortCMIS/client/ClientIntf.cs b/PortCMIS/client/ClientIntf.cs
index 2e54ba3..714c0b8 100644
--- a/PortCMIS/client/ClientIntf.cs
+++ b/PortCMIS/client/ClientIntf.cs
@@ -135,7 +135,7 @@
ICmisBinding Binding { get; }
/// <value>
- /// Gets the default operation context.
+ /// Gets and sets the default operation context.
/// </value>
IOperationContext DefaultContext { get; set; }
diff --git a/PortCMIS/client/ClientObjects.cs b/PortCMIS/client/ClientObjects.cs
index d5bca43..0a2afcf 100644
--- a/PortCMIS/client/ClientObjects.cs
+++ b/PortCMIS/client/ClientObjects.cs
@@ -847,6 +847,13 @@
/// </summary>
public class Document : AbstractFileableCmisObject, IDocument
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session object</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level data object</param>
+ /// <param name="context">the operation context used to fetch this object</param>
public Document(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
Initialize(session, objectType, objectData, context);
@@ -1255,6 +1262,13 @@
/// </summary>
public class Folder : AbstractFileableCmisObject, IFolder
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session object</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level data object</param>
+ /// <param name="context">the operation context used to fetch this object</param>
public Folder(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
Initialize(session, objectType, objectData, context);
@@ -1664,6 +1678,13 @@
/// </summary>
public class Policy : AbstractFileableCmisObject, IPolicy
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session object</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level data object</param>
+ /// <param name="context">the operation context used to fetch this object</param>
public Policy(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
Initialize(session, objectType, objectData, context);
@@ -1678,7 +1699,13 @@
/// </summary>
public class Relationship : AbstractCmisObject, IRelationship
{
-
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session object</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level data object</param>
+ /// <param name="context">the operation context used to fetch this object</param>
public Relationship(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
Initialize(session, objectType, objectData, context);
@@ -1762,6 +1789,13 @@
/// </summary>
public class Item : AbstractFileableCmisObject, IItem
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session object</param>
+ /// <param name="objectType">the object type</param>
+ /// <param name="objectData">the low-level data object</param>
+ /// <param name="context">the operation context used to fetch this object</param>
public Item(ISession session, IObjectType objectType, IObjectData objectData, IOperationContext context)
{
Initialize(session, objectType, objectData, context);
@@ -1773,6 +1807,11 @@
/// </summary>
public class Property : IProperty
{
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="propertyDefinition">the property definition</param>
+ /// <param name="values">the property values</param>
public Property(IPropertyDefinition propertyDefinition, IList<object> values)
{
PropertyDefinition = propertyDefinition;
@@ -1873,6 +1912,19 @@
private ISession session;
private string objectId;
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="session">the session objec</param>
+ /// <param name="objectId">the object ID</param>
+ /// <param name="streamId">the stream ID</param>
+ /// <param name="mimeType">the MIME type</param>
+ /// <param name="length">the length in bytes, if known</param>
+ /// <param name="kind">the kind</param>
+ /// <param name="title">the title</param>
+ /// <param name="height">the thumbnail height</param>
+ /// <param name="width">the thumbnail width</param>
+ /// <param name="renditionDocumentId">the ID of the stand-alone rendition document, if it exists</param>
public Rendition(ISession session, string objectId, string streamId, string mimeType, BigInteger? length, string kind,
string title, BigInteger? height, BigInteger? width, string renditionDocumentId)
{
@@ -1923,6 +1975,27 @@
/// </summary>
public class ContentStreamHash : IContentStreamHash
{
+ /// <summary>Algorithm MD5</summary>
+ public const string AlgorithmMD5 = "md5";
+
+ /// <summary>Algorithm sha-1</summary>
+ public const string AlgorithmSHA1 = "sha-1";
+
+ /// <summary>Algorithm sha-224</summary>
+ public const string AlgorithmSHA224 = "sha-224";
+
+ /// <summary>Algorithm sha-256</summary>
+ public const string AlgorithmSHA256 = "sha-256";
+
+ /// <summary>Algorithm sha-384</summary>
+ public const string AlgorithmSHA384 = "sha-384";
+
+ /// <summary>Algorithm sha-512</summary>
+ public const string AlgorithmSHA512 = "sha-512";
+
+ /// <summary>Algorithm sha-3</summary>
+ public const string AlgorithmSHA3 = "sha-3";
+
/// <inheritdoc/>
public string PropertyValue { get; protected set; }
@@ -1932,6 +2005,10 @@
/// <inheritdoc/>
public string Hash { get; protected set; }
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="propertyValue">a property value</param>
public ContentStreamHash(string propertyValue)
{
PropertyValue = propertyValue;
@@ -1952,6 +2029,11 @@
Hash = pv.Substring(algEnd + 1).Replace(" ", "").ToLowerInvariant();
}
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="algorithm">the algorithm</param>
+ /// <param name="hashStr">the hash string</param>
public ContentStreamHash(string algorithm, string hashStr)
{
if (algorithm == null || algorithm.Trim().Length == 0)
diff --git a/PortCMIS/client/ClientUtils.cs b/PortCMIS/client/ClientUtils.cs
index 7cd11db..03af80d 100644
--- a/PortCMIS/client/ClientUtils.cs
+++ b/PortCMIS/client/ClientUtils.cs
@@ -17,10 +17,12 @@
* under the License.
*/
+using PortCMIS.Data;
using PortCMIS.Enums;
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Numerics;
using System.Text;
@@ -928,6 +930,139 @@
}
}
+ /// <summary>
+ /// Content Stream helpers.
+ /// </summary>
+ public class ContentStreamUtils
+ {
+ /// <summary>Octet Stream MIME type.</summary>
+ private const string OctetStream = "application/octet-stream";
+
+ private ContentStreamUtils()
+ {
+ }
+
+ /// <summary>
+ /// Creates a content stream object.
+ /// </summary>
+ /// <param name="filename">the filename</param>
+ /// <param name="length">the length</param>
+ /// <param name="mimetype">the MIME type</param>
+ /// <param name="stream">the stream</param>
+ /// <returns>the content stream</returns>
+ public static IContentStream CreateContentStream(string filename, BigInteger? length, string mimetype, Stream stream)
+ {
+ return new ContentStream()
+ {
+ FileName = CheckFilename(filename),
+ Length = length,
+ MimeType = CheckMimeType(mimetype),
+ Stream = stream
+ };
+ }
+
+ // --- byte arrays ---
+
+ /// <summary>
+ /// Creates a content stream object from a byte array.
+ /// </summary>
+ /// <param name="filename">the filename</param>
+ /// <param name="contentBytes">the byte array</param>
+ /// <param name="mimetype">the MIME type</param>
+ /// <returns>the content stream</returns>
+ public static IContentStream CreateByteArrayContentStream(string filename, byte[] contentBytes, string mimetype)
+ {
+ if (contentBytes == null)
+ {
+ return CreateContentStream(filename, null, mimetype, null);
+ }
+
+ return CreateByteArrayContentStream(filename, contentBytes, 0, contentBytes.Length, mimetype);
+ }
+
+ /// <summary>
+ /// Creates a content stream object from a byte array.
+ /// </summary>
+ /// <param name="filename">the filename</param>
+ /// <param name="contentBytes">the byte array</param>
+ /// <param name="index">the begin of the stream in the byte array</param>
+ /// <param name="count">the length of the stream</param>
+ /// <param name="mimetype">the MIME type</param>
+ /// <returns>the content stream</returns>
+ public static IContentStream CreateByteArrayContentStream(string filename, byte[] contentBytes, int index, int count, string mimetype)
+ {
+ if (contentBytes == null)
+ {
+ return CreateContentStream(filename, null, mimetype, null);
+ }
+
+ if (index < 0 || index > contentBytes.Length)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ else if (count < 0 || (index + count) > contentBytes.Length || (index + count) < 0)
+ {
+ throw new ArgumentOutOfRangeException("count");
+ }
+
+ return CreateContentStream(filename, count, mimetype, new MemoryStream(contentBytes, index, count));
+ }
+
+ // --- strings ---
+
+ /// <summary>
+ /// Creates a content stream object from a string.
+ /// </summary>
+ /// <param name="filename">the filename</param>
+ /// <param name="content">the content</param>
+ /// <returns>the content stream</returns>
+ public static IContentStream CreateTextContentStream(string filename, string content)
+ {
+ return CreateTextContentStream(filename, content, "text/plain; charset=UTF-8");
+ }
+
+ /// <summary>
+ /// Creates a content stream object from a string.
+ /// </summary>
+ /// <param name="filename">the filename</param>
+ /// <param name="content">the content</param>
+ /// <param name="mimetype">the MIME type</param>
+ /// <returns>the content stream</returns>
+ public static IContentStream CreateTextContentStream(string filename, string content, string mimetype)
+ {
+ byte[] contentBytes = Encoding.UTF8.GetBytes(content);
+ return CreateByteArrayContentStream(filename, contentBytes, CheckMimeType(mimetype));
+ }
+
+ // ---
+
+ private static string CheckFilename(string filename)
+ {
+ if (filename == null || filename.Length == 0)
+ {
+ return "content";
+ }
+
+ return filename;
+ }
+
+ private static string CheckMimeType(string mimetype)
+ {
+ if (mimetype == null)
+ {
+ return OctetStream;
+ }
+
+ string result = mimetype.Trim();
+ if (result.Length < 3)
+ {
+ return OctetStream;
+ }
+
+ return result;
+ }
+ }
+
internal class StringListBuilder
{
private string seperator;
diff --git a/PortCMIS/const/BindingType.cs b/PortCMIS/const/BindingType.cs
index 2559e41..ce13562 100644
--- a/PortCMIS/const/BindingType.cs
+++ b/PortCMIS/const/BindingType.cs
@@ -19,6 +19,9 @@
namespace PortCMIS
{
+ /// <summary>
+ /// Binding type.
+ /// </summary>
public static class BindingType
{
/// <summary>Binding type AtomPub</summary>
diff --git a/PortCMIS/const/ExtensionFeatures.cs b/PortCMIS/const/ExtensionFeatures.cs
index c65e82a..651ec3d 100644
--- a/PortCMIS/const/ExtensionFeatures.cs
+++ b/PortCMIS/const/ExtensionFeatures.cs
@@ -54,5 +54,18 @@
VersionLabel = "1.0",
Description = "Adds the property cmis:contentStreamHash, which represents the hash of the document content."
};
+
+ /// <summary>
+ /// Latest Accessible State extension.
+ /// </summary>
+ public readonly static IExtensionFeature LatestAccessibleState = new ExtensionFeature()
+ {
+ Id = "http://docs.oasis-open.org/ns/cmis/extension/latestAccessibleState/1.1",
+ Url = "https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cmis",
+ CommonName = "Latest Accessible State",
+ VersionLabel = "1.1",
+ Description = "This extension provides for an identifier of each cmis:document that retrieves "
+ + "the latest accessible state of the document whether the document is versioned or not."
+ };
}
}
diff --git a/PortCMIS/const/PermissionMappingKeys.cs b/PortCMIS/const/PermissionMappingKeys.cs
index 202bcbd..b45f631 100644
--- a/PortCMIS/const/PermissionMappingKeys.cs
+++ b/PortCMIS/const/PermissionMappingKeys.cs
@@ -19,6 +19,9 @@
namespace PortCMIS
{
+ /// <summary>
+ /// Keys for permission mappings.
+ /// </summary>
public static class PermissionMappingKeys
{
public const string CanGetDescendentsFolder = "canGetDescendents.Folder";
diff --git a/PortCMIS/data/DataImpl.cs b/PortCMIS/data/DataImpl.cs
index 06da0b5..1e67cfc 100644
--- a/PortCMIS/data/DataImpl.cs
+++ b/PortCMIS/data/DataImpl.cs
@@ -389,7 +389,11 @@
/// <inheritdoc/>
public ITypeMutability TypeMutability { get; set; }
- public void Initialize(ITypeDefinition typeDefinition)
+ /// <summary>
+ /// Initializes the type definition object.
+ /// </summary>
+ /// <param name="typeDefinition">the type definition</param>
+ protected void Initialize(ITypeDefinition typeDefinition)
{
Id = typeDefinition.Id;
LocalName = typeDefinition.LocalName;
@@ -414,6 +418,11 @@
}
}
}
+
+ /// <summary>
+ /// Adds a property type definition.
+ /// </summary>
+ /// <param name="propertyDefinition">the property type definition</param>
public void AddPropertyDefinition(IPropertyDefinition propertyDefinition)
{
if (propertyDefinition == null || propertyDefinition.Id == null)
@@ -424,6 +433,7 @@
propertyDefintionDict[propertyDefinition.Id] = propertyDefinition;
}
+ /// <inheritdoc/>
public override string ToString()
{
return "TypeDefinition: " + BaseTypeId + " (" + Id + ")";
@@ -572,6 +582,9 @@
public bool? IsOpenChoice { get; set; }
}
+ /// <summary>
+ /// Choice implementation.
+ /// </summary>
public class Choice<T> : IChoice<T>
{
/// <inheritdoc/>
@@ -584,6 +597,9 @@
public IList<IChoice<T>> Choices { get; set; }
}
+ /// <summary>
+ /// Boolean property definition implementation.
+ /// </summary>
public class PropertyBooleanDefinition : PropertyDefinition, IPropertyBooleanDefinition
{
/// <inheritdoc/>
@@ -593,6 +609,9 @@
public IList<IChoice<bool?>> Choices { get; set; }
}
+ /// <summary>
+ /// DataTime property definition implementation.
+ /// </summary>
public class PropertyDateTimeDefinition : PropertyDefinition, IPropertyDateTimeDefinition
{
/// <inheritdoc/>
@@ -605,6 +624,9 @@
public DateTimeResolution? DateTimeResolution { get; set; }
}
+ /// <summary>
+ /// Decimal property definition implementation.
+ /// </summary>
public class PropertyDecimalDefinition : PropertyDefinition, IPropertyDecimalDefinition
{
/// <inheritdoc/>
@@ -623,6 +645,9 @@
public DecimalPrecision? Precision { get; set; }
}
+ /// <summary>
+ /// HTML property definition implementation.
+ /// </summary>
public class PropertyHtmlDefinition : PropertyDefinition, IPropertyHtmlDefinition
{
/// <inheritdoc/>
@@ -632,6 +657,9 @@
public IList<IChoice<string>> Choices { get; set; }
}
+ /// <summary>
+ /// ID property definition implementation.
+ /// </summary>
public class PropertyIdDefinition : PropertyDefinition, IPropertyIdDefinition
{
/// <inheritdoc/>
@@ -641,6 +669,9 @@
public IList<IChoice<string>> Choices { get; set; }
}
+ /// <summary>
+ /// Integer property definition implementation.
+ /// </summary>
public class PropertyIntegerDefinition : PropertyDefinition, IPropertyIntegerDefinition
{
/// <inheritdoc/>
@@ -656,6 +687,9 @@
public BigInteger? MaxValue { get; set; }
}
+ /// <summary>
+ /// String property definition implementation.
+ /// </summary>
public class PropertyStringDefinition : PropertyDefinition, IPropertyStringDefinition
{
/// <inheritdoc/>
@@ -668,6 +702,9 @@
public BigInteger? MaxLength { get; set; }
}
+ /// <summary>
+ /// URI property definition implementation.
+ /// </summary>
public class PropertyUriDefinition : PropertyDefinition, IPropertyUriDefinition
{
/// <inheritdoc/>
diff --git a/PortCMIS/data/DataIntf.cs b/PortCMIS/data/DataIntf.cs
index 2accd2a..9aaea10 100644
--- a/PortCMIS/data/DataIntf.cs
+++ b/PortCMIS/data/DataIntf.cs
@@ -32,166 +32,361 @@
public interface IRepositoryInfo : IExtensionsData
{
/// <value>
- /// Repository ID.
+ /// Gets the repository ID.
/// </value>
string Id { get; }
/// <value>
- /// Repository Name.
+ /// Gets the repository Name.
/// </value>
string Name { get; }
/// <value>
- /// Repository description.
+ /// Gets the repository description.
/// </value>
string Description { get; }
/// <value>
- /// Repository vendor.
+ /// Gets the repository vendor.
/// </value>
string VendorName { get; }
/// <value>
- /// Repository product name.
+ /// Gets the repository product name.
/// </value>
string ProductName { get; }
/// <value>
- /// Repository product version.
+ /// Gets the repository product version.
/// </value>
string ProductVersion { get; }
/// <value>
- /// Root folder ID.
+ /// Gets the root folder ID.
/// </value>
string RootFolderId { get; }
/// <value>
- /// Repository capabilities.
+ /// Gets the repository capabilities.
/// </value>
IRepositoryCapabilities Capabilities { get; }
/// <value>
- /// Repository ACL capabilities.
+ /// Gets the repository ACL capabilities.
/// </value>
IAclCapabilities AclCapabilities { get; }
/// <value>
- /// Latest change log token.
+ /// Gets the latest change log token.
/// </value>
string LatestChangeLogToken { get; }
/// <value>
- /// CMIS version (string).
+ /// Gets the CMIS version as string.
/// </value>
string CmisVersionSupported { get; }
/// <value>
- /// CMIS version (enum).
+ /// Gets the CMIS version as enum.
/// </value>
CmisVersion CmisVersion { get; }
/// <value>
- /// Repository thin client URI.
+ /// Gets the repository thin client URI.
/// </value>
string ThinClientUri { get; }
/// <value>
- /// Changes incomplete flag.
+ /// Gets the changes incomplete flag.
/// </value>
bool? ChangesIncomplete { get; }
/// <value>
- /// List of changable base types.
+ /// Gets the list of changable base types.
/// </value>
IList<BaseTypeId?> ChangesOnType { get; }
/// <value>
- /// Principal ID of an anonymous user, if supported.
+ /// Gets the principal ID of an anonymous user, if supported.
/// </value>
string PrincipalIdAnonymous { get; }
/// <value>
- /// Principal ID of an unauthenticated user, if supported.
+ /// Gets the principal ID of an unauthenticated user, if supported.
/// </value>
string PrincipalIdAnyone { get; }
/// <value>
- /// List of extension features.
+ /// Gets the list of extension features.
/// </value>
IList<IExtensionFeature> ExtensionFeatures { get; }
}
+ /// <summary>
+ /// Repository Capabilities.
+ /// </summary>
public interface IRepositoryCapabilities : IExtensionsData
{
+ /// <value>
+ /// Gets the content Stream Updates capability.
+ /// </value>
CapabilityContentStreamUpdates? ContentStreamUpdatesCapability { get; }
+
+ /// <value>
+ /// Gets the change log capability.
+ /// </value>
CapabilityChanges? ChangesCapability { get; }
+
+ /// <value>
+ /// Gets the rendition capability.
+ /// </value>
CapabilityRenditions? RenditionsCapability { get; }
+
+ /// <value>
+ /// Gets whether getDescendants is supported or not.
+ /// </value>
bool? IsGetDescendantsSupported { get; }
+
+ /// <value>
+ /// Gets whether getFolderTree is supported or not.
+ /// </value>
bool? IsGetFolderTreeSupported { get; }
+
+ /// <value>
+ /// Gets the OREDER BY capability.
+ /// </value>
CapabilityOrderBy? OrderByCapability { get; }
+
+ /// <value>
+ /// Gets whether multi-filing is supported or not.
+ /// </value>
bool? IsMultifilingSupported { get; }
+
+ /// <value>
+ /// Gets whether unfiling is supported or not.
+ /// </value>
bool? IsUnfilingSupported { get; }
+
+ /// <value>
+ /// Gets whether version specific filing is supported or not.
+ /// </value>
bool? IsVersionSpecificFilingSupported { get; }
+
+ /// <value>
+ /// Gets whether the PWC is searchable or not.
+ /// </value>
bool? IsPwcSearchableSupported { get; }
+
+ /// <value>
+ /// Gets whether PWC is updapatable or not.
+ /// </value>
bool? IsPwcUpdatableSupported { get; }
+
+ /// <value>
+ /// Gets whether query for all versions is supported or not.
+ /// </value>
bool? IsAllVersionsSearchableSupported { get; }
+
+ /// <value>
+ /// Gets the query capability.
+ /// </value>
CapabilityQuery? QueryCapability { get; }
+
+ /// <value>
+ /// Gets the Join capability.
+ /// </value>
CapabilityJoin? JoinCapability { get; }
+
+ /// <value>
+ /// Gets the ACL capability.
+ /// </value>
CapabilityAcl? AclCapability { get; }
+
+ /// <value>
+ /// Gets which property types are supported for new types.
+ /// </value>
ICreatablePropertyTypes CreatablePropertyTypes { get; }
+
+ /// <value>
+ /// Gets which attributes can be set on a new type.
+ /// </value>
INewTypeSettableAttributes NewTypeSettableAttributes { get; }
}
+ /// <summary>
+ /// Property Type that are supported for new types.
+ /// </summary>
public interface ICreatablePropertyTypes : IExtensionsData
{
+ /// <value>
+ /// Gets the set of property types that are supported for new types.
+ /// </value>
ISet<PropertyType> CanCreate { get; }
}
+ /// <summary>
+ /// Attributes that can be set on new types.
+ /// </summary>
public interface INewTypeSettableAttributes : IExtensionsData
{
+ /// <value>
+ /// Gets whether the type ID can be set or not.
+ /// </value>
bool? CanSetId { get; }
+
+ /// <value>
+ /// Gets whether the local name can be set or not.
+ /// </value>
bool? CanSetLocalName { get; }
+
+ /// <value>
+ /// Gets whether the local namespace can be set or not.
+ /// </value>
bool? CanSetLocalNamespace { get; }
+
+ /// <value>
+ /// Gets whether the display name can be set or not.
+ /// </value>
bool? CanSetDisplayName { get; }
+
+ /// <value>
+ /// Gets whether the query name can be set or not.
+ /// </value>
bool? CanSetQueryName { get; }
+
+ /// <value>
+ /// Gets whether the description can be set or not.
+ /// </value>
bool? CanSetDescription { get; }
+
+ /// <value>
+ /// Gets whether the creatable flag can be set or not.
+ /// </value>
bool? CanSetCreatable { get; }
+
+ /// <value>
+ /// Gets whether the filable flag can be set or not.
+ /// </value>
bool? CanSetFileable { get; }
+
+ /// <value>
+ /// Gets whether the queryable flag can be set or not.
+ /// </value>
bool? CanSetQueryable { get; }
+
+ /// <value>
+ /// Gets whether the fulltext flag can be set or not.
+ /// </value>
bool? CanSetFulltextIndexed { get; }
+
+ /// <value>
+ /// Gets whether the IncludedInSupertype flag can be set or not.
+ /// </value>
bool? CanSetIncludedInSupertypeQuery { get; }
+
+ /// <value>
+ /// Gets whether the policy control can be set or not.
+ /// </value>
bool? CanSetControllablePolicy { get; }
+
+ /// <value>
+ /// Gets whether the ACL control can be set or not.
+ /// </value>
bool? CanSetControllableAcl { get; }
}
+ /// <summary>
+ /// ACL capabilities.
+ /// </summary>
public interface IAclCapabilities : IExtensionsData
{
+ /// <value>
+ /// Gets which permission set is supported.
+ /// </value>
SupportedPermissions? SupportedPermissions { get; }
+
+ /// <value>
+ /// Gets which ACL propagation is supported.
+ /// </value>
AclPropagation? AclPropagation { get; }
+
+ /// <value>
+ /// Gets permission definitions.
+ /// </value>
IList<IPermissionDefinition> Permissions { get; }
+
+ /// <value>
+ /// Gets permission mapping.
+ /// </value>
IDictionary<string, IPermissionMapping> PermissionMapping { get; }
}
+ /// <summary>
+ /// Permission definition.
+ /// </summary>
public interface IPermissionDefinition : IExtensionsData
{
+ /// <value>
+ /// Gets the permission ID.
+ /// </value>
string Id { get; }
+
+ /// <value>
+ /// Gets the description of the permission.
+ /// </value>
string Description { get; }
}
+ /// <summary>
+ /// Permission mapping.
+ /// </summary>
public interface IPermissionMapping : IExtensionsData
{
+ /// <value>
+ /// Gets the permission key.
+ /// </value>
+ /// <seealso cref="PortCMIS.PermissionMappingKeys"/>
string Key { get; }
+
+ /// <value>
+ /// Gets the required permissions.
+ /// </value>
IList<string> Permissions { get; }
}
+ /// <summary>
+ /// Extension feature.
+ /// </summary>
public interface IExtensionFeature : IExtensionsData
{
+ /// <value>
+ /// Gets the ID of the feature.
+ /// </value>
string Id { get; }
+
+ /// <value>
+ /// Gets the URL of the feature.
+ /// </value>
string Url { get; }
+
+ /// <value>
+ /// Gets the name of the feature.
+ /// </value>
string CommonName { get; }
+
+ /// <value>
+ /// Gets the version label of the feature.
+ /// </value>
string VersionLabel { get; }
+
+ /// <value>
+ /// Gets the description of the feature.
+ /// </value>
string Description { get; }
+
+ /// <value>
+ /// Gets a feature specific set of data.
+ /// </value>
IDictionary<string, string> FeatureData { get; }
}
@@ -736,33 +931,88 @@
/// </summary>
public interface IObjectList : IExtensionsData
{
+ /// <value>
+ /// Gets the list of objects.
+ /// </value>
IList<IObjectData> Objects { get; }
+
+ /// <value>
+ /// Gets whether there are more objects, if known.
+ /// </value>
bool? HasMoreItems { get; }
+
+ /// <value>
+ /// Gets total number of objects in the list, if known.
+ /// </value>
BigInteger? NumItems { get; }
}
+ /// <summary>
+ /// Object in a folder.
+ /// </summary>
public interface IObjectInFolderData : IExtensionsData
{
+ /// <value>
+ /// Gets the object.
+ /// </value>
IObjectData Object { get; }
+
+ /// <value>
+ /// Get the path segment of the object in the folder.
+ /// </value>
string PathSegment { get; }
}
+ /// <summary>
+ /// List of objects in a folder.
+ /// </summary>
public interface IObjectInFolderList : IExtensionsData
{
+ /// <value>
+ /// Gets the list of objects.
+ /// </value>
IList<IObjectInFolderData> Objects { get; }
+
+ /// <value>
+ /// Gets whether there are more objects, if known.
+ /// </value>
bool? HasMoreItems { get; }
+
+ /// <value>
+ /// Gets total number of objects in the list, if known.
+ /// </value>
BigInteger? NumItems { get; }
}
+ /// <summary>
+ /// Tree node of objects in a folder.
+ /// </summary>
public interface IObjectInFolderContainer : IExtensionsData
{
+ /// <value>
+ /// Gets the object.
+ /// </value>
IObjectInFolderData Object { get; }
+
+ /// <value>
+ /// Gets the children of the object, if any.
+ /// </value>
IList<IObjectInFolderContainer> Children { get; }
}
+ /// <summary>
+ /// Object parent.
+ /// </summary>
public interface IObjectParentData : IExtensionsData
{
+ /// <value>
+ /// Gets the parent object.
+ /// </value>
IObjectData Object { get; }
+
+ /// <value>
+ /// Gets the relative path segment of the object in the parent folder.
+ /// </value>
string RelativePathSegment { get; }
}
diff --git a/PortCMISTests/SimpleCmisTest.cs b/PortCMISTests/SimpleCmisTest.cs
index 3481314..11568af 100644
--- a/PortCMISTests/SimpleCmisTest.cs
+++ b/PortCMISTests/SimpleCmisTest.cs
@@ -111,26 +111,14 @@
}
// create folder
- IDictionary<string, object> props = new Dictionary<string, object>();
- props[PropertyIds.Name] = "porttest";
- props[PropertyIds.ObjectTypeId] = "cmis:folder";
-
IFolder root = Session.GetRootFolder();
- IFolder newFolder = root.CreateFolder(props);
+ IFolder newFolder = CreateFolder(root, "porttest");
+
Assert.IsNotNull(newFolder);
// create document
- props = new Dictionary<string, object>();
- props[PropertyIds.Name] = "test.txt";
- props[PropertyIds.ObjectTypeId] = "cmis:document";
-
- byte[] contentBytes = Encoding.UTF8.GetBytes("Hello World");
-
- ContentStream content = new ContentStream();
- content.MimeType = "text/plain";
- content.Stream = new MemoryStream(contentBytes);
-
- IDocument newDoc = newFolder.CreateDocument(props, content, VersioningState.None);
+ string contentString = "Hello World";
+ IDocument newDoc = CreateTextDocument(newFolder, "test.txt", contentString);
Assert.IsNotNull(newDoc);
// get content
@@ -138,16 +126,9 @@
Assert.IsNotNull(newContent);
Assert.IsNotNull(newContent.Stream);
- MemoryStream memStream = new MemoryStream();
- newContent.Stream.CopyTo(memStream);
- byte[] newContentBytes = memStream.ToArray();
+ Assert.AreEqual(contentString, ConvertStreamToString(newContent.Stream));
- Assert.AreEqual(contentBytes.Length, newContentBytes.Length);
- for (int i = 0; i < contentBytes.Length; i++)
- {
- Assert.AreEqual(contentBytes[i], newContentBytes[i]);
- }
-
+ // fetch it again to get the updated content stream length property
IOperationContext ctxt = Session.CreateOperationContext();
ctxt.FilterString = "*";
ICmisObject newObj = Session.GetObject(newDoc, ctxt);
@@ -156,7 +137,7 @@
IDocument newDoc2 = (IDocument)newObj;
Assert.AreEqual(newDoc.Name, newDoc2.Name);
- Assert.AreEqual(contentBytes.Length, newDoc2.ContentStreamLength);
+ Assert.AreEqual(Encoding.UTF8.GetBytes(contentString).Length, newDoc2.ContentStreamLength);
// delete document
newDoc.Delete();
@@ -200,12 +181,8 @@
try
{
// create folder
- IDictionary<string, object> props = new Dictionary<string, object>();
- props[PropertyIds.Name] = name1;
- props[PropertyIds.ObjectTypeId] = "cmis:folder";
-
IFolder root = Session.GetRootFolder();
- newFolder = root.CreateFolder(props);
+ newFolder = CreateFolder(root, name1);
Assert.IsNotNull(newFolder);
IFolder newFolder2 = (IFolder)Session.GetObject(newFolder, oc);
@@ -237,6 +214,45 @@
}
[TestMethod]
+ public void TestUpdateContent()
+ {
+ IDocument doc = null;
+ try
+ {
+ // create document
+ string contentString1 = "11111";
+ doc = CreateTextDocument(Session.GetRootFolder(), "test.txt", contentString1);
+ Assert.IsNotNull(doc);
+
+ // get content
+ IContentStream content1 = doc.GetContentStream();
+ Assert.IsNotNull(content1);
+ Assert.IsNotNull(content1.Stream);
+
+ Assert.AreEqual(contentString1, ConvertStreamToString(content1.Stream));
+
+ // update content
+ string contentString2 = "22222";
+ doc.SetContentStream(ContentStreamUtils.CreateTextContentStream("test2.txt", contentString2), true);
+
+ // get content again
+ IContentStream content2 = doc.GetContentStream();
+ Assert.IsNotNull(content2);
+ Assert.IsNotNull(content2.Stream);
+
+ Assert.AreEqual(contentString2, ConvertStreamToString(content2.Stream));
+ }
+ finally
+ {
+ if (doc != null)
+ {
+ doc.Delete();
+ }
+ }
+ }
+
+
+ [TestMethod]
public void TestQuery()
{
if (Session.RepositoryInfo.Capabilities.QueryCapability == CapabilityQuery.None)
diff --git a/PortCMISTests/framework/TestFramework.cs b/PortCMISTests/framework/TestFramework.cs
index c2e429c..3970878 100644
--- a/PortCMISTests/framework/TestFramework.cs
+++ b/PortCMISTests/framework/TestFramework.cs
@@ -18,11 +18,15 @@
*/
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using PortCMIS;
using PortCMIS.Client;
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;
@@ -87,5 +91,48 @@
return session;
}
+
+ public IFolder CreateFolder(IFolder parent, string name)
+ {
+ IDictionary<string, object> props = new Dictionary<string, object>();
+ props[PropertyIds.Name] = name;
+ props[PropertyIds.ObjectTypeId] = "cmis:folder";
+
+ return parent.CreateFolder(props);
+ }
+
+ public IDocument CreateTextDocument(IFolder parent, string name, string content)
+ {
+ IDictionary<string, object> props = new Dictionary<string, object>();
+ props[PropertyIds.Name] = name;
+ props[PropertyIds.ObjectTypeId] = "cmis:document";
+
+ IContentStream contentStream = ContentStreamUtils.CreateTextContentStream(name, content);
+
+ return parent.CreateDocument(props, contentStream, VersioningState.None);
+ }
+
+ public byte[] ConvertStreamToByteArray(Stream stream)
+ {
+ MemoryStream memStream = new MemoryStream();
+ stream.CopyTo(memStream);
+ return memStream.ToArray();
+ }
+
+ public string ConvertStreamToString(Stream stream)
+ {
+ return Encoding.UTF8.GetString(ConvertStreamToByteArray(stream));
+ }
+
+ // --- asserts ---
+
+ public void AreEqual(byte[] ba1, byte[] ba2)
+ {
+ Assert.AreEqual(ba1.Length, ba2.Length);
+ for (int i = 0; i < ba1.Length; i++)
+ {
+ Assert.AreEqual(ba1[i], ba2[i]);
+ }
+ }
}
}