﻿/*
 * 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 Close()
        {
            // 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, IncludeRelationships? 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, IncludeRelationships? 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, IncludeRelationships? 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, IncludeRelationships? 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, IncludeRelationships? 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, IncludeRelationships? 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 is IPropertyId))
            {
                throw new CmisInvalidArgumentException("Source Id is not set!");
            }

            string sourceId = ((IPropertyId)sourceIdProperty).FirstValue;
            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, IncludeRelationships.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, IncludeRelationships.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,
            IncludeRelationships? 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,
            IncludeRelationships? 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, List<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, IncludeRelationships? 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, IncludeRelationships.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, IncludeRelationships? 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;
        }
    }
}
