﻿/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using DotCMIS.Binding.Impl;
using DotCMIS.Binding.Services;
using DotCMIS.CMISWebServicesReference;
using DotCMIS.Data;
using DotCMIS.Data.Extensions;
using DotCMIS.Exceptions;
using DotCMIS.Enums;

namespace DotCMIS.Binding.AtomPub
{
    /// <summary>
    /// AtomPub binding SPI.
    /// </summary>
    internal class CmisAtomPubSpi : ICmisSpi
    {
        private RepositoryService repositoryService;
        private NavigationService navigationService;
        private ObjectService objectService;
        private VersioningService versioningService;
        private DiscoveryService discoveryService;
        private MultiFilingService multiFilingService;
        private RelationshipService relationshipService;
        private PolicyService policyService;
        private AclService aclService;

        public void initialize(BindingSession session)
        {
            repositoryService = new RepositoryService(session);
            navigationService = new NavigationService(session);
            objectService = new ObjectService(session);
            versioningService = new VersioningService(session);
            discoveryService = new DiscoveryService(session);
            multiFilingService = new MultiFilingService(session);
            relationshipService = new RelationshipService(session);
            policyService = new PolicyService(session);
            aclService = new AclService(session);
        }

        public IRepositoryService GetRepositoryService()
        {
            return repositoryService;
        }

        public INavigationService GetNavigationService()
        {
            return navigationService;
        }

        public IObjectService GetObjectService()
        {
            return objectService;
        }

        public IVersioningService GetVersioningService()
        {
            return versioningService;
        }

        public IRelationshipService GetRelationshipService()
        {
            return relationshipService;
        }

        public IDiscoveryService GetDiscoveryService()
        {
            return discoveryService;
        }

        public IMultiFilingService GetMultiFilingService()
        {
            return multiFilingService;
        }

        public IAclService GetAclService()
        {
            return aclService;
        }

        public IPolicyService GetPolicyService()
        {
            return policyService;
        }

        public void ClearAllCaches()
        {
            // nothing to do
        }

        public void ClearRepositoryCache(string repositoryId)
        {
            // nothing to do
        }

        public void Dispose()
        {
            // nothing to do
        }
    }

    internal abstract class AbstractAtomPubService
    {
        protected const string NameCollection = "collection";
        protected const string NameURITemplate = "uritemplate";
        protected const string NamePathSegment = "pathSegment";
        protected const string NameRelativePathSegment = "relativePathSegment";
        protected const string NameNumItems = "numItems";

        private const string SessionLinkCache = "org.apache.chemistry.dotcmis.binding.atompub.linkcache";

        protected enum IdentifierType
        {
            Id, Path
        };

        protected BindingSession Session { get; set; }


        // ---- link cache ----

        protected LinkCache GetLinkCache()
        {
            LinkCache linkCache = (LinkCache)Session.GetValue(SessionLinkCache);
            if (linkCache == null)
            {
                linkCache = new LinkCache(Session);
                Session.PutValue(SessionLinkCache, linkCache);
            }

            return linkCache;
        }

        protected string GetLink(string repositoryId, string id, string rel, string type)
        {
            if (repositoryId == null)
            {
                throw new CmisInvalidArgumentException("Repository id must be set!");
            }

            if (id == null)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            return GetLinkCache().GetLink(repositoryId, id, rel, type);
        }

        protected string GetLink(string repositoryId, string id, string rel)
        {
            return GetLink(repositoryId, id, rel, null);
        }

        protected string LoadLink(string repositoryId, string id, string rel, string type)
        {
            string link = GetLink(repositoryId, id, rel, type);
            if (link == null)
            {
                GetObjectInternal(repositoryId, IdentifierType.Id, id, ReturnVersion.This, null, null, null, null, null, null, null);
                link = GetLink(repositoryId, id, rel, type);
            }

            return link;
        }

        protected void AddLink(string repositoryId, string id, string rel, string type, string link)
        {
            GetLinkCache().AddLink(repositoryId, id, rel, type, link);
        }

        protected void AddLink(string repositoryId, string id, AtomLink link)
        {
            GetLinkCache().AddLink(repositoryId, id, link.Rel, link.Type, link.Href);
        }

        protected void RemoveLinks(string repositoryId, string id)
        {
            GetLinkCache().RemoveLinks(repositoryId, id);
        }

        protected void LockLinks()
        {
            GetLinkCache().LockLinks();
        }

        protected void UnlockLinks()
        {
            GetLinkCache().UnlockLinks();
        }

        protected string GetTypeLink(string repositoryId, string typeId, string rel, string type)
        {
            if (repositoryId == null)
            {
                throw new CmisInvalidArgumentException("Repository id must be set!");
            }

            if (typeId == null)
            {
                throw new CmisInvalidArgumentException("Type id must be set!");
            }

            return GetLinkCache().GetTypeLink(repositoryId, typeId, rel, type);
        }

        protected string GetTypeLink(string repositoryId, string typeId, string rel)
        {
            return GetTypeLink(repositoryId, typeId, rel, null);
        }

        protected string LoadTypeLink(string repositoryId, string typeId, string rel, string type)
        {
            string link = GetTypeLink(repositoryId, typeId, rel, type);
            if (link == null)
            {
                GetTypeDefinitionInternal(repositoryId, typeId);
                link = GetTypeLink(repositoryId, typeId, rel, type);
            }

            return link;
        }

        protected void AddTypeLink(string repositoryId, string typeId, string rel, string type, string link)
        {
            GetLinkCache().AddTypeLink(repositoryId, typeId, rel, type, link);
        }

        protected void AddTypeLink(string repositoryId, string typeId, AtomLink link)
        {
            GetLinkCache().AddTypeLink(repositoryId, typeId, link.Rel, link.Type, link.Href);
        }

        protected void RemoveTypeLinks(string repositoryId, string id)
        {
            GetLinkCache().RemoveTypeLinks(repositoryId, id);
        }

        protected void LockTypeLinks()
        {
            GetLinkCache().LockTypeLinks();
        }

        protected void UnlockTypeLinks()
        {
            GetLinkCache().UnlockTypeLinks();
        }

        protected string GetCollection(string repositoryId, string collection)
        {
            return GetLinkCache().GetCollection(repositoryId, collection);
        }

        protected string LoadCollection(string repositoryId, string collection)
        {
            string link = GetCollection(repositoryId, collection);
            if (link == null)
            {
                GetRepositoriesInternal(repositoryId);
                link = GetCollection(repositoryId, collection);
            }

            return link;
        }

        protected void AddCollection(string repositoryId, string collection, string link)
        {
            GetLinkCache().AddCollection(repositoryId, collection, link);
        }

        protected void AddCollection(string repositoryId, IDictionary<string, string> colDict)
        {
            string collection = null;
            colDict.TryGetValue("collectionType", out collection);

            string link = null;
            colDict.TryGetValue("href", out link);

            AddCollection(repositoryId, collection, link);
        }

        protected string GetRepositoryLink(string repositoryId, string rel)
        {
            return GetLinkCache().GetRepositoryLink(repositoryId, rel);
        }

        protected string LoadRepositoryLink(string repositoryId, string rel)
        {
            string link = GetRepositoryLink(repositoryId, rel);
            if (link == null)
            {
                GetRepositoriesInternal(repositoryId);
                link = GetRepositoryLink(repositoryId, rel);
            }

            return link;
        }

        protected void AddRepositoryLink(string repositoryId, string rel, string link)
        {
            GetLinkCache().AddRepositoryLink(repositoryId, rel, link);
        }

        protected void AddRepositoryLink(string repositoryId, AtomLink link)
        {
            AddRepositoryLink(repositoryId, link.Rel, link.Href);
        }

        protected string GetTemplateLink(string repositoryId, string type, IDictionary<string, object> parameters)
        {
            return GetLinkCache().GetTemplateLink(repositoryId, type, parameters);
        }

        protected string LoadTemplateLink(string repositoryId, string type, IDictionary<string, object> parameters)
        {
            string link = GetTemplateLink(repositoryId, type, parameters);
            if (link == null)
            {
                GetRepositoriesInternal(repositoryId);
                link = GetTemplateLink(repositoryId, type, parameters);
            }

            return link;
        }

        protected void AddTemplate(string repositoryId, string type, string link)
        {
            GetLinkCache().AddTemplate(repositoryId, type, link);
        }

        protected void AddTemplate(string repositoryId, IDictionary<string, string> tempDict)
        {
            string type = null;
            tempDict.TryGetValue("type", out type);

            string template = null;
            tempDict.TryGetValue("template", out template);

            AddTemplate(repositoryId, type, template);
        }

        // ---- exceptions ----

        protected CmisBaseException ConvertStatusCode(HttpStatusCode code, string message, string errorContent, Exception e)
        {
            switch (code)
            {
                case HttpStatusCode.BadRequest:
                    return new CmisInvalidArgumentException(message, errorContent, e);
                case HttpStatusCode.NotFound:
                    return new CmisObjectNotFoundException(message, errorContent, e);
                case HttpStatusCode.Forbidden:
                    return new CmisPermissionDeniedException(message, errorContent, e);
                case HttpStatusCode.MethodNotAllowed:
                    return new CmisNotSupportedException(message, errorContent, e);
                case HttpStatusCode.Conflict:
                    return new CmisConstraintException(message, errorContent, e);
                default:
                    return new CmisRuntimeException(message, errorContent, e);
            }
        }

        protected void ThrowLinkException(String repositoryId, String id, String rel, String type)
        {
            int index = GetLinkCache().CheckLink(repositoryId, id, rel, type);

            switch (index)
            {
                case 0:
                    throw new CmisObjectNotFoundException("Unknown repository!");
                case 1:
                    throw new CmisObjectNotFoundException("Unknown object!");
                case 2:
                    throw new CmisNotSupportedException("Operation not supported by the repository for this object!");
                case 3:
                    throw new CmisNotSupportedException("No link with matching media type!");
                case 4:
                    throw new CmisRuntimeException("Nothing wrong! Either this is a bug or threading issue.");
                default:
                    throw new CmisRuntimeException("Unknown error!");
            }
        }

        // ---- helpers ----

        protected T Parse<T>(Stream stream) where T : AtomBase
        {
            AtomPubParser parser = new AtomPubParser(stream);

            try
            {
                parser.Parse();
            }
            catch (Exception e)
            {
                throw new CmisConnectionException("Parsing exception!", e);
            }

            AtomBase parseResult = parser.GetParseResults();

            if (!typeof(T).IsInstanceOfType(parseResult))
            {
                throw new CmisConnectionException("Unexpected document! Received "
                        + (parseResult == null ? "something unknown" : parseResult.GetAtomType()) + "!");
            }

            return (T)parseResult;
        }

        protected HttpUtils.Response Read(UrlBuilder url)
        {
            HttpUtils.Response resp = HttpUtils.InvokeGET(url, Session);

            if (resp.StatusCode != HttpStatusCode.OK)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            return resp;
        }

        protected HttpUtils.Response Post(UrlBuilder url, string contentType, HttpUtils.Output writer)
        {
            HttpUtils.Response resp = HttpUtils.InvokePOST(url, contentType, writer, Session);

            if (resp.StatusCode != HttpStatusCode.Created)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            return resp;
        }

        protected HttpUtils.Response Put(UrlBuilder url, string contentType, HttpUtils.Output writer)
        {
            HttpUtils.Response resp = HttpUtils.InvokePUT(url, contentType, writer, Session);

            if ((int)resp.StatusCode < 200 || (int)resp.StatusCode > 299)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            return resp;
        }

        protected void Delete(UrlBuilder url)
        {
            HttpUtils.Response resp = HttpUtils.InvokeDELETE(url, Session);

            if (resp.StatusCode != HttpStatusCode.NoContent)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }
        }

        protected string GetServiceDocURL()
        {
            return Session.GetValue(SessionParameter.AtomPubUrl) as string;
        }

        protected bool IsNextLink(AtomElement element)
        {
            return AtomPubConstants.RelNext == ((AtomLink)element.Object).Rel;
        }

        protected bool IsStr(string name, AtomElement element)
        {
            return name == element.LocalName && element.Object is string;
        }

        protected bool IsInt(string name, AtomElement element)
        {
            return name == element.LocalName && element.Object is Int64;
        }

        // ---- common methods ----

        protected cmisObjectType CreateIdObject(string objectId)
        {
            cmisObjectType cmisObject = new cmisObjectType();

            cmisPropertiesType properties = new cmisPropertiesType();
            cmisObject.properties = properties;

            cmisPropertyId idProperty = new cmisPropertyId();
            properties.Items = new cmisProperty[] { idProperty };
            idProperty.propertyDefinitionId = PropertyIds.ObjectId;
            idProperty.value = new string[] { objectId };

            return cmisObject;
        }

        protected bool IsAclMergeRequired(IAcl addAces, IAcl removeAces)
        {
            return (addAces != null && addAces.Aces != null && addAces.Aces.Count > 0)
                    || (removeAces != null && removeAces.Aces != null && removeAces.Aces.Count > 0);
        }

        protected IAcl MergeAcls(IAcl originalAces, IAcl addAces, IAcl removeAces)
        {
            IDictionary<string, HashSet<string>> originals = ConvertAclToDict(originalAces);
            IDictionary<string, HashSet<string>> adds = ConvertAclToDict(addAces);
            IDictionary<string, HashSet<string>> removes = ConvertAclToDict(removeAces);
            IList<IAce> newACEs = new List<IAce>();

            // iterate through the original ACEs
            foreach (KeyValuePair<string, HashSet<string>> ace in originals)
            {
                // add permissions
                HashSet<string> addPermissions = adds[ace.Key];
                if (addPermissions != null)
                {
                    foreach (string perm in addPermissions)
                    {
                        ace.Value.Add(perm);
                    }
                }

                // remove permissions
                HashSet<string> removePermissions = removes[ace.Key];
                if (removePermissions != null)
                {
                    foreach (string perm in removePermissions)
                    {
                        ace.Value.Remove(perm);
                    }
                }

                // create new ACE
                Ace resultAce = new Ace();
                Principal resultPrincipal = new Principal();
                resultPrincipal.Id = ace.Key;
                resultAce.Principal = resultPrincipal;
                resultAce.Permissions = new List<string>(ace.Value);

                newACEs.Add(resultAce);
            }

            // find all ACEs that should be added but are not in the original ACE list
            foreach (KeyValuePair<string, HashSet<string>> ace in adds)
            {
                if (!originals.ContainsKey(ace.Key) && ace.Value.Count > 0)
                {
                    Ace resultAce = new Ace();
                    Principal resultPrincipal = new Principal();
                    resultPrincipal.Id = ace.Key;
                    resultAce.Principal = resultPrincipal;
                    resultAce.Permissions = new List<string>(ace.Value);

                    newACEs.Add(resultAce);
                }
            }

            Acl result = new Acl();
            result.Aces = newACEs;

            return result;
        }

        private IDictionary<string, HashSet<string>> ConvertAclToDict(IAcl acl)
        {
            IDictionary<string, HashSet<string>> result = new Dictionary<string, HashSet<string>>();

            if (acl == null || acl.Aces == null)
            {
                return result;
            }

            foreach (Ace ace in acl.Aces)
            {
                // don't consider indirect ACEs - we can't change them
                if (!ace.IsDirect)
                {
                    // ignore
                    continue;
                }

                // although a principal must not be null, check it
                if ((ace.Principal == null) || (ace.Principal.Id == null))
                {
                    // ignore
                    continue;
                }

                if (ace.Permissions == null)
                {
                    continue;
                }

                HashSet<string> permissions;
                if (!result.TryGetValue(ace.Principal.Id, out permissions))
                {
                    permissions = new HashSet<string>();
                    result[ace.Principal.Id] = permissions;
                }

                foreach (string perm in ace.Permissions)
                {
                    permissions.Add(perm);
                }
            }

            return result;
        }


        protected AtomAcl UpdateAcl(string repositoryId, string objectId, IAcl acl, AclPropagation? aclPropagation)
        {
            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelACL, AtomPubConstants.MediatypeACL);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelACL, AtomPubConstants.MediatypeACL);
            }

            UrlBuilder aclUrl = new UrlBuilder(link);
            aclUrl.AddParameter(AtomPubConstants.ParamACLPropagation, aclPropagation);

            // set up object and writer
            cmisAccessControlListType cmisAcl = Converter.Convert(acl);
            HttpUtils.Output output = delegate(Stream stream)
            {
                AtomWriter.AclSerializer.Serialize(stream, cmisAcl);
            };

            // update
            HttpUtils.Response resp = Put(aclUrl, AtomPubConstants.MediatypeACL, output);

            // parse new acl
            return Parse<AtomAcl>(resp.Stream);
        }

        protected IList<IRepositoryInfo> GetRepositoriesInternal(string repositoryId)
        {
            IList<IRepositoryInfo> repInfos = new List<IRepositoryInfo>();

            // retrieve service doc
            UrlBuilder url = new UrlBuilder(GetServiceDocURL());
            url.AddParameter(AtomPubConstants.ParamRepositoryId, repositoryId);

            // read and parse
            HttpUtils.Response resp = Read(url);
            ServiceDoc serviceDoc = Parse<ServiceDoc>(resp.Stream);

            // walk through the workspaces
            foreach (RepositoryWorkspace ws in serviceDoc.GetWorkspaces())
            {
                if (ws.Id == null)
                {
                    // found a non-CMIS workspace
                    continue;
                }

                foreach (AtomElement element in ws.GetElements())
                {
                    if (element.LocalName == NameCollection)
                    {
                        AddCollection(ws.Id, (IDictionary<string, string>)element.Object);
                    }
                    else if (element.Object is AtomLink)
                    {
                        AddRepositoryLink(ws.Id, (AtomLink)element.Object);
                    }
                    else if (element.LocalName == NameURITemplate)
                    {
                        AddTemplate(ws.Id, (IDictionary<string, string>)element.Object);
                    }
                    else if (element.Object is cmisRepositoryInfoType)
                    {
                        repInfos.Add(Converter.Convert((cmisRepositoryInfoType)element.Object));
                    }
                }
            }

            return repInfos;
        }

        protected IObjectData GetObjectInternal(string repositoryId, IdentifierType idOrPath, string objectIdOrPath,
            ReturnVersion? returnVersion, string filter, bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships,
            string renditionFilter, bool? includePolicyIds, bool? includeAcl, IExtensionsData extension)
        {
            IObjectData result = null;

            Dictionary<string, object> parameters = new Dictionary<string, object>();
            parameters[AtomPubConstants.ParamId] = objectIdOrPath;
            parameters[AtomPubConstants.ParamPath] = objectIdOrPath;
            parameters[AtomPubConstants.ParamReturnVersion] = returnVersion;
            parameters[AtomPubConstants.ParamFilter] = filter;
            parameters[AtomPubConstants.ParamAllowableActions] = includeAllowableActions;
            parameters[AtomPubConstants.ParamACL] = includeAcl;
            parameters[AtomPubConstants.ParamPolicyIds] = includePolicyIds;
            parameters[AtomPubConstants.ParamRelationships] = includeRelationships;
            parameters[AtomPubConstants.ParamRenditionFilter] = renditionFilter;

            string link = LoadTemplateLink(repositoryId, (idOrPath == IdentifierType.Id ? AtomPubConstants.TemplateObjectById
                    : AtomPubConstants.TemplateObjectByPath), parameters);
            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            UrlBuilder url = new UrlBuilder(link);
            // workaround for missing template parameter in the CMIS spec
            if ((returnVersion != null) && (returnVersion != ReturnVersion.This))
            {
                url.AddParameter(AtomPubConstants.ParamReturnVersion, returnVersion);
            }

            HttpUtils.Response resp = Read(url);
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            if (entry.Id == null)
            {
                throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
            }

            LockLinks();
            try
            {
                RemoveLinks(repositoryId, entry.Id);

                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisObjectType)
                    {
                        result = Converter.Convert((cmisObjectType)element.Object);
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }

            return result;
        }

        protected ITypeDefinition GetTypeDefinitionInternal(string repositoryId, string typeId)
        {
            ITypeDefinition result = null;

            Dictionary<string, object> parameters = new Dictionary<string, object>();
            parameters[AtomPubConstants.ParamId] = typeId;

            string link = LoadTemplateLink(repositoryId, AtomPubConstants.TemplateTypeById, parameters);
            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            // read and parse
            HttpUtils.Response resp = Read(new UrlBuilder(link));
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // we expect a CMIS entry
            if (entry.Id == null)
            {
                throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
            }

            LockTypeLinks();
            try
            {
                // clean up cache
                RemoveTypeLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddTypeLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisTypeDefinitionType)
                    {
                        result = Converter.Convert((cmisTypeDefinitionType)element.Object);
                    }
                }
            }
            finally
            {
                UnlockTypeLinks();
            }

            return result;
        }
    }

    internal class RepositoryService : AbstractAtomPubService, IRepositoryService
    {
        public RepositoryService(BindingSession session)
        {
            Session = session;
        }

        public IList<IRepositoryInfo> GetRepositoryInfos(IExtensionsData extension)
        {
            return GetRepositoriesInternal(null);
        }

        public IRepositoryInfo GetRepositoryInfo(string repositoryId, IExtensionsData extension)
        {
            IList<IRepositoryInfo> repositoryInfos = GetRepositoriesInternal(repositoryId);

            // find the repository
            foreach (IRepositoryInfo info in repositoryInfos)
            {
                if (info.Id == null) { continue; }
                if (info.Id == repositoryId) { return info; }
            }

            throw new CmisObjectNotFoundException("Repository not found!");
        }

        public ITypeDefinitionList GetTypeChildren(string repositoryId, string typeId, bool? includePropertyDefinitions,
            long? maxItems, long? skipCount, IExtensionsData extension)
        {
            TypeDefinitionList result = new TypeDefinitionList();

            // find the link
            string link = null;
            if (typeId == null)
            {
                link = LoadCollection(repositoryId, AtomPubConstants.CollectionTypes);
            }
            else
            {
                link = LoadTypeLink(repositoryId, typeId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or type!");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamTypeId, typeId);
            url.AddParameter(AtomPubConstants.ParamPropertyDefinitions, includePropertyDefinitions);
            url.AddParameter(AtomPubConstants.ParamMaxItems, maxItems);
            url.AddParameter(AtomPubConstants.ParamSkipCount, skipCount);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element)) { result.HasMoreItems = true; }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            result.List = new List<ITypeDefinition>(feed.GetEntries().Count);

            // get the children
            foreach (AtomEntry entry in feed.GetEntries())
            {
                ITypeDefinition child = null;

                LockTypeLinks();
                try
                {
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is AtomLink)
                        {
                            AddTypeLink(repositoryId, entry.Id, (AtomLink)element.Object);
                        }
                        else if (element.Object is cmisTypeDefinitionType)
                        {
                            child = Converter.Convert((cmisTypeDefinitionType)element.Object);
                        }
                    }
                }
                finally
                {
                    UnlockTypeLinks();
                }

                if (child != null)
                {
                    result.List.Add(child);
                }
            }

            return result;
        }

        public IList<ITypeDefinitionContainer> GetTypeDescendants(string repositoryId, string typeId, long? depth,
            bool? includePropertyDefinitions, IExtensionsData extension)
        {
            List<ITypeDefinitionContainer> result = new List<ITypeDefinitionContainer>();

            // find the link
            string link = null;
            if (typeId == null)
            {
                link = LoadRepositoryLink(repositoryId, AtomPubConstants.RepRelTypeDesc);
            }
            else
            {
                link = LoadTypeLink(repositoryId, typeId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeDescendants);
            }

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or type!");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamTypeId, typeId);
            url.AddParameter(AtomPubConstants.ParamDepth, depth);
            url.AddParameter(AtomPubConstants.ParamPropertyDefinitions, includePropertyDefinitions);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // process tree
            AddTypeDescendantsLevel(repositoryId, feed, result);

            return result;
        }

        private void AddTypeDescendantsLevel(string repositoryId, AtomFeed feed, List<ITypeDefinitionContainer> containerList)
        {
            if (feed == null || feed.GetEntries().Count == 0)
            {
                return;
            }

            foreach (AtomEntry entry in feed.GetEntries())
            {
                TypeDefinitionContainer childContainer = null;
                List<ITypeDefinitionContainer> childContainerList = new List<ITypeDefinitionContainer>();

                // walk through the entry
                LockTypeLinks();
                try
                {
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is AtomLink)
                        {
                            AddTypeLink(repositoryId, entry.Id, (AtomLink)element.Object);
                        }
                        else if (element.Object is cmisTypeDefinitionType)
                        {
                            childContainer = new TypeDefinitionContainer();
                            childContainer.TypeDefinition = Converter.Convert((cmisTypeDefinitionType)element.Object);
                        }
                        else if (element.Object is AtomFeed)
                        {
                            AddTypeDescendantsLevel(repositoryId, (AtomFeed)element.Object, childContainerList);
                        }
                    }
                }
                finally
                {
                    UnlockTypeLinks();
                }

                if (childContainer != null)
                {
                    childContainer.Children = childContainerList;
                    containerList.Add(childContainer);
                }
            }
        }

        public ITypeDefinition GetTypeDefinition(string repositoryId, string typeId, IExtensionsData extension)
        {
            return GetTypeDefinitionInternal(repositoryId, typeId);
        }
    }

    internal class NavigationService : AbstractAtomPubService, INavigationService
    {
        public NavigationService(BindingSession session)
        {
            Session = session;
        }

        public IObjectInFolderList GetChildren(string repositoryId, string folderId, string filter, string orderBy,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            bool? includePathSegment, long? maxItems, long? skipCount, IExtensionsData extension)
        {
            ObjectInFolderList result = new ObjectInFolderList();

            // find the link
            String link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamOrderBy, orderBy);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamRelationships, includeRelationships);
            url.AddParameter(AtomPubConstants.ParamRenditionFilter, renditionFilter);
            url.AddParameter(AtomPubConstants.ParamPathSegment, includePathSegment);
            url.AddParameter(AtomPubConstants.ParamMaxItems, maxItems);
            url.AddParameter(AtomPubConstants.ParamSkipCount, skipCount);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element)) { result.HasMoreItems = true; }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            // get the children
            if (feed.GetEntries().Count > 0)
            {
                result.Objects = new List<IObjectInFolderData>(feed.GetEntries().Count);

                foreach (AtomEntry entry in feed.GetEntries())
                {
                    ObjectInFolderData child = null;
                    String pathSegment = null;

                    LockLinks();
                    try
                    {
                        // clean up cache
                        RemoveLinks(repositoryId, entry.Id);

                        // walk through the entry
                        foreach (AtomElement element in entry.GetElements())
                        {
                            if (element.Object is AtomLink)
                            {
                                AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                            }
                            else if (IsStr(NamePathSegment, element))
                            {
                                pathSegment = (string)element.Object;
                            }
                            else if (element.Object is cmisObjectType)
                            {
                                child = new ObjectInFolderData();
                                child.Object = Converter.Convert((cmisObjectType)element.Object);
                            }
                        }
                    }
                    finally
                    {
                        UnlockLinks();
                    }

                    if (child != null)
                    {
                        child.PathSegment = pathSegment;
                        result.Objects.Add(child);
                    }
                }
            }

            return result;
        }

        public IList<IObjectInFolderContainer> GetDescendants(string repositoryId, string folderId, long? depth, string filter,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            bool? includePathSegment, IExtensionsData extension)
        {
            IList<IObjectInFolderContainer> result = new List<IObjectInFolderContainer>();

            // find the link
            String link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeDescendants);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeDescendants);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamDepth, depth);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamRelationships, includeRelationships);
            url.AddParameter(AtomPubConstants.ParamRenditionFilter, renditionFilter);
            url.AddParameter(AtomPubConstants.ParamPathSegment, includePathSegment);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // process tree
            AddDescendantsLevel(repositoryId, feed, result);

            return result;
        }

        public IList<IObjectInFolderContainer> GetFolderTree(string repositoryId, string folderId, long? depth, string filter,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            bool? includePathSegment, IExtensionsData extension)
        {
            IList<IObjectInFolderContainer> result = new List<IObjectInFolderContainer>();

            // find the link
            string link = LoadLink(repositoryId, folderId, AtomPubConstants.RelFolderTree, AtomPubConstants.MediatypeDescendants);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelFolderTree, AtomPubConstants.MediatypeDescendants);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamDepth, depth);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamRelationships, includeRelationships);
            url.AddParameter(AtomPubConstants.ParamRenditionFilter, renditionFilter);
            url.AddParameter(AtomPubConstants.ParamPathSegment, includePathSegment);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // process tree
            AddDescendantsLevel(repositoryId, feed, result);

            return result;
        }

        public IList<IObjectParentData> GetObjectParents(string repositoryId, string objectId, string filter,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            bool? includeRelativePathSegment, IExtensionsData extension)
        {
            IList<IObjectParentData> result = new List<IObjectParentData>();

            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelUp, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                // root and unfiled objects have no UP link
                return result;
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamRelationships, includeRelationships);
            url.AddParameter(AtomPubConstants.ParamRenditionFilter, renditionFilter);
            url.AddParameter(AtomPubConstants.ParamRelativePathSegment, includeRelativePathSegment);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomBase atomBase = Parse<AtomBase>(resp.Stream);

            if (atomBase is AtomFeed)
            {
                // it's a feed
                AtomFeed feed = (AtomFeed)atomBase;

                // walk through the feed
                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectParentData objectParent = ProcessParentEntry(entry, repositoryId);

                    if (objectParent != null)
                    {
                        result.Add(objectParent);
                    }
                }
            }
            else if (atomBase is AtomEntry)
            {
                // it's an entry
                AtomEntry entry = (AtomEntry)atomBase;

                IObjectParentData objectParent = ProcessParentEntry(entry, repositoryId);

                if (objectParent != null)
                {
                    result.Add(objectParent);
                }
            }

            return result;
        }

        private IObjectParentData ProcessParentEntry(AtomEntry entry, string repositoryId)
        {
            ObjectParentData result = null;
            String relativePathSegment = null;

            LockLinks();
            try
            {
                // clean up cache
                RemoveLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisObjectType)
                    {
                        result = new ObjectParentData();
                        result.Object = Converter.Convert((cmisObjectType)element.Object);
                    }
                    else if (IsStr(NameRelativePathSegment, element))
                    {
                        relativePathSegment = (string)element.Object;
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }

            if (result != null)
            {
                result.RelativePathSegment = relativePathSegment;
            }

            return result;
        }

        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, ExtensionsData extension)
        {
            IObjectData result = null;

            // find the link
            String link = LoadLink(repositoryId, folderId, AtomPubConstants.RelUp, AtomPubConstants.MediatypeEntry);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelUp, AtomPubConstants.MediatypeEntry);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);

            // read
            HttpUtils.Response resp = Read(url);
            AtomBase atomBase = Parse<AtomBase>(resp.Stream);

            // get the entry
            AtomEntry entry = null;
            if (atomBase is AtomFeed)
            {
                AtomFeed feed = (AtomFeed)atomBase;
                if (feed.GetEntries().Count == 0)
                {
                    throw new CmisRuntimeException("Parent feed is empty!");
                }
                entry = feed.GetEntries()[0];
            }
            else if (atomBase is AtomEntry)
            {
                entry = (AtomEntry)atomBase;
            }
            else
            {
                throw new CmisRuntimeException("Unexpected document!");
            }

            LockLinks();
            try
            {
                // clean up cache
                RemoveLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisObjectType)
                    {
                        result = Converter.Convert((cmisObjectType)element.Object);
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }

            return result;
        }

        public IObjectList GetCheckedOutDocs(string repositoryId, string folderId, string filter, string orderBy,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            long? maxItems, long? skipCount, IExtensionsData extension)
        {
            ObjectList result = new ObjectList();

            // find the link
            String link = LoadCollection(repositoryId, AtomPubConstants.CollectionCheckedout);

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or checkedout collection not supported!");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFolderId, folderId);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamOrderBy, orderBy);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamRelationships, includeRelationships);
            url.AddParameter(AtomPubConstants.ParamRenditionFilter, renditionFilter);
            url.AddParameter(AtomPubConstants.ParamMaxItems, maxItems);
            url.AddParameter(AtomPubConstants.ParamSkipCount, skipCount);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element))
                    {
                        result.HasMoreItems = true;
                    }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            // get the documents
            if (feed.GetEntries().Count > 0)
            {
                result.Objects = new List<IObjectData>(feed.GetEntries().Count);

                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData child = null;

                    LockLinks();
                    try
                    {
                        // clean up cache
                        RemoveLinks(repositoryId, entry.Id);

                        // walk through the entry
                        foreach (AtomElement element in entry.GetElements())
                        {
                            if (element.Object is AtomLink)
                            {
                                AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                            }
                            else if (element.Object is cmisObjectType)
                            {
                                child = Converter.Convert((cmisObjectType)element.Object);
                            }
                        }
                    }
                    finally
                    {
                        UnlockLinks();
                    }

                    if (child != null)
                    {
                        result.Objects.Add(child);
                    }
                }
            }

            return result;
        }

        private void AddDescendantsLevel(String repositoryId, AtomFeed feed, IList<IObjectInFolderContainer> containerList)
        {
            if ((feed == null) || (feed.GetEntries().Count == 0))
            {
                return;
            }

            // walk through the feed
            foreach (AtomEntry entry in feed.GetEntries())
            {
                ObjectInFolderData objectInFolder = null;
                string pathSegment = null;
                IList<IObjectInFolderContainer> childContainerList = new List<IObjectInFolderContainer>();

                LockLinks();
                try
                {
                    // clean up cache
                    RemoveLinks(repositoryId, entry.Id);

                    // walk through the entry
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is AtomLink)
                        {
                            AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                        }
                        else if (element.Object is cmisObjectType)
                        {
                            objectInFolder = new ObjectInFolderData();
                            objectInFolder.Object = Converter.Convert((cmisObjectType)element.Object);
                        }
                        else if (IsStr(NamePathSegment, element))
                        {
                            pathSegment = (string)element.Object;
                        }
                        else if (element.Object is AtomFeed)
                        {
                            AddDescendantsLevel(repositoryId, (AtomFeed)element.Object, childContainerList);
                        }
                    }
                }
                finally
                {
                    UnlockLinks();
                }

                if (objectInFolder != null)
                {
                    objectInFolder.PathSegment = pathSegment;
                    ObjectInFolderContainer childContainer = new ObjectInFolderContainer();
                    childContainer.Object = objectInFolder;
                    childContainer.Children = childContainerList;
                    containerList.Add(childContainer);
                }
            }
        }
    }

    internal class ObjectService : AbstractAtomPubService, IObjectService
    {
        public ObjectService(BindingSession session)
        {
            Session = session;
        }

        public string CreateDocument(string repositoryId, IProperties properties, string folderId, IContentStream contentStream,
            VersioningState? versioningState, IList<string> policies, IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            CheckCreateProperties(properties);

            // find the link
            string link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamVersioningState, versioningState);

            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);
            cmisObject.policyIds = Converter.ConvertPolicies(policies);

            String mediaType = null;
            Stream stream = null;

            if (contentStream != null)
            {
                mediaType = contentStream.MimeType;
                stream = contentStream.Stream;
            }

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject, mediaType, stream);

            // post the new folder object
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // handle ACL modifications
            HandleAclModifications(repositoryId, entry, addAces, removeAces);

            return entry.Id;
        }

        public string CreateDocumentFromSource(string repositoryId, string sourceId, IProperties properties, string folderId,
            VersioningState? versioningState, IList<string> policies, IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            throw new CmisNotSupportedException("createDocumentFromSource is not supported by the AtomPub binding!");
        }

        public string CreateFolder(string repositoryId, IProperties properties, string folderId, IList<string> policies,
            IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            CheckCreateProperties(properties);

            // find the link
            string link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);


            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);
            cmisObject.policyIds = Converter.ConvertPolicies(policies);

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject);

            // post the new folder object
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // handle ACL modifications
            HandleAclModifications(repositoryId, entry, addAces, removeAces);

            return entry.Id;
        }

        public string CreateRelationship(string repositoryId, IProperties properties, IList<string> policies, IAcl addAces,
            IAcl removeAces, IExtensionsData extension)
        {
            CheckCreateProperties(properties);

            // find source id
            IPropertyData sourceIdProperty = properties[PropertyIds.SourceId];
            if (sourceIdProperty == null || sourceIdProperty.PropertyType != PropertyType.Id)
            {
                throw new CmisInvalidArgumentException("Source Id is not set!");
            }

            string sourceId = sourceIdProperty.FirstValue as string;
            if (sourceId == null)
            {
                throw new CmisInvalidArgumentException("Source Id is not set!");
            }

            // find the link
            string link = LoadLink(repositoryId, sourceId, AtomPubConstants.RelRelationships, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, sourceId, AtomPubConstants.RelRelationships, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);

            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);
            cmisObject.policyIds = Converter.ConvertPolicies(policies);

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject);

            // post the new folder object
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // handle ACL modifications
            HandleAclModifications(repositoryId, entry, addAces, removeAces);

            return entry.Id;
        }

        public string CreatePolicy(string repositoryId, IProperties properties, string folderId, IList<string> policies,
            IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            CheckCreateProperties(properties);

            // find the link
            string link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);


            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);
            cmisObject.policyIds = Converter.ConvertPolicies(policies);

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject);

            // post the new folder object
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // handle ACL modifications
            HandleAclModifications(repositoryId, entry, addAces, removeAces);

            return entry.Id;
        }

        public IAllowableActions GetAllowableActions(string repositoryId, string objectId, IExtensionsData extension)
        {
            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelAllowableActions, AtomPubConstants.MediatypeAllowableAction);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelAllowableActions, AtomPubConstants.MediatypeAllowableAction);
            }

            UrlBuilder url = new UrlBuilder(link);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomAllowableActions allowableActions = Parse<AtomAllowableActions>(resp.Stream);

            return Converter.Convert(allowableActions.AllowableActions);
        }

        public IProperties GetProperties(string repositoryId, string objectId, string filter, IExtensionsData extension)
        {
            IObjectData obj = GetObjectInternal(repositoryId, IdentifierType.Id, objectId, ReturnVersion.This, filter,
                    false, IncludeRelationshipsFlag.None, "cmis:none", false, false, extension);

            return obj.Properties;
        }

        public IList<IRenditionData> GetRenditions(string repositoryId, string objectId, string renditionFilter,
            long? maxItems, long? skipCount, IExtensionsData extension)
        {
            IObjectData obj = GetObjectInternal(repositoryId, IdentifierType.Id, objectId, ReturnVersion.This,
                PropertyIds.ObjectId, false, IncludeRelationshipsFlag.None, renditionFilter, false, false, extension);

            IList<IRenditionData> result = obj.Renditions;
            if (result == null)
            {
                result = new List<IRenditionData>();
            }

            return result;
        }

        public IObjectData GetObject(string repositoryId, string objectId, string filter, bool? includeAllowableActions,
            IncludeRelationshipsFlag? includeRelationships, string renditionFilter, bool? includePolicyIds,
            bool? includeAcl, IExtensionsData extension)
        {
            return GetObjectInternal(repositoryId, IdentifierType.Id, objectId, ReturnVersion.This, filter, includeAllowableActions,
                includeRelationships, renditionFilter, includePolicyIds, includeAcl, extension);
        }

        public IObjectData GetObjectByPath(string repositoryId, string path, string filter, bool? includeAllowableActions,
            IncludeRelationshipsFlag? includeRelationships, string renditionFilter, bool? includePolicyIds, bool? includeAcl,
            IExtensionsData extension)
        {
            return GetObjectInternal(repositoryId, IdentifierType.Path, path, ReturnVersion.This, filter, includeAllowableActions,
                includeRelationships, renditionFilter, includePolicyIds, includeAcl, extension);
        }

        public IContentStream GetContentStream(string repositoryId, string objectId, string streamId, long? offset, long? length,
            IExtensionsData extension)
        {
            ContentStream result = new ContentStream();

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.LinkRelContent, null);

            if (link == null)
            {
                throw new CmisConstraintException("No content stream");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamStreamId, streamId);

            // get the content
            if (offset != null && offset > Int32.MaxValue)
            {
                throw new CmisInvalidArgumentException("Offset >" + Int32.MaxValue);
            }
            if (length != null && length > Int32.MaxValue)
            {
                throw new CmisInvalidArgumentException("Length >" + Int32.MaxValue);
            }
            HttpUtils.Response resp = HttpUtils.InvokeGET(url, Session, (int?)offset, (int?)length);

            // check response code
            if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.PartialContent)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            result.FileName = null;
            result.Length = resp.ContentLength;
            result.MimeType = resp.ContentType;
            result.Stream = resp.Stream;

            return result;
        }

        public void UpdateProperties(string repositoryId, ref string objectId, ref string changeToken, IProperties properties,
            IExtensionsData extension)
        {
            // we need an object id
            if (objectId == null || objectId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamChangeToken, changeToken);

            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject);

            // update
            HttpUtils.Response resp = Put(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse new entry
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // we expect a CMIS entry
            if (entry.Id == null)
            {
                throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
            }

            // set object id
            objectId = entry.Id;
            changeToken = null;

            LockLinks();
            try
            {
                // clean up cache
                RemoveLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisObjectType)
                    {
                        // extract new change token
                        cmisObject = (cmisObjectType)element.Object;
                        if (cmisObject.properties != null)
                        {
                            foreach (cmisProperty property in cmisObject.properties.Items)
                            {
                                if (PropertyIds.ChangeToken == property.propertyDefinitionId && property is cmisPropertyString)
                                {
                                    cmisPropertyString changeTokenProperty = (cmisPropertyString)property;
                                    if (changeTokenProperty.value != null && changeTokenProperty.value.Length > 0)
                                    {
                                        changeToken = changeTokenProperty.value[0];
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }
        }

        public void MoveObject(string repositoryId, ref string objectId, string targetFolderId, string sourceFolderId,
            IExtensionsData extension)
        {
            if (objectId == null || objectId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            if (targetFolderId == null || targetFolderId.Length == 0 || sourceFolderId == null || sourceFolderId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Source and target folder must be set!");
            }

            // find the link
            String link = LoadLink(repositoryId, targetFolderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, targetFolderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamSourceFolderId, sourceFolderId);

            // set up object and writer
            AtomEntryWriter entryWriter = new AtomEntryWriter(CreateIdObject(objectId));

            // post move request
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            objectId = entry.Id;
        }

        public void DeleteObject(string repositoryId, string objectId, bool? allVersions, IExtensionsData extension)
        {
            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamAllVersions, allVersions);

            Delete(url);
        }

        public IFailedToDeleteData DeleteTree(string repositoryId, string folderId, bool? allVersions, UnfileObject? unfileObjects,
            bool? continueOnFailure, ExtensionsData extension)
        {
            // find the link
            String link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeDescendants);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeDescendants);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamAllVersions, allVersions);
            url.AddParameter(AtomPubConstants.ParamUnfildeObjects, unfileObjects);
            url.AddParameter(AtomPubConstants.ParamContinueOnFailure, continueOnFailure);

            // make the call
            HttpUtils.Response resp = HttpUtils.InvokeDELETE(url, Session);

            // check response code
            if (resp.StatusCode == HttpStatusCode.OK || resp.StatusCode == HttpStatusCode.Accepted || resp.StatusCode == HttpStatusCode.NoContent)
            {
                return new FailedToDeleteData();
            }

            throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
        }

        public void SetContentStream(string repositoryId, ref string objectId, bool? overwriteFlag, ref string changeToken,
            IContentStream contentStream, IExtensionsData extension)
        {
            if (objectId == null)
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // we need content
            if (contentStream == null || contentStream.Stream == null || contentStream.MimeType == null)
            {
                throw new CmisInvalidArgumentException("Content must be set!");
            }

            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelEditMedia, null);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelEditMedia, null);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamChangeToken, changeToken);
            url.AddParameter(AtomPubConstants.ParamOverwriteFlag, overwriteFlag);

            HttpUtils.Output output = delegate(Stream stream)
            {
                int b;
                byte[] buffer = new byte[4096];
                while ((b = contentStream.Stream.Read(buffer, 0, buffer.Length)) > -1)
                {
                    stream.Write(buffer, 0, b);
                }

                contentStream.Stream.Close();
            };

            // send content
            HttpUtils.Response resp = HttpUtils.InvokePUT(url, contentStream.MimeType, output, Session);

            // check response code
            if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.Created && resp.StatusCode != HttpStatusCode.NoContent)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            objectId = null;
            changeToken = null;
        }

        public void DeleteContentStream(string repositoryId, ref string objectId, ref string changeToken, IExtensionsData extension)
        {
            if (objectId == null)
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelEditMedia, null);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelEditMedia, null);
            }

            UrlBuilder url = new UrlBuilder(link);
            if (changeToken != null)
            {
                url.AddParameter(AtomPubConstants.ParamChangeToken, changeToken);
            }

            Delete(url);

            objectId = null;
            changeToken = null;
        }

        // ---- internal ---

        private void CheckCreateProperties(IProperties properties)
        {
            if (properties == null || properties.PropertyList == null)
            {
                throw new CmisInvalidArgumentException("Properties must be set!");
            }

            if (properties[PropertyIds.ObjectTypeId] == null)
            {
                throw new CmisInvalidArgumentException("Property " + PropertyIds.ObjectTypeId + " must be set!");
            }

            if (properties[PropertyIds.ObjectId] != null)
            {
                throw new CmisInvalidArgumentException("Property " + PropertyIds.ObjectId + " must not be set!");
            }
        }

        private void HandleAclModifications(String repositoryId, AtomEntry entry, IAcl addAces, IAcl removeAces)
        {
            if (!IsAclMergeRequired(addAces, removeAces))
            {
                return;
            }

            IAcl originalAces = null;

            // walk through the entry and find the current ACL
            foreach (AtomElement element in entry.GetElements())
            {
                if (element.Object is cmisObjectType)
                {
                    // extract current ACL
                    cmisObjectType cmisObject = (cmisObjectType)element.Object;
                    originalAces = Converter.Convert(cmisObject.acl, cmisObject.exactACLSpecified ? (bool?)cmisObject.exactACL : null);

                    break;
                }
            }

            if (originalAces != null)
            {
                // merge and update ACL
                IAcl newACL = MergeAcls(originalAces, addAces, removeAces);
                if (newACL != null)
                {
                    UpdateAcl(repositoryId, entry.Id, newACL, null);
                }
            }
        }
    }

    internal class VersioningService : AbstractAtomPubService, IVersioningService
    {
        public VersioningService(BindingSession session)
        {
            Session = session;
        }

        public void CheckOut(string repositoryId, ref string objectId, IExtensionsData extension, out bool? contentCopied)
        {
            if (objectId == null || objectId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            // find the link
            String link = LoadCollection(repositoryId, AtomPubConstants.CollectionCheckedout);

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or checkedout collection not supported!");
            }

            UrlBuilder url = new UrlBuilder(link);

            // set up object and writer
            AtomEntryWriter entryWriter = new AtomEntryWriter(CreateIdObject(objectId));

            // post move request
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse the response
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            objectId = entry.Id;

            LockLinks();
            try
            {
                // clean up cache
                RemoveLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }

            contentCopied = null;
        }

        public void CancelCheckOut(string repositoryId, string objectId, IExtensionsData extension)
        {
            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);
            }

            Delete(new UrlBuilder(link));
        }

        public void CheckIn(string repositoryId, ref string objectId, bool? major, IProperties properties,
            IContentStream contentStream, string checkinComment, IList<string> policies, IAcl addAces, IAcl removeAces,
            IExtensionsData extension)
        {
            // we need an object id
            if (objectId == null || objectId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelSelf, AtomPubConstants.MediatypeEntry);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamCheckinComment, checkinComment);
            url.AddParameter(AtomPubConstants.ParamMajor, major);
            url.AddParameter(AtomPubConstants.ParamCheckIn, "true");

            // set up object and writer
            cmisObjectType cmisObject = new cmisObjectType();
            cmisObject.properties = Converter.Convert(properties);
            cmisObject.policyIds = Converter.ConvertPolicies(policies);

            if (cmisObject.properties == null)
            {
                cmisObject.properties = new cmisPropertiesType();
            }

            string mediaType = null;
            Stream stream = null;

            if (contentStream != null)
            {
                mediaType = contentStream.MimeType;
                stream = contentStream.Stream;
            }

            AtomEntryWriter entryWriter = new AtomEntryWriter(cmisObject, mediaType, stream);

            // update
            HttpUtils.Response resp = Put(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));

            // parse new entry
            AtomEntry entry = Parse<AtomEntry>(resp.Stream);

            // we expect a CMIS entry
            if (entry.Id == null)
            {
                throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
            }

            // set object id
            objectId = entry.Id;

            IAcl originalAces = null;

            LockLinks();
            try
            {
                // clean up cache
                RemoveLinks(repositoryId, entry.Id);

                // walk through the entry
                foreach (AtomElement element in entry.GetElements())
                {
                    if (element.Object is AtomLink)
                    {
                        AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                    }
                    else if (element.Object is cmisObjectType)
                    {
                        // extract current ACL
                        cmisObject = (cmisObjectType)element.Object;
                        originalAces = Converter.Convert(cmisObject.acl, cmisObject.exactACLSpecified ? (bool?)cmisObject.exactACL : null);
                    }
                }
            }
            finally
            {
                UnlockLinks();
            }

            // handle ACL modifications
            if ((originalAces != null) && (IsAclMergeRequired(addAces, removeAces)))
            {
                // merge and update ACL
                IAcl newACL = MergeAcls(originalAces, addAces, removeAces);
                if (newACL != null)
                {
                    UpdateAcl(repositoryId, entry.Id, newACL, null);
                }
            }
        }

        public IObjectData GetObjectOfLatestVersion(string repositoryId, string objectId, string versionSeriesId, bool major,
            string filter, bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships,
            string renditionFilter, bool? includePolicyIds, bool? includeAcl, IExtensionsData extension)
        {
            ReturnVersion returnVersion = ReturnVersion.Latest;
            if (major)
            {
                returnVersion = ReturnVersion.LatestMajor;
            }

            return GetObjectInternal(repositoryId, IdentifierType.Id, objectId, returnVersion, filter,
                    includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds, includeAcl, extension);
        }

        public IProperties GetPropertiesOfLatestVersion(string repositoryId, string objectId, string versionSeriesId, bool major,
            string filter, IExtensionsData extension)
        {
            ReturnVersion returnVersion = ReturnVersion.Latest;
            if (major)
            {
                returnVersion = ReturnVersion.LatestMajor;
            }

            IObjectData objectData = GetObjectInternal(repositoryId, IdentifierType.Id, objectId, returnVersion, filter,
                    false, IncludeRelationshipsFlag.None, "cmis:none", false, false, extension);

            return objectData.Properties;
        }

        public IList<IObjectData> GetAllVersions(string repositoryId, string objectId, string versionSeriesId, string filter,
            bool? includeAllowableActions, IExtensionsData extension)
        {
            IList<IObjectData> result = new List<IObjectData>();

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelVersionHistory, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelVersionHistory, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // get the versions
            if (feed.GetEntries().Count > 0)
            {
                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData version = null;

                    LockLinks();
                    try
                    {
                        // clean up cache
                        RemoveLinks(repositoryId, entry.Id);

                        // walk through the entry
                        foreach (AtomElement element in entry.GetElements())
                        {
                            if (element.Object is AtomLink)
                            {
                                AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                            }
                            else if (element.Object is cmisObjectType)
                            {
                                version = Converter.Convert((cmisObjectType)element.Object);
                            }
                        }
                    }
                    finally
                    {
                        UnlockLinks();
                    }

                    if (version != null)
                    {
                        result.Add(version);
                    }
                }
            }

            return result;
        }
    }

    internal class RelationshipService : AbstractAtomPubService, IRelationshipService
    {
        public RelationshipService(BindingSession session)
        {
            Session = session;
        }

        public IObjectList GetObjectRelationships(string repositoryId, string objectId, bool? includeSubRelationshipTypes,
            RelationshipDirection? relationshipDirection, string typeId, string filter, bool? includeAllowableActions,
            long? maxItems, long? skipCount, IExtensionsData extension)
        {
            ObjectList result = new ObjectList();

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelRelationships, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelRelationships, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamSubRelationshipTypes, includeSubRelationshipTypes);
            url.AddParameter(AtomPubConstants.ParamRelationshipDirection, relationshipDirection);
            url.AddParameter(AtomPubConstants.ParamTypeId, typeId);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(AtomPubConstants.ParamMaxItems, maxItems);
            url.AddParameter(AtomPubConstants.ParamSkipCount, skipCount);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element))
                    {
                        result.HasMoreItems = true;
                    }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            // get the children
            if (feed.GetEntries().Count > 0)
            {
                result.Objects = new List<IObjectData>(feed.GetEntries().Count);

                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData relationship = null;

                    LockLinks();
                    try
                    {
                        // clean up cache
                        RemoveLinks(repositoryId, entry.Id);

                        // walk through the entry
                        foreach (AtomElement element in entry.GetElements())
                        {
                            if (element.Object is AtomLink)
                            {
                                AddLink(repositoryId, entry.Id, (AtomLink)element.Object);
                            }
                            else if (element.Object is cmisObjectType)
                            {
                                relationship = Converter.Convert((cmisObjectType)element.Object);
                            }
                        }
                    }
                    finally
                    {
                        UnlockLinks();
                    }

                    if (relationship != null)
                    {
                        result.Objects.Add(relationship);
                    }
                }
            }

            return result;
        }
    }

    internal class DiscoveryService : AbstractAtomPubService, IDiscoveryService
    {
        public DiscoveryService(BindingSession session)
        {
            Session = session;
        }

        public IObjectList Query(string repositoryId, string statement, bool? searchAllVersions,
            bool? includeAllowableActions, IncludeRelationshipsFlag? includeRelationships, string renditionFilter,
            long? maxItems, long? skipCount, IExtensionsData extension)
        {
            ObjectList result = new ObjectList();

            // find the link
            String link = LoadCollection(repositoryId, AtomPubConstants.CollectionQuery);

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or query not supported!");
            }

            UrlBuilder url = new UrlBuilder(link);

            // compile query request
            AtomQueryWriter queryWriter = new AtomQueryWriter(statement, searchAllVersions, includeAllowableActions,
                includeRelationships, renditionFilter, maxItems, skipCount);

            // post the query and parse results
            HttpUtils.Response resp = Post(url, AtomPubConstants.MediatypeQuery, new HttpUtils.Output(queryWriter.Write));
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element))
                    {
                        result.HasMoreItems = true;
                    }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            // get the result set
            if (feed.GetEntries().Count > 0)
            {
                result.Objects = new List<IObjectData>(feed.GetEntries().Count);

                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData hit = null;

                    // walk through the entry
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is cmisObjectType)
                        {
                            hit = Converter.Convert((cmisObjectType)element.Object);
                        }
                    }

                    if (hit != null)
                    {
                        result.Objects.Add(hit);
                    }
                }
            }

            return result;
        }

        public IObjectList GetContentChanges(string repositoryId, ref string changeLogToken, bool? includeProperties,
           string filter, bool? includePolicyIds, bool? includeAcl, long? maxItems, IExtensionsData extension)
        {
            ObjectList result = new ObjectList();

            // find the link
            String link = LoadRepositoryLink(repositoryId, AtomPubConstants.RepRelChanges);

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or content changes not supported!");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamChangeLogToken, changeLogToken);
            url.AddParameter(AtomPubConstants.ParamProperties, includeProperties);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);
            url.AddParameter(AtomPubConstants.ParamPolicyIds, includePolicyIds);
            url.AddParameter(AtomPubConstants.ParamACL, includeAcl);
            url.AddParameter(AtomPubConstants.ParamMaxItems, maxItems);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // handle top level
            foreach (AtomElement element in feed.GetElements())
            {
                if (element.Object is AtomLink)
                {
                    if (IsNextLink(element))
                    {
                        result.HasMoreItems = true;
                    }
                }
                else if (IsInt(NameNumItems, element))
                {
                    result.NumItems = (long)element.Object;
                }
            }

            // get the changes
            if (feed.GetEntries().Count > 0)
            {
                result.Objects = new List<IObjectData>(feed.GetEntries().Count);
                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData hit = null;

                    // walk through the entry
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is cmisObjectType)
                        {
                            hit = Converter.Convert((cmisObjectType)element.Object);
                        }
                    }

                    if (hit != null)
                    {
                        result.Objects.Add(hit);
                    }
                }
            }

            return result;
        }
    }

    internal class MultiFilingService : AbstractAtomPubService, IMultiFilingService
    {
        public MultiFilingService(BindingSession session)
        {
            Session = session;
        }

        public void AddObjectToFolder(string repositoryId, string objectId, string folderId, bool? allVersions, IExtensionsData extension)
        {
            if (objectId == null)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            // find the link
            string link = LoadLink(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);

            if (link == null)
            {
                ThrowLinkException(repositoryId, folderId, AtomPubConstants.RelDown, AtomPubConstants.MediatypeChildren);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamAllVersions, allVersions);

            // set up object and writer
            AtomEntryWriter entryWriter = new AtomEntryWriter(CreateIdObject(objectId));

            // post addObjectToFolder request
            Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));
        }

        public void RemoveObjectFromFolder(string repositoryId, string objectId, string folderId, IExtensionsData extension)
        {
            if (objectId == null)
            {
                throw new CmisInvalidArgumentException("Object id must be set!");
            }

            // find the link
            string link = LoadCollection(repositoryId, AtomPubConstants.CollectionUnfiled);

            if (link == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository or unfiling not supported!");
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamRemoveFrom, folderId);

            // set up object and writer
            AtomEntryWriter entryWriter = new AtomEntryWriter(CreateIdObject(objectId));

            // post removeObjectFromFolder request
            Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));
        }
    }

    internal class AclService : AbstractAtomPubService, IAclService
    {
        public AclService(BindingSession session)
        {
            Session = session;
        }

        public IAcl GetAcl(string repositoryId, string objectId, bool? onlyBasicPermissions, IExtensionsData extension)
        {
            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelACL, AtomPubConstants.MediatypeACL);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelACL, AtomPubConstants.MediatypeACL);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamOnlyBasicPermissions, onlyBasicPermissions);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomAcl acl = Parse<AtomAcl>(resp.Stream);

            return Converter.Convert(acl.ACL, null);
        }

        public IAcl ApplyAcl(string repositoryId, string objectId, IAcl addAces, IAcl removeAces, AclPropagation? aclPropagation,
            IExtensionsData extension)
        {
            IAcl result = null;

            // fetch the current ACL
            IAcl originalAces = GetAcl(repositoryId, objectId, false, null);

            // if no changes required, just return the ACL
            if (!IsAclMergeRequired(addAces, removeAces))
            {
                return originalAces;
            }

            // merge ACLs
            IAcl newACL = MergeAcls(originalAces, addAces, removeAces);

            // update ACL
            AtomAcl acl = UpdateAcl(repositoryId, objectId, newACL, aclPropagation);
            result = Converter.Convert(acl.ACL, null);

            return result;
        }
    }

    internal class PolicyService : AbstractAtomPubService, IPolicyService
    {
        public PolicyService(BindingSession session)
        {
            Session = session;
        }

        public void ApplyPolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension)
        {
            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);

            // set up object and writer
            AtomEntryWriter entryWriter = new AtomEntryWriter(CreateIdObject(objectId));

            // post applyPolicy request
            Post(url, AtomPubConstants.MediatypeEntry, new HttpUtils.Output(entryWriter.Write));
        }

        public void RemovePolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension)
        {
            // we need a policy id
            if (policyId == null || policyId.Length == 0)
            {
                throw new CmisInvalidArgumentException("Policy id must be set!");
            }

            // find the link
            String link = LoadLink(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, PropertyIds.ObjectId);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // find the policy
            string policyLink = null;
            bool found = false;

            if (feed.GetEntries().Count > 0)
            {
                foreach (AtomEntry entry in feed.GetEntries())
                {
                    // walk through the entry
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is AtomLink)
                        {
                            AtomLink atomLink = (AtomLink)element.Object;
                            if (AtomPubConstants.RelSelf == atomLink.Rel)
                            {
                                policyLink = atomLink.Href;
                            }
                        }
                        else if (element.Object is cmisObjectType)
                        {
                            string id = FindIdProperty((cmisObjectType)element.Object);
                            if (policyId == id)
                            {
                                found = true;
                            }
                        }
                    }

                    if (found)
                    {
                        break;
                    }
                }
            }

            // if found, delete it
            if (found && policyLink != null)
            {
                Delete(new UrlBuilder(policyLink));
            }
        }

        public IList<IObjectData> GetAppliedPolicies(string repositoryId, string objectId, string filter, IExtensionsData extension)
        {
            IList<IObjectData> result = new List<IObjectData>();

            // find the link
            string link = LoadLink(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);

            if (link == null)
            {
                ThrowLinkException(repositoryId, objectId, AtomPubConstants.RelPolicies, AtomPubConstants.MediatypeFeed);
            }

            UrlBuilder url = new UrlBuilder(link);
            url.AddParameter(AtomPubConstants.ParamFilter, filter);

            // read and parse
            HttpUtils.Response resp = Read(url);
            AtomFeed feed = Parse<AtomFeed>(resp.Stream);

            // get the policies
            if (feed.GetEntries().Count > 0)
            {
                foreach (AtomEntry entry in feed.GetEntries())
                {
                    IObjectData policy = null;

                    // walk through the entry
                    foreach (AtomElement element in entry.GetElements())
                    {
                        if (element.Object is cmisObjectType)
                        {
                            policy = Converter.Convert((cmisObjectType)element.Object);
                        }
                    }

                    if (policy != null)
                    {
                        result.Add(policy);
                    }
                }
            }

            return result;
        }

        private string FindIdProperty(cmisObjectType cmisObject)
        {
            if (cmisObject == null || cmisObject.properties == null)
            {
                return null;
            }

            foreach (cmisProperty property in cmisObject.properties.Items)
            {
                if (PropertyIds.ObjectId == property.propertyDefinitionId && property is cmisPropertyId)
                {
                    string[] values = ((cmisPropertyId)property).value;
                    if (values.Length == 1)
                    {
                        return values[0];
                    }
                }
            }

            return null;
        }
    }
}
