You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2015/07/20 10:48:59 UTC
svn commit: r1691890 [9/14] - in /chemistry/portcmis: ./ PortCMIS/
PortCMIS/Properties/ PortCMIS/binding/ PortCMIS/binding/atompub/
PortCMIS/binding/browser/ PortCMIS/binding/browser/json/ PortCMIS/client/
PortCMIS/const/ PortCMIS/data/ PortCMIS/enum/ ...
Added: chemistry/portcmis/PortCMIS/client/ClientImpl.cs
URL: http://svn.apache.org/viewvc/chemistry/portcmis/PortCMIS/client/ClientImpl.cs?rev=1691890&view=auto
==============================================================================
--- chemistry/portcmis/PortCMIS/client/ClientImpl.cs (added)
+++ chemistry/portcmis/PortCMIS/client/ClientImpl.cs Mon Jul 20 08:48:57 2015
@@ -0,0 +1,1625 @@
+/*
+* 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 PortCMIS.Binding;
+using PortCMIS.Binding.Services;
+using PortCMIS.Data;
+using PortCMIS.Enums;
+using PortCMIS.Exceptions;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Numerics;
+using System.Text;
+
+namespace PortCMIS.Client.Impl
+{
+ /// <summary>
+ /// Session factory implementation.
+ /// </summary>
+ public class SessionFactory : ISessionFactory
+ {
+ private SessionFactory()
+ {
+ }
+
+ public static SessionFactory NewInstance()
+ {
+ return new SessionFactory();
+ }
+
+ public ISession CreateSession(IDictionary<string, string> parameters)
+ {
+ return CreateSession(parameters, null, null, null);
+ }
+
+ public ISession CreateSession(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
+ {
+ Session session = new Session(parameters, objectFactory, authenticationProvider, cache);
+ session.Connect();
+
+ return session;
+ }
+
+ public IList<IRepository> GetRepositories(IDictionary<string, string> parameters)
+ {
+ return GetRepositories(parameters, null, null, null);
+ }
+
+ public IList<IRepository> GetRepositories(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
+ {
+ ICmisBinding binding = CmisBindingHelper.CreateBinding(parameters);
+
+ IList<IRepositoryInfo> repositoryInfos = binding.GetRepositoryService().GetRepositoryInfos(null);
+
+ IList<IRepository> result = new List<IRepository>();
+ foreach (IRepositoryInfo data in repositoryInfos)
+ {
+ result.Add(new Repository(data, parameters, this, objectFactory, binding.GetAuthenticationProvider(), cache));
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Binding helper class.
+ /// </summary>
+ internal class CmisBindingHelper
+ {
+ public static ICmisBinding CreateBinding(IDictionary<string, string> parameters)
+ {
+ return CreateBinding(parameters, null);
+ }
+
+ public static ICmisBinding CreateBinding(IDictionary<string, string> parameters, IAuthenticationProvider authenticationProvider)
+ {
+ if (parameters == null)
+ {
+ throw new ArgumentNullException("parameters");
+ }
+
+ if (!parameters.ContainsKey(SessionParameter.BindingType))
+ {
+ parameters[SessionParameter.BindingType] = BindingType.Custom;
+ }
+
+ string bt = parameters[SessionParameter.BindingType];
+ switch (bt)
+ {
+ case BindingType.AtomPub:
+ return CreateAtomPubBinding(parameters, authenticationProvider);
+ case BindingType.WebServices:
+ return CreateWebServiceBinding(parameters, authenticationProvider);
+ case BindingType.Browser:
+ return CreateBrowserBinding(parameters, authenticationProvider);
+ case BindingType.Custom:
+ return CreateCustomBinding(parameters, authenticationProvider);
+ default:
+ throw new CmisRuntimeException("Ambiguous session parameter: " + parameters);
+ }
+ }
+
+ private static ICmisBinding CreateCustomBinding(IDictionary<string, string> parameters, IAuthenticationProvider authenticationProvider)
+ {
+ CmisBindingFactory factory = CmisBindingFactory.NewInstance();
+ ICmisBinding binding = factory.CreateCmisBinding(parameters, authenticationProvider);
+
+ return binding;
+ }
+
+ private static ICmisBinding CreateWebServiceBinding(IDictionary<string, string> parameters, IAuthenticationProvider authenticationProvider)
+ {
+ CmisBindingFactory factory = CmisBindingFactory.NewInstance();
+ ICmisBinding binding = factory.CreateCmisWebServicesBinding(parameters, authenticationProvider);
+
+ return binding;
+ }
+
+ private static ICmisBinding CreateAtomPubBinding(IDictionary<string, string> parameters, IAuthenticationProvider authenticationProvider)
+ {
+ CmisBindingFactory factory = CmisBindingFactory.NewInstance();
+ ICmisBinding binding = factory.CreateCmisAtomPubBinding(parameters, authenticationProvider);
+
+ return binding;
+ }
+
+ private static ICmisBinding CreateBrowserBinding(IDictionary<string, string> parameters, IAuthenticationProvider authenticationProvider)
+ {
+ CmisBindingFactory factory = CmisBindingFactory.NewInstance();
+ ICmisBinding binding = factory.CreateCmisBrowserBinding(parameters, authenticationProvider);
+
+ return binding;
+ }
+ }
+
+ /// <summary>
+ /// Repository implementation.
+ /// </summary>
+ public class Repository : RepositoryInfo, IRepository
+ {
+ private IDictionary<string, string> parameters;
+ private SessionFactory sessionFactory;
+ private IObjectFactory objectFactory;
+ private IAuthenticationProvider authenticationProvider;
+ private ICache cache;
+
+ public Repository(IRepositoryInfo info, IDictionary<string, string> parameters, SessionFactory sessionFactory, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
+ : base(info)
+ {
+ this.parameters = new Dictionary<string, string>(parameters);
+ this.parameters[SessionParameter.RepositoryId] = Id;
+
+ this.sessionFactory = sessionFactory;
+ this.objectFactory = objectFactory;
+ this.authenticationProvider = authenticationProvider;
+ this.cache = cache;
+ }
+
+ public ISession CreateSession()
+ {
+ return sessionFactory.CreateSession(parameters, objectFactory, authenticationProvider, cache);
+ }
+ }
+
+ /// <summary>
+ /// Session implementation.
+ /// </summary>
+ public class Session : ISession
+ {
+ private static HashSet<Updatability> CreateUpdatability = new HashSet<Updatability>();
+ private static HashSet<Updatability> CreateAndCheckoutUpdatability = new HashSet<Updatability>();
+ static Session()
+ {
+ CreateUpdatability.Add(Updatability.OnCreate);
+ CreateUpdatability.Add(Updatability.ReadWrite);
+ CreateAndCheckoutUpdatability.Add(Updatability.OnCreate);
+ CreateAndCheckoutUpdatability.Add(Updatability.ReadWrite);
+ CreateAndCheckoutUpdatability.Add(Updatability.WhenCheckedOut);
+ }
+
+ protected static IOperationContext FallbackContext = new OperationContext(null, false, true, false, IncludeRelationships.None, null, true, null, true, 100);
+
+ protected IDictionary<string, string> parameters;
+ private object sessionLock = new object();
+
+ public ICmisBinding Binding { get; protected set; }
+ public IRepositoryInfo RepositoryInfo { get; protected set; }
+ public string RepositoryId { get { return RepositoryInfo.Id; } }
+
+ public IObjectFactory ObjectFactory { get; protected set; }
+ protected IAuthenticationProvider AuthenticationProvider { get; set; }
+ protected ICache Cache { get; set; }
+ protected bool cachePathOmit;
+
+ private IOperationContext context = FallbackContext;
+ public IOperationContext DefaultContext
+ {
+ get
+ {
+ lock (sessionLock)
+ {
+ return context;
+ }
+ }
+ set
+ {
+ lock (sessionLock)
+ {
+ context = (value == null ? FallbackContext : value);
+ }
+ }
+ }
+
+ public Session(IDictionary<string, string> parameters, IObjectFactory objectFactory, IAuthenticationProvider authenticationProvider, ICache cache)
+ {
+ if (parameters == null)
+ {
+ throw new ArgumentNullException("parameters");
+ }
+
+ this.parameters = parameters;
+
+ ObjectFactory = (objectFactory == null ? CreateObjectFactory() : objectFactory);
+ AuthenticationProvider = authenticationProvider;
+ Cache = (cache == null ? CreateCache() : cache);
+
+ string cachePathOmitStr;
+ if (parameters.TryGetValue(SessionParameter.CachePathOmit, out cachePathOmitStr))
+ {
+ cachePathOmit = cachePathOmitStr.ToLower() == "true";
+ }
+ else
+ {
+ cachePathOmit = false;
+ }
+ }
+
+ public void Connect()
+ {
+ lock (sessionLock)
+ {
+ Binding = CmisBindingHelper.CreateBinding(parameters, AuthenticationProvider);
+
+ string repositoryId;
+ if (!parameters.TryGetValue(SessionParameter.RepositoryId, out repositoryId))
+ {
+ throw new ArgumentException("Repository Id is not set!");
+ }
+
+ RepositoryInfo = Binding.GetRepositoryService().GetRepositoryInfo(repositoryId, null);
+ }
+ }
+
+ protected ICache CreateCache()
+ {
+ try
+ {
+ string typeName;
+ Type cacheType;
+
+ if (parameters.TryGetValue(SessionParameter.CacheClass, out typeName))
+ {
+ cacheType = Type.GetType(typeName);
+ }
+ else
+ {
+ cacheType = typeof(CmisObjectCache);
+ }
+
+ ICache cacheObject = Activator.CreateInstance(cacheType) as ICache;
+ if (cacheObject == null)
+ {
+ throw new Exception("Class does not implement ICache!");
+ }
+
+ cacheObject.Initialize(this, parameters);
+
+ return cacheObject;
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Unable to create cache: " + e, e);
+ }
+ }
+
+ protected IObjectFactory CreateObjectFactory()
+ {
+ try
+ {
+ string ofName;
+ Type ofType;
+
+ if (parameters.TryGetValue(SessionParameter.ObjectFactoryClass, out ofName))
+ {
+ ofType = Type.GetType(ofName);
+ }
+ else
+ {
+ ofType = typeof(ObjectFactory);
+ }
+
+ IObjectFactory ofObject = Activator.CreateInstance(ofType) as IObjectFactory;
+ if (ofObject == null)
+ {
+ throw new Exception("Class does not implement IObjectFactory!");
+ }
+
+ ofObject.Initialize(this, parameters);
+
+ return ofObject;
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Unable to create object factory: " + e, e);
+ }
+ }
+
+ public void Clear()
+ {
+ lock (sessionLock)
+ {
+ Cache = CreateCache();
+ Binding.ClearAllCaches();
+ }
+ }
+
+ // session context
+
+ public IOperationContext CreateOperationContext()
+ {
+ return new OperationContext();
+ }
+
+ public IOperationContext CreateOperationContext(HashSet<string> filter, bool includeAcls, bool includeAllowableActions, bool includePolicies,
+ IncludeRelationships includeRelationships, HashSet<string> renditionFilter, bool includePathSegments, string orderBy,
+ bool cacheEnabled, int maxItemsPerPage)
+ {
+ return new OperationContext(filter, includeAcls, includeAllowableActions, includePolicies, includeRelationships, renditionFilter,
+ includePathSegments, orderBy, cacheEnabled, maxItemsPerPage);
+ }
+
+ public IObjectId CreateObjectId(string id)
+ {
+ return new ObjectId(id);
+ }
+
+ // types
+
+ public IObjectType GetTypeDefinition(string typeId)
+ {
+ ITypeDefinition typeDefinition = Binding.GetRepositoryService().GetTypeDefinition(RepositoryId, typeId, null);
+ return ObjectFactory.ConvertTypeDefinition(typeDefinition);
+ }
+
+ public IItemEnumerable<IObjectType> GetTypeChildren(string typeId, bool includePropertyDefinitions)
+ {
+ IRepositoryService service = Binding.GetRepositoryService();
+
+ PageFetcher<IObjectType>.FetchPage fetchPageDelegate = delegate(BigInteger maxNumItems, BigInteger skipCount)
+ {
+ // fetch the data
+ ITypeDefinitionList tdl = service.GetTypeChildren(RepositoryId, typeId, includePropertyDefinitions, maxNumItems, skipCount, null);
+
+ // convert type definitions
+ int count = (tdl != null && tdl.List != null ? tdl.List.Count : 0);
+ IList<IObjectType> page = new List<IObjectType>(count);
+ if (count > 0)
+ {
+ foreach (ITypeDefinition typeDefinition in tdl.List)
+ {
+ page.Add(ObjectFactory.ConvertTypeDefinition(typeDefinition));
+ }
+ }
+
+ return new PageFetcher<IObjectType>.Page<IObjectType>(page, tdl.NumItems, tdl.HasMoreItems);
+ };
+
+ return new CollectionEnumerable<IObjectType>(new PageFetcher<IObjectType>(DefaultContext.MaxItemsPerPage, fetchPageDelegate));
+ }
+
+ public IList<ITree<IObjectType>> GetTypeDescendants(string typeId, int depth, bool includePropertyDefinitions)
+ {
+ IList<ITypeDefinitionContainer> descendants = Binding.GetRepositoryService().GetTypeDescendants(
+ RepositoryId, typeId, depth, includePropertyDefinitions, null);
+
+ return ConvertTypeDescendants(descendants);
+ }
+
+ private IList<ITree<IObjectType>> ConvertTypeDescendants(IList<ITypeDefinitionContainer> descendantsList)
+ {
+ if (descendantsList == null || descendantsList.Count == 0)
+ {
+ return null;
+ }
+
+ IList<ITree<IObjectType>> result = new List<ITree<IObjectType>>();
+
+ foreach (ITypeDefinitionContainer container in descendantsList)
+ {
+ Tree<IObjectType> tree = new Tree<IObjectType>();
+ tree.Item = ObjectFactory.ConvertTypeDefinition(container.TypeDefinition);
+ tree.Children = ConvertTypeDescendants(container.Children);
+
+ result.Add(tree);
+ }
+
+ return result;
+ }
+
+ // navigation
+
+ public IFolder GetRootFolder()
+ {
+ return GetRootFolder(DefaultContext);
+ }
+
+ public IFolder GetRootFolder(IOperationContext context)
+ {
+ IFolder rootFolder = GetObject(RepositoryInfo.RootFolderId, context) as IFolder;
+ if (rootFolder == null)
+ {
+ throw new CmisRuntimeException("Root folder object is not a folder!");
+ }
+
+ return rootFolder;
+ }
+
+ public IItemEnumerable<IDocument> GetCheckedOutDocs()
+ {
+ return GetCheckedOutDocs(DefaultContext);
+ }
+
+ public IItemEnumerable<IDocument> GetCheckedOutDocs(IOperationContext context)
+ {
+ INavigationService service = Binding.GetNavigationService();
+ IOperationContext ctxt = new OperationContext(context);
+
+ PageFetcher<IDocument>.FetchPage fetchPageDelegate = delegate(BigInteger maxNumItems, BigInteger skipCount)
+ {
+ // get all checked out documents
+ IObjectList checkedOutDocs = service.GetCheckedOutDocs(RepositoryId, null, ctxt.FilterString, ctxt.OrderBy,
+ ctxt.IncludeAllowableActions, ctxt.IncludeRelationships, ctxt.RenditionFilterString, maxNumItems, skipCount, null);
+
+ // convert objects
+ IList<IDocument> page = new List<IDocument>();
+ if (checkedOutDocs.Objects != null)
+ {
+ foreach (IObjectData objectData in checkedOutDocs.Objects)
+ {
+ IDocument doc = ObjectFactory.ConvertObject(objectData, ctxt) as IDocument;
+ if (doc == null)
+ {
+ // should not happen...
+ continue;
+ }
+
+ page.Add(doc);
+ }
+ }
+
+ return new PageFetcher<IDocument>.Page<IDocument>(page, checkedOutDocs.NumItems, checkedOutDocs.HasMoreItems);
+ };
+
+ return new CollectionEnumerable<IDocument>(new PageFetcher<IDocument>(DefaultContext.MaxItemsPerPage, fetchPageDelegate));
+ }
+
+ public ICmisObject GetObject(IObjectId objectId)
+ {
+ return GetObject(objectId, DefaultContext);
+ }
+
+ public ICmisObject GetObject(IObjectId objectId, IOperationContext context)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Object Id must be set!", "objectId");
+ }
+
+ return GetObject(objectId.Id, context);
+ }
+
+ public ICmisObject GetObject(string objectId)
+ {
+ return GetObject(objectId, DefaultContext);
+ }
+
+ public ICmisObject GetObject(string objectId, IOperationContext context)
+ {
+ if (objectId == null)
+ {
+ throw new ArgumentException("Object Id must be set!", "objectId");
+ }
+ if (context == null)
+ {
+ throw new ArgumentException("Operation context must be set!", "context");
+ }
+
+ ICmisObject result = null;
+
+ // ask the cache first
+ if (context.CacheEnabled)
+ {
+ result = Cache.GetById(objectId, context.CacheKey);
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ // get the object
+ IObjectData objectData = Binding.GetObjectService().GetObject(RepositoryId, objectId, context.FilterString,
+ context.IncludeAllowableActions, context.IncludeRelationships, context.RenditionFilterString, context.IncludePolicies,
+ context.IncludeAcls, null);
+
+ result = ObjectFactory.ConvertObject(objectData, context);
+
+ // put into cache
+ if (context.CacheEnabled)
+ {
+ Cache.Put(result, context.CacheKey);
+ }
+
+ return result;
+ }
+
+ public ICmisObject GetObjectByPath(string path)
+ {
+ return GetObjectByPath(path, DefaultContext);
+ }
+
+ public ICmisObject GetObjectByPath(string path, IOperationContext context)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException("path");
+ }
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ ICmisObject result = null;
+
+ // ask the cache first
+ if (context.CacheEnabled && !cachePathOmit)
+ {
+ result = Cache.GetByPath(path, context.CacheKey);
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ // get the object
+ IObjectData objectData = Binding.GetObjectService().GetObjectByPath(RepositoryId, path, context.FilterString,
+ context.IncludeAllowableActions, context.IncludeRelationships, context.RenditionFilterString, context.IncludePolicies,
+ context.IncludeAcls, null);
+
+ result = ObjectFactory.ConvertObject(objectData, context);
+
+ // put into cache
+ if (context.CacheEnabled)
+ {
+ Cache.PutPath(path, result, context.CacheKey);
+ }
+
+ return result;
+ }
+
+ public ICmisObject GetObjectByPath(string parentPath, string name)
+ {
+ return GetObjectByPath(parentPath, name, DefaultContext);
+ }
+
+ public ICmisObject GetObjectByPath(string parentPath, string name, IOperationContext context)
+ {
+ if (parentPath == null || parentPath.Length < 1)
+ {
+ throw new ArgumentException("Parent path must be set!", "parentPath");
+ }
+ if (parentPath[0] != '/')
+ {
+ throw new ArgumentException("Parent path must start with a '/'!", "parentPath");
+ }
+ if (name == null || name.Length < 1)
+ {
+ throw new ArgumentException("Name must be set!", "name");
+ }
+
+ StringBuilder path = new StringBuilder();
+ path.Append(parentPath);
+ if (!parentPath.EndsWith("/"))
+ {
+ path.Append('/');
+ }
+ path.Append(name);
+
+ return GetObjectByPath(path.ToString(), context);
+ }
+
+ public IDocument GetLatestDocumentVersion(string objectId)
+ {
+ return GetLatestDocumentVersion(objectId, DefaultContext);
+ }
+
+ public IDocument GetLatestDocumentVersion(string objectId, IOperationContext context)
+ {
+ if (objectId == null)
+ {
+ throw new ArgumentNullException("objectId");
+ }
+
+ return GetLatestDocumentVersion(CreateObjectId(objectId), false, context);
+ }
+
+ public IDocument GetLatestDocumentVersion(IObjectId objectId)
+ {
+ return GetLatestDocumentVersion(objectId, false, DefaultContext);
+ }
+
+ public IDocument GetLatestDocumentVersion(IObjectId objectId, IOperationContext context)
+ {
+ return GetLatestDocumentVersion(objectId, false, context);
+ }
+
+ public IDocument GetLatestDocumentVersion(IObjectId objectId, bool major, IOperationContext context)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentNullException("objectId");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ ICmisObject result = null;
+
+ string versionSeriesId = null;
+
+ // first attempt: if we got a Document object, try getting the version
+ // series ID from it
+ if (objectId is IDocument)
+ {
+ versionSeriesId = ((IDocument)objectId).VersionSeriesId;
+ }
+
+ // second attempt: if we have a Document object in the cache, retrieve
+ // the version series ID form there
+ if (versionSeriesId == null)
+ {
+ if (context.CacheEnabled)
+ {
+ ICmisObject sourceDoc = Cache.GetById(objectId.Id, context.CacheKey);
+ if (sourceDoc is IDocument)
+ {
+ versionSeriesId = ((IDocument)sourceDoc).VersionSeriesId;
+ }
+ }
+ }
+
+ // third attempt (Web Services only): get the version series ID from the
+ // repository
+ // (the AtomPub and Browser binding don't need the version series ID ->
+ // avoid roundtrip)
+ if (versionSeriesId == null)
+ {
+ string bindingType = Binding.BindingType;
+ if (bindingType == BindingType.WebServices || bindingType == BindingType.Custom)
+ {
+
+ // get the document to find the version series ID
+ IObjectData sourceObjectData = Binding.GetObjectService().GetObject(RepositoryId, objectId.Id,
+ PropertyIds.ObjectId + "," + PropertyIds.VersionSeriesId, false, IncludeRelationships.None,
+ "cmis:none", false, false, null);
+
+ if (sourceObjectData.Properties != null)
+ {
+ IPropertyData verionsSeriesIdProp = sourceObjectData.Properties[PropertyIds.VersionSeriesId];
+ if (verionsSeriesIdProp != null)
+ {
+ versionSeriesId = verionsSeriesIdProp.FirstValue as string;
+ }
+ }
+
+ // the Web Services binding needs the version series ID -> fail
+ if (versionSeriesId == null)
+ {
+ throw new ArgumentException("Object is not a document or not versionable!");
+ }
+ }
+ }
+
+ // get the object
+ IObjectData objectData = Binding.GetVersioningService().GetObjectOfLatestVersion(RepositoryId,
+ objectId.Id, versionSeriesId, major, context.FilterString,
+ context.IncludeAllowableActions, context.IncludeRelationships,
+ context.RenditionFilterString, context.IncludePolicies, context.IncludeAcls, null);
+
+ result = ObjectFactory.ConvertObject(objectData, context);
+
+ // put into cache
+ if (context.CacheEnabled)
+ {
+ Cache.Put(result, context.CacheKey);
+ }
+
+ // check result
+ if (!(result is IDocument))
+ {
+ throw new ArgumentException("Latest version is not a document!");
+ }
+
+ return result as IDocument;
+ }
+
+ public void RemoveObjectFromCache(IObjectId objectId)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ return;
+ }
+
+ RemoveObjectFromCache(objectId.Id);
+ }
+
+ public void RemoveObjectFromCache(string objectId)
+ {
+ Cache.Remove(objectId);
+ }
+
+ // discovery
+
+ public IItemEnumerable<IQueryResult> Query(string statement, bool searchAllVersions)
+ {
+ return Query(statement, searchAllVersions, DefaultContext);
+ }
+
+ public IItemEnumerable<IQueryResult> Query(string statement, bool searchAllVersions, IOperationContext context)
+ {
+ IDiscoveryService service = Binding.GetDiscoveryService();
+ IOperationContext ctxt = new OperationContext(context);
+
+ PageFetcher<IQueryResult>.FetchPage fetchPageDelegate = delegate(BigInteger maxNumItems, BigInteger skipCount)
+ {
+ // fetch the data
+ IObjectList resultList = service.Query(RepositoryId, statement, searchAllVersions, ctxt.IncludeAllowableActions,
+ ctxt.IncludeRelationships, ctxt.RenditionFilterString, maxNumItems, skipCount, null);
+
+ // convert query results
+ IList<IQueryResult> page = new List<IQueryResult>();
+ if (resultList.Objects != null)
+ {
+ foreach (IObjectData objectData in resultList.Objects)
+ {
+ if (objectData == null)
+ {
+ continue;
+ }
+
+ page.Add(ObjectFactory.ConvertQueryResult(objectData));
+ }
+ }
+
+ return new PageFetcher<IQueryResult>.Page<IQueryResult>(page, resultList.NumItems, resultList.HasMoreItems);
+ };
+
+ return new CollectionEnumerable<IQueryResult>(new PageFetcher<IQueryResult>(DefaultContext.MaxItemsPerPage, fetchPageDelegate));
+ }
+
+ public IItemEnumerable<ICmisObject> QueryObjects(string typeId, string where, bool searchAllVersions, IOperationContext context)
+ {
+ if (typeId == null || typeId.Trim().Length == 0)
+ {
+ throw new ArgumentException("Type ID must be set!", "typeId");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentException("Operation context must be set!", "context");
+ }
+
+ IDiscoveryService discoveryService = Binding.GetDiscoveryService();
+ IObjectFactory of = ObjectFactory;
+ OperationContext ctxt = new OperationContext(context);
+ StringBuilder statement = new StringBuilder("SELECT ");
+
+ string select = ctxt.FilterString;
+ if (select == null)
+ {
+ statement.Append('*');
+ }
+ else
+ {
+ statement.Append(select);
+ }
+
+ IObjectType type = GetTypeDefinition(typeId);
+ statement.Append(" FROM ");
+ statement.Append(type.QueryName);
+
+ if (where != null && where.Trim().Length > 0)
+ {
+ statement.Append(" WHERE ");
+ statement.Append(where);
+ }
+
+ string orderBy = ctxt.OrderBy;
+ if (orderBy != null && orderBy.Trim().Length > 0)
+ {
+ statement.Append(" ORDER BY ");
+ statement.Append(orderBy);
+ }
+
+ PageFetcher<ICmisObject>.FetchPage fetchPageDelegate = delegate(BigInteger maxNumItems, BigInteger skipCount)
+ {
+ // fetch the data
+ IObjectList resultList = discoveryService.Query(RepositoryId, statement.ToString(),
+ searchAllVersions, ctxt.IncludeAllowableActions, ctxt.IncludeRelationships,
+ ctxt.RenditionFilterString, maxNumItems, skipCount, null);
+
+ // convert query results
+ IList<ICmisObject> page = new List<ICmisObject>();
+ if (resultList.Objects != null)
+ {
+ foreach (IObjectData objectData in resultList.Objects)
+ {
+ if (objectData == null)
+ {
+ continue;
+ }
+
+ page.Add(of.ConvertObject(objectData, ctxt));
+ }
+ }
+
+ return new PageFetcher<ICmisObject>.Page<ICmisObject>(page, resultList.NumItems, resultList.HasMoreItems);
+ };
+
+ return new CollectionEnumerable<ICmisObject>(new PageFetcher<ICmisObject>(DefaultContext.MaxItemsPerPage, fetchPageDelegate));
+ }
+
+ public IQueryStatement CreateQueryStatement(string statement)
+ {
+ return new QueryStatement(this, statement);
+ }
+
+ public string GetLatestChangeLogToken()
+ {
+ return Binding.GetRepositoryService().GetRepositoryInfo(RepositoryId, null).LatestChangeLogToken;
+ }
+
+ public IChangeEvents GetContentChanges(string changeLogToken, bool includeProperties, long maxNumItems)
+ {
+ return GetContentChanges(changeLogToken, includeProperties, maxNumItems, DefaultContext);
+ }
+
+ public IChangeEvents GetContentChanges(string changeLogToken, bool includeProperties, long maxNumItems,
+ IOperationContext context)
+ {
+ lock (sessionLock)
+ {
+ IObjectList objectList = Binding.GetDiscoveryService().GetContentChanges(RepositoryId, ref changeLogToken, includeProperties,
+ context.FilterString, context.IncludePolicies, context.IncludeAcls, maxNumItems, null);
+
+ return ObjectFactory.ConvertChangeEvents(changeLogToken, objectList);
+ }
+ }
+
+ // create
+
+ public IObjectId CreateDocument(IDictionary<string, object> properties, IObjectId folderId, IContentStream contentStream,
+ VersioningState? versioningState, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces)
+ {
+ if (properties == null || properties.Count == 0)
+ {
+ throw new ArgumentException("Properties must not be empty!");
+ }
+
+ string newId = Binding.GetObjectService().CreateDocument(RepositoryId, ObjectFactory.ConvertProperties(properties, null, null,
+ (versioningState == VersioningState.CheckedOut ? CreateAndCheckoutUpdatability : CreateUpdatability)),
+ (folderId == null ? null : folderId.Id), contentStream, versioningState, ObjectFactory.ConvertPolicies(policies),
+ ObjectFactory.ConvertAces(addAces), ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreateDocument(IDictionary<string, object> properties, IObjectId folderId, IContentStream contentStream,
+ VersioningState? versioningState)
+ {
+ return CreateDocument(properties, folderId, contentStream, versioningState, null, null, null);
+ }
+
+ public IObjectId CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, IObjectId folderId,
+ VersioningState? versioningState, IList<IPolicy> policies, IList<IAce> addAces, IList<IAce> removeAces)
+ {
+ if (source == null || source.Id == null)
+ {
+ throw new ArgumentException("Source must be set!");
+ }
+
+ // get the type of the source document
+ IObjectType type = null;
+ IList<ISecondaryType> secondaryTypes = null;
+ if (source is ICmisObject)
+ {
+ type = ((ICmisObject)source).ObjectType;
+ secondaryTypes = ((ICmisObject)source).SecondaryTypes;
+ }
+ else
+ {
+ ICmisObject sourceObj = GetObject(source);
+ type = sourceObj.ObjectType;
+ secondaryTypes = sourceObj.SecondaryTypes;
+ }
+
+ if (type.BaseTypeId != BaseTypeId.CmisDocument)
+ {
+ throw new ArgumentException("Source object must be a document!");
+ }
+
+ string newId = Binding.GetObjectService().CreateDocumentFromSource(RepositoryId, source.Id,
+ ObjectFactory.ConvertProperties(properties, type, secondaryTypes,
+ (versioningState == VersioningState.CheckedOut ? CreateAndCheckoutUpdatability : CreateUpdatability)),
+ (folderId == null ? null : folderId.Id),
+ versioningState, ObjectFactory.ConvertPolicies(policies), ObjectFactory.ConvertAces(addAces),
+ ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreateDocumentFromSource(IObjectId source, IDictionary<string, object> properties, IObjectId folderId,
+ VersioningState? versioningState)
+ {
+ return CreateDocumentFromSource(source, properties, folderId, versioningState, null, null, null);
+ }
+
+ public IObjectId CreateFolder(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies,
+ IList<IAce> addAces, IList<IAce> removeAces)
+ {
+ if (folderId == null || folderId.Id == null)
+ {
+ throw new ArgumentException("Folder ID must be set!");
+ }
+ if (properties == null || properties.Count == 0)
+ {
+ throw new ArgumentException("Properties must not be empty!");
+ }
+
+ string newId = Binding.GetObjectService().CreateFolder(RepositoryId, ObjectFactory.ConvertProperties(properties, null, null, CreateUpdatability),
+ (folderId == null ? null : folderId.Id), ObjectFactory.ConvertPolicies(policies), ObjectFactory.ConvertAces(addAces),
+ ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreateFolder(IDictionary<string, object> properties, IObjectId folderId)
+ {
+ return CreateFolder(properties, folderId, null, null, null);
+ }
+
+ public IObjectId CreatePolicy(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies,
+ IList<IAce> addAces, IList<IAce> removeAces)
+ {
+ if (properties == null || properties.Count == 0)
+ {
+ throw new ArgumentException("Properties must not be empty!");
+ }
+
+ string newId = Binding.GetObjectService().CreatePolicy(RepositoryId, ObjectFactory.ConvertProperties(properties, null, null, CreateUpdatability),
+ (folderId == null ? null : folderId.Id), ObjectFactory.ConvertPolicies(policies), ObjectFactory.ConvertAces(addAces),
+ ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreatePolicy(IDictionary<string, object> properties, IObjectId folderId)
+ {
+ return CreatePolicy(properties, folderId, null, null, null);
+ }
+
+ public IObjectId CreateItem(IDictionary<string, object> properties, IObjectId folderId, IList<IPolicy> policies, IList<IAce> addAces,
+ IList<IAce> removeAces)
+ {
+ if (properties == null || properties.Count == 0)
+ {
+ throw new ArgumentException("Properties must not be empty!");
+ }
+
+ string newId = Binding.GetObjectService().CreateItem(RepositoryId, ObjectFactory.ConvertProperties(properties, null, null, CreateUpdatability),
+ (folderId == null ? null : folderId.Id), ObjectFactory.ConvertPolicies(policies), ObjectFactory.ConvertAces(addAces),
+ ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreateItem(IDictionary<string, object> properties, IObjectId folderId)
+ {
+ return CreateItem(properties, folderId, null, null, null);
+ }
+
+ public IObjectId CreateRelationship(IDictionary<string, object> properties, IList<IPolicy> policies, IList<IAce> addAces,
+ IList<IAce> removeAces)
+ {
+ if (properties == null || properties.Count == 0)
+ {
+ throw new ArgumentException("Properties must not be empty!");
+ }
+
+ string newId = Binding.GetObjectService().CreateRelationship(RepositoryId, ObjectFactory.ConvertProperties(properties, null, null, CreateUpdatability),
+ ObjectFactory.ConvertPolicies(policies), ObjectFactory.ConvertAces(addAces), ObjectFactory.ConvertAces(removeAces), null);
+
+ return newId == null ? null : CreateObjectId(newId);
+ }
+
+ public IObjectId CreateRelationship(IDictionary<string, object> properties)
+ {
+ return CreateRelationship(properties, null, null, null);
+ }
+
+ public IItemEnumerable<IRelationship> GetRelationships(IObjectId objectId, bool includeSubRelationshipTypes,
+ RelationshipDirection? relationshipDirection, IObjectType type, IOperationContext context)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!");
+ }
+
+ string id = objectId.Id;
+ string typeId = (type == null ? null : type.Id);
+ IRelationshipService service = Binding.GetRelationshipService();
+ IOperationContext ctxt = new OperationContext(context);
+
+ PageFetcher<IRelationship>.FetchPage fetchPageDelegate = delegate(BigInteger maxNumItems, BigInteger skipCount)
+ {
+ // fetch the relationships
+ IObjectList relList = service.GetObjectRelationships(RepositoryId, id, includeSubRelationshipTypes, relationshipDirection,
+ typeId, ctxt.FilterString, ctxt.IncludeAllowableActions, maxNumItems, skipCount, null);
+
+ // convert relationship objects
+ IList<IRelationship> page = new List<IRelationship>();
+ if (relList.Objects != null)
+ {
+ foreach (IObjectData rod in relList.Objects)
+ {
+ IRelationship relationship = GetObject(CreateObjectId(rod.Id), ctxt) as IRelationship;
+ if (relationship == null)
+ {
+ throw new CmisRuntimeException("Repository returned an object that is not a relationship!");
+ }
+
+ page.Add(relationship);
+ }
+ }
+
+ return new PageFetcher<IRelationship>.Page<IRelationship>(page, relList.NumItems, relList.HasMoreItems);
+ };
+
+ return new CollectionEnumerable<IRelationship>(new PageFetcher<IRelationship>(DefaultContext.MaxItemsPerPage, fetchPageDelegate));
+ }
+
+ // delete
+ public void Delete(IObjectId objectId)
+ {
+ Delete(objectId, true);
+ }
+
+ public void Delete(IObjectId objectId, bool allVersions)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!", "objectId");
+ }
+
+ Binding.GetObjectService().DeleteObject(RepositoryId, objectId.Id, allVersions, null);
+ RemoveObjectFromCache(objectId);
+ }
+
+ // content stream
+ public IContentStream GetContentStream(IObjectId docId)
+ {
+ return GetContentStream(docId, null, null, null);
+ }
+
+ public IContentStream GetContentStream(IObjectId docId, string streamId, long? offset, long? length)
+ {
+ if (docId == null || docId.Id == null)
+ {
+ throw new ArgumentException("Invalid document ID!", "objectId");
+ }
+
+ // get the content stream
+ IContentStream contentStream = null;
+ try
+ {
+ contentStream = Binding.GetObjectService().GetContentStream(RepositoryId, docId.Id, streamId, offset, length, null);
+ }
+ catch (CmisConstraintException)
+ {
+ // no content stream
+ return null;
+ }
+
+ return contentStream;
+ }
+
+ // permissions
+
+ public IAcl GetAcl(IObjectId objectId, bool onlyBasicPermissions)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!", "objectId");
+ }
+
+ return Binding.GetAclService().GetAcl(RepositoryId, objectId.Id, onlyBasicPermissions, null);
+ }
+
+ public IAcl ApplyAcl(IObjectId objectId, IList<IAce> addAces, IList<IAce> removeAces, AclPropagation? aclPropagation)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!", "objectId");
+ }
+
+ return Binding.GetAclService().ApplyAcl(RepositoryId, objectId.Id, ObjectFactory.ConvertAces(addAces),
+ ObjectFactory.ConvertAces(removeAces), aclPropagation, null);
+ }
+
+ public void ApplyPolicy(IObjectId objectId, params IObjectId[] policyIds)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!", "objectId");
+ }
+ if (policyIds == null || (policyIds.Length == 0))
+ {
+ throw new ArgumentException("No Policies provided!");
+ }
+
+ string[] ids = new string[policyIds.Length];
+ for (int i = 0; i < policyIds.Length; i++)
+ {
+ if (policyIds[i] == null || policyIds[i].Id == null)
+ {
+ throw new ArgumentException("A Policy ID is not set!", "policyIds");
+ }
+
+ ids[i] = policyIds[i].Id;
+ }
+
+ foreach (string id in ids)
+ {
+ Binding.GetPolicyService().ApplyPolicy(RepositoryId, id, objectId.Id, null);
+ }
+ }
+
+ public void RemovePolicy(IObjectId objectId, params IObjectId[] policyIds)
+ {
+ if (objectId == null || objectId.Id == null)
+ {
+ throw new ArgumentException("Invalid object ID!", "objectId");
+ }
+ if (policyIds == null || policyIds.Length == 0)
+ {
+ throw new ArgumentException("No Policies provided!", "policyIds");
+ }
+
+ string[] ids = new string[policyIds.Length];
+ for (int i = 0; i < policyIds.Length; i++)
+ {
+ if (policyIds[i] == null || policyIds[i].Id == null)
+ {
+ throw new ArgumentException("A Policy Id is not set!");
+ }
+
+ ids[i] = policyIds[i].Id;
+ }
+
+ foreach (string id in ids)
+ {
+ Binding.GetPolicyService().RemovePolicy(RepositoryId, id, objectId.Id, null);
+ }
+ }
+ }
+
+ public class QueryStatement : IQueryStatement
+ {
+ private ISession session;
+ private string statement;
+ private IDictionary<int, string> parametersDict = new Dictionary<int, string>();
+
+ public QueryStatement(Session session, string statement)
+ {
+ if (session == null)
+ {
+ throw new ArgumentNullException("session");
+ }
+
+ if (statement == null)
+ {
+ throw new ArgumentNullException("statement");
+ }
+
+ this.session = session;
+ this.statement = statement.Trim();
+ }
+
+ public void SetType(int parameterIndex, string typeId)
+ {
+ SetType(parameterIndex, session.GetTypeDefinition(typeId));
+ }
+
+ public void SetType(int parameterIndex, IObjectType type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentException("Type must be set!");
+ }
+
+ if (type.QueryName == null)
+ {
+ throw new ArgumentException("Type has no query name!");
+ }
+
+ parametersDict[parameterIndex] = type.QueryName;
+ }
+
+ public void SetProperty(int parameterIndex, string typeId, string propertyId)
+ {
+ IObjectType type = session.GetTypeDefinition(typeId);
+
+ IPropertyDefinition propertyDefinition = type[propertyId];
+ if (propertyDefinition == null)
+ {
+ throw new ArgumentException("Property does not exist!");
+ }
+
+ SetProperty(parameterIndex, propertyDefinition);
+ }
+
+ public void SetProperty(int parameterIndex, IPropertyDefinition propertyDefinition)
+ {
+ if (propertyDefinition == null)
+ {
+ throw new ArgumentException("Property must be set!");
+ }
+
+ string queryName = propertyDefinition.QueryName;
+ if (queryName == null)
+ {
+ throw new ArgumentException("Property has no query name!");
+ }
+
+ parametersDict[parameterIndex] = queryName;
+ }
+
+ public void SetInteger(int parameterIndex, params BigInteger[] num)
+ {
+ if (num == null || num.Length == 0)
+ {
+ throw new ArgumentException("Number must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (BigInteger n in num)
+ {
+ if (n == null)
+ {
+ throw new ArgumentException("Number is null!");
+ }
+
+ slb.Add(n.ToString("#", CultureInfo.InvariantCulture));
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetDecimal(int parameterIndex, params decimal[] num)
+ {
+ if (num == null || num.Length == 0)
+ {
+ throw new ArgumentException("Number must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (decimal n in num)
+ {
+ slb.Add(n.ToString("#", CultureInfo.InvariantCulture));
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetString(int parameterIndex, params string[] str)
+ {
+ if (str == null || str.Length == 0)
+ {
+ throw new ArgumentException("String must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (string s in str)
+ {
+ if (s == null)
+ {
+ throw new ArgumentException("String is null!");
+ }
+
+ slb.Add(Escape(s));
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetStringLike(int parameterIndex, string str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentException("String must be set!");
+ }
+
+ parametersDict[parameterIndex] = EscapeLike(str);
+ }
+
+ public void SetStringContains(int parameterIndex, string str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentException("String must be set!");
+ }
+
+ parametersDict[parameterIndex] = EscapeContains(str);
+ }
+
+ public void SetId(int parameterIndex, params IObjectId[] id)
+ {
+ if (id == null || id.Length == 0)
+ {
+ throw new ArgumentException("Id must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (IObjectId oid in id)
+ {
+ if (oid == null || oid.Id == null)
+ {
+ throw new ArgumentException("Id is null!");
+ }
+
+ slb.Add(Escape(oid.Id));
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetUri(int parameterIndex, params Uri[] uri)
+ {
+ if (uri == null || uri.Length == 0)
+ {
+ throw new ArgumentException("URI must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (Uri u in uri)
+ {
+ if (u == null)
+ {
+ throw new ArgumentException("URI is null!");
+ }
+
+ slb.Add(Escape(u.ToString()));
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetBoolean(int parameterIndex, params bool[] boolean)
+ {
+ if (boolean == null || boolean.Length == 0)
+ {
+ throw new ArgumentException("Boolean must be set!");
+ }
+
+ StringListBuilder slb = new StringListBuilder(",");
+ foreach (bool b in boolean)
+ {
+ slb.Add(b ? "TRUE" : "FALSE");
+ }
+
+ parametersDict[parameterIndex] = slb.ToString();
+ }
+
+ public void SetDateTime(int parameterIndex, params DateTime[] dt)
+ {
+ SetDateTime(parameterIndex, false, dt);
+ }
+
+ public void SetDateTime(int parameterIndex, params long[] ms)
+ {
+ SetDateTime(parameterIndex, false, ms);
+ }
+
+ public void SetDateTimeTimestamp(int parameterIndex, params DateTime[] dt)
+ {
+ SetDateTime(parameterIndex, true, dt);
+ }
+
+ public void SetDateTimeTimestamp(int parameterIndex, params long[] ms)
+ {
+ SetDateTime(parameterIndex, true, ms);
+ }
+
+ protected void SetDateTime(int parameterIndex, bool prefix, params DateTime[] cal)
+ {
+ if (cal == null || cal.Length == 0)
+ {
+ throw new ArgumentException("DateTime must be set!");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ foreach (DateTime dt in cal)
+ {
+ if (dt == null)
+ {
+ throw new ArgumentException("DateTime is null!");
+ }
+
+ if (sb.Length > 0)
+ {
+ sb.Append(',');
+ }
+
+ if (prefix)
+ {
+ sb.Append("TIMESTAMP ");
+ }
+
+ DateTime tmp = dt.ToUniversalTime();
+ sb.Append("'");
+ sb.Append(tmp.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'", CultureInfo.InvariantCulture));
+ sb.Append("'");
+ }
+
+ parametersDict[parameterIndex] = sb.ToString();
+ }
+
+ protected void SetDateTime(int parameterIndex, bool prefix, params long[] ms)
+ {
+ if (ms == null || ms.Length == 0)
+ {
+ throw new ArgumentException("DateTime must be set!");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ foreach (long dt in ms)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(',');
+ }
+
+ if (prefix)
+ {
+ sb.Append("TIMESTAMP ");
+ }
+
+ DateTime tmp = DateTimeHelper.ConvertMillisToDateTime(dt).ToUniversalTime();
+ sb.Append("'");
+ sb.Append(tmp.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'", CultureInfo.InvariantCulture));
+ sb.Append("'");
+ }
+
+ parametersDict[parameterIndex] = sb.ToString();
+ }
+
+ public string ToQueryString()
+ {
+ bool inStr = false;
+ int parameterIndex = 0;
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < statement.Length; i++)
+ {
+ char c = statement[i];
+
+ if (c == '\'')
+ {
+ if (inStr && statement[i - 1] == '\\')
+ {
+ inStr = true;
+ }
+ else
+ {
+ inStr = !inStr;
+ }
+ sb.Append(c);
+ }
+ else if (c == '?' && !inStr)
+ {
+ parameterIndex++;
+ string s;
+ if (parametersDict.TryGetValue(parameterIndex, out s))
+ {
+ sb.Append(s);
+ }
+ else
+ {
+ sb.Append(c);
+ }
+ }
+ else
+ {
+ sb.Append(c);
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ public IItemEnumerable<IQueryResult> Query(bool searchAllVersions)
+ {
+ return session.Query(ToQueryString(), searchAllVersions);
+ }
+
+ public IItemEnumerable<IQueryResult> Query(bool searchAllVersions, IOperationContext context)
+ {
+ return session.Query(ToQueryString(), searchAllVersions, context);
+ }
+
+ // --- internal ---
+
+ private static string Escape(string str)
+ {
+ StringBuilder sb = new StringBuilder("'");
+ for (int i = 0; i < str.Length; i++)
+ {
+ char c = str[i];
+
+ if (c == '\'' || c == '\\')
+ {
+ sb.Append('\\');
+ }
+
+ sb.Append(c);
+ }
+
+ sb.Append('\'');
+
+ return sb.ToString();
+ }
+
+ private static string EscapeLike(string str)
+ {
+ StringBuilder sb = new StringBuilder("'");
+ for (int i = 0; i < str.Length; i++)
+ {
+ char c = str[i];
+
+ if (c == '\'')
+ {
+ sb.Append('\\');
+ }
+ else if (c == '\\')
+ {
+ if (i + 1 < str.Length && (str[i + 1] == '%' || str[i + 1] == '_'))
+ {
+ // no additional back slash
+ }
+ else
+ {
+ sb.Append('\\');
+ }
+ }
+
+ sb.Append(c);
+ }
+
+ sb.Append('\'');
+
+ return sb.ToString();
+ }
+
+ private static string EscapeContains(string str)
+ {
+ StringBuilder sb = new StringBuilder("'");
+ for (int i = 0; i < str.Length; i++)
+ {
+ char c = str[i];
+
+ if (c == '\\')
+ {
+ sb.Append('\\');
+ }
+ else if (c == '\'' || c == '\"')
+ {
+ sb.Append("\\\\\\");
+ }
+
+ sb.Append(c);
+ }
+
+ sb.Append('\'');
+
+ return sb.ToString();
+ }
+ }
+}