﻿/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* Kind, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

using PortCMIS.Binding.Browser.Json;
using PortCMIS.Binding.Http;
using PortCMIS.Binding.Impl;
using PortCMIS.Binding.Services;
using PortCMIS.Client;
using PortCMIS.Data;
using PortCMIS.Data.Extensions;
using PortCMIS.Enums;
using PortCMIS.Exceptions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Numerics;
using System.Text;

namespace PortCMIS.Binding.Browser
{
    /// <summary>
    /// Extended Repository Info for the Browser Binding.
    /// </summary>
    public class RepositoryInfoBrowserBinding : RepositoryInfo
    {
        /// <value>
        /// The base repository URL for non-object related calls.
        /// </value>
        public string RepositoryUrl { get; set; }

        /// <value>
        /// The base root URL for object related calls.
        /// </value>
        public string RootUrl { get; set; }
    }

    /// <summary>
    /// Browser binding SPI.
    /// </summary>
    internal class CmisBrowserSpi : ICmisSpi
    {
        public const string RepositoryUrlCache = "org.apache.chemistry.portcmis.binding.browser.repositoryurls";

        private BindingSession session;
        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;

        /// <inheritdoc/>
        public void Initialize(IBindingSession session)
        {
            this.session = session as BindingSession;
            if (this.session == null)
            {
                throw new ArgumentException("Invalid binding session!");
            }

            repositoryService = new RepositoryService(this.session);
            navigationService = new NavigationService(this.session);
            objectService = new ObjectService(this.session);
            versioningService = new VersioningService(this.session);
            discoveryService = new DiscoveryService(this.session);
            multiFilingService = new MultiFilingService(this.session);
            relationshipService = new RelationshipService(this.session);
            policyService = new PolicyService(this.session);
            aclService = new AclService(this.session);
        }

        /// <inheritdoc/>
        public IRepositoryService GetRepositoryService()
        {
            return repositoryService;
        }

        /// <inheritdoc/>
        public INavigationService GetNavigationService()
        {
            return navigationService;
        }

        /// <inheritdoc/>
        public IObjectService GetObjectService()
        {
            return objectService;
        }

        /// <inheritdoc/>
        public IVersioningService GetVersioningService()
        {
            return versioningService;
        }

        /// <inheritdoc/>
        public IRelationshipService GetRelationshipService()
        {
            return relationshipService;
        }

        /// <inheritdoc/>
        public IDiscoveryService GetDiscoveryService()
        {
            return discoveryService;
        }

        /// <inheritdoc/>
        public IMultiFilingService GetMultiFilingService()
        {
            return multiFilingService;
        }

        /// <inheritdoc/>
        public IAclService GetAclService()
        {
            return aclService;
        }

        /// <inheritdoc/>
        public IPolicyService GetPolicyService()
        {
            return policyService;
        }

        /// <inheritdoc/>
        public void ClearAllCaches()
        {
            session.RemoveValue(RepositoryUrlCache);
        }

        /// <inheritdoc/>
        public void ClearRepositoryCache(string repositoryId)
        {
            RepositoryUrlCache repUrlCache = session.GetValue(RepositoryUrlCache) as RepositoryUrlCache;
            if (repUrlCache != null)
            {
                repUrlCache.RemoveRepository(repositoryId);
            }
        }

        /// <inheritdoc/>
        public void Dispose()
        {
            // nothing to do
        }
    }

    internal class ClientTypeCache : ITypeCache
    {
        private string RepositoryId { get; set; }
        private AbstractBrowserBindingService Service { get; set; }

        public ClientTypeCache(string repositoryId, AbstractBrowserBindingService service)
        {
            this.RepositoryId = repositoryId;
            this.Service = service;
        }

        public ITypeDefinition GetTypeDefinition(string typeId)
        {
            TypeDefinitionCache cache = Service.Session.GetTypeDefinitionCache();

            ITypeDefinition type = cache.Get(RepositoryId, typeId);
            if (type == null)
            {
                type = Service.GetTypeDefinitionInternal(RepositoryId, typeId);
                if (type != null)
                {
                    cache.Put(RepositoryId, type);
                }
            }

            return type;
        }

        public ITypeDefinition ReloadTypeDefinition(string typeId)
        {
            TypeDefinitionCache cache = Service.Session.GetTypeDefinitionCache();

            ITypeDefinition type = Service.GetTypeDefinitionInternal(RepositoryId, typeId);
            if (type != null)
            {
                cache.Put(RepositoryId, type);
            }

            return type;
        }

        public ITypeDefinition GetTypeDefinitionForObject(string objectId)
        {
            return null;
        }

        public IPropertyDefinition GetPropertyDefinition(string propId)
        {
            return null;
        }
    }

    internal class FormDataComposer
    {
        public string CmisAction { get; private set; }

        public IContentStream Stream { get; set; }

        public IProperties Properties { get; set; }
        public bool Succinct { get; set; }
        public DateTimeFormat DateTimeFormat { get; set; }

        public IAcl AddAces { get; set; }
        public IAcl RemoveAces { get; set; }

        public IList<string> Policies { get; set; }
        public string PolicyId { get; set; }

        public IList<string> AddSecondaryTypeIds { get; set; }
        public IList<string> RemoveSecondaryTypeIds { get; set; }

        public IList<IBulkUpdateObjectIdAndChangeToken> ObjectIdsAndChangeTokens { get; set; }

        private IDictionary<string, object> parameters;

        public IDictionary<string, object> Parameters
        {
            get
            {
                if (parameters == null)
                {
                    parameters = new Dictionary<string, object>();
                }
                return parameters;
            }
            set { parameters = value; }
        }

        public FormDataComposer(string cmisAction)
        {
            CmisAction = cmisAction;
        }

        public HttpContent CreateHttpContent()
        {
            if (Stream == null)
            {
                return CreateFormUrlEncodedContent();
            }
            else
            {
                return CreateMultipartFormDataContent();
            }
        }

        protected FormUrlEncodedContent CreateFormUrlEncodedContent()
        {
            return new FormUrlEncodedContent(CreateContent());
        }

        protected MultipartFormDataContent CreateMultipartFormDataContent()
        {
            MultipartFormDataContent content = new MultipartFormDataContent();

            try
            {
                IList<KeyValuePair<string, string>> mpfParameters = CreateContent();
                foreach (KeyValuePair<string, string> p in mpfParameters)
                {
                    content.Add(new StringContent(p.Value, Encoding.UTF8), p.Key);
                }

                if (Stream.Stream != null)
                {
                    StreamContent streamContent = new StreamContent(Stream.Stream);
                    streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(Stream.MimeType ?? "application/octet-stream");

                    content.Add(streamContent, "content", Stream.FileName ?? "content");
                }

                return content;
            } catch
            {
                content.Dispose();
                throw;
            }
        }

        protected IList<KeyValuePair<string, string>> CreateContent()
        {
            IList<KeyValuePair<string, string>> result = new List<KeyValuePair<string, string>>();

            // set cmisaction
            result.Add(new KeyValuePair<string, string>(BindingConstants.ControlCmisAction, CmisAction));

            // set parameters
            if (parameters != null)
            {
                foreach (KeyValuePair<string, object> p in parameters)
                {
                    if (p.Value != null)
                    {
                        result.Add(new KeyValuePair<string, string>(p.Key, UrlBuilder.NormalizeParameter(p.Value)));
                    }
                }
            }

            // set succinct
            if (Succinct)
            {
                result.Add(new KeyValuePair<string, string>(BindingConstants.ControlSuccinct, "true"));
            }

            // set properties
            AddPropertiesParameters(Properties, result);

            // set Aces
            AddAcesParameters(AddAces, BindingConstants.ControlAddAcePrincipal, BindingConstants.ControlAddAcePermission, result);
            AddAcesParameters(RemoveAces, BindingConstants.ControlRemoveAcePrincipal, BindingConstants.ControlRemoveAcePermission, result);

            // set policies
            AddPoliciesParameters(Policies, result);
            AddPolicyIdParameter(PolicyId, result);

            // set secondary type IDs
            AddSecondaryTypeIdParameters(AddSecondaryTypeIds, BindingConstants.ControlAddSecondaryType, result);
            AddSecondaryTypeIdParameters(RemoveSecondaryTypeIds, BindingConstants.ControlRemoveSecondaryType, result);

            // set bulk update values
            AddObjectIdsAndChangeTokens(ObjectIdsAndChangeTokens, result);

            return result;
        }

        private void AddPropertiesParameters(IProperties properties, IList<KeyValuePair<string, string>> result)
        {
            if (properties == null || properties.PropertyList == null)
            {
                return;
            }

            int idx = 0;
            foreach (PropertyData prop in properties.PropertyList)
            {
                if (prop == null)
                {
                    continue;
                }

                string idxStr = "[" + idx + "]";
                result.Add(new KeyValuePair<string, string>(BindingConstants.ControlPropId + idxStr, prop.Id));

                if (prop.Values != null && prop.Values.Count > 0)
                {
                    if (prop.Values.Count == 1)
                    {
                        result.Add(new KeyValuePair<string, string>(
                            BindingConstants.ControlPropValue + idxStr, ConvertPropertyValue(prop.FirstValue, DateTimeFormat)));
                    }
                    else
                    {
                        int vidx = 0;
                        foreach (object obj in prop.Values)
                        {
                            string vidxStr = "[" + vidx + "]";
                            result.Add(new KeyValuePair<string, string>(
                                BindingConstants.ControlPropValue + idxStr + vidxStr, ConvertPropertyValue(obj, DateTimeFormat)));
                            vidx++;
                        }
                    }
                }
                idx++;
            }
        }

        private void AddAcesParameters(IAcl acl, string principalControl, string permissionControl, IList<KeyValuePair<string, string>> result)
        {
            if (acl == null || acl.Aces == null)
            {
                return;
            }

            int idx = 0;
            foreach (IAce ace in acl.Aces)
            {
                if (ace.PrincipalId != null && ace.Permissions != null && ace.Permissions.Count > 0)
                {
                    string idxStr = "[" + idx + "]";
                    result.Add(new KeyValuePair<string, string>(principalControl + idxStr, ace.PrincipalId));

                    int permIdx = 0;
                    foreach (string perm in ace.Permissions)
                    {
                        if (perm != null)
                        {
                            string permIdxStr = "[" + permIdx + "]";
                            result.Add(new KeyValuePair<string, string>(permissionControl + idxStr + permIdxStr, perm));
                            permIdx++;
                        }
                    }
                    idx++;
                }
            }
        }

        private void AddPoliciesParameters(IList<string> policies, IList<KeyValuePair<string, string>> result)
        {
            if (policies == null)
            {
                return;
            }

            int idx = 0;
            foreach (string policy in policies)
            {
                if (policy != null)
                {
                    string idxStr = "[" + idx + "]";
                    result.Add(new KeyValuePair<string, string>(BindingConstants.ControlPolicy + idxStr, policy));
                    idx++;
                }
            }
        }

        private void AddPolicyIdParameter(string policyId, IList<KeyValuePair<string, string>> result)
        {
            if (policyId == null)
            {
                return;
            }

            result.Add(new KeyValuePair<string, string>(BindingConstants.ControlPolicyId, policyId));
        }

        private void AddSecondaryTypeIdParameters(IList<string> secondaryTypeIds, string secondaryTypeIdControl, IList<KeyValuePair<string, string>> result)
        {
            if (secondaryTypeIds == null || secondaryTypeIds.Count == 0)
            {
                return;
            }

            int idx = 0;
            foreach (string typeId in secondaryTypeIds)
            {
                if (string.IsNullOrEmpty(typeId))
                {
                    continue;
                }

                string idxStr = "[" + idx + "]";
                result.Add(new KeyValuePair<string, string>(secondaryTypeIdControl + idxStr, typeId));

                idx++;
            }
        }

        public void AddObjectIdsAndChangeTokens(IList<IBulkUpdateObjectIdAndChangeToken> objectIdsAndChangeTokens, IList<KeyValuePair<string, string>> result)
        {
            if (objectIdsAndChangeTokens == null || objectIdsAndChangeTokens.Count == 0)
            {
                return;
            }

            int idx = 0;
            foreach (IBulkUpdateObjectIdAndChangeToken oc in objectIdsAndChangeTokens)
            {
                if (oc == null || oc.Id == null || oc.Id.Length == 0)
                {
                    continue;
                }

                string idxStr = "[" + idx + "]";
                result.Add(new KeyValuePair<string, string>(BindingConstants.ControlObjectId + idxStr, oc.Id));
                result.Add(new KeyValuePair<string, string>(BindingConstants.ControlChangeToken + idxStr, oc.ChangeToken ?? ""));

                idx++;
            }
        }

        private string ConvertPropertyValue(object value, DateTimeFormat dateTimeFormat)
        {
            if (value == null)
            {
                return null;
            }
            else if (value is string)
            {
                return (string)value;
            }
            else if (value is DateTime)
            {
                if (DateTimeFormat == DateTimeFormat.Extended)
                {
                    return DateTimeHelper.FormatISO8601((DateTime)value);
                }
                else
                {
                    return DateTimeHelper.ConvertDateTimeToMillis((DateTime)value).ToString(CultureInfo.InvariantCulture);
                }
            }
            else if (value is decimal)
            {
                return ((decimal)value).ToString("g", CultureInfo.InvariantCulture);
            }
            else if (value is BigInteger)
            {
                return ((BigInteger)value).ToString("0", CultureInfo.InvariantCulture);
            }
            else if (value is Boolean)
            {
                return (Boolean)value ? "true" : "false";
            }
            else if (value is Double)
            {
                if (Double.IsInfinity((Double)value) || Double.IsNaN((Double)value))
                {
                    return "null";
                }
                else
                {
                    return ((Double)value).ToString("g", CultureInfo.InvariantCulture);
                }
            }
            else if (value is Single)
            {
                if (Single.IsInfinity((Single)value) || Single.IsNaN((Single)value))
                {
                    return "null";
                }
                else
                {
                    return ((Single)value).ToString("g", CultureInfo.InvariantCulture);
                }
            }
            else
            {
                try
                {
                    return Convert.ToInt64(value, CultureInfo.InvariantCulture).ToString("0", CultureInfo.InvariantCulture);
                }
                catch
                {
                    return value.ToString();
                }
            }
        }
    }


    /// <summary>
    /// Common service data and operations.
    /// </summary>
    internal abstract class AbstractBrowserBindingService
    {
        private BindingSession session;

        public BindingSession Session
        {
            get
            {
                return session;
            }
            protected set
            {
                session = value;

                Succinct = true;
                object succintObj = session.GetValue(SessionParameter.BrowserSuccinct);
                if (succintObj is string)
                {
                    Succinct = Convert.ToBoolean((string)succintObj, CultureInfo.InvariantCulture);
                }

                DateTimeFormat = DateTimeFormat.Simple;
                object dateTimeFormatObj = session.GetValue(SessionParameter.BrowserDateTimeFormat);
                if (dateTimeFormatObj is string)
                {
                    DateTimeFormat? dtf = ((string)dateTimeFormatObj).GetCmisEnum<DateTimeFormat>();
                    DateTimeFormat = dtf ?? DateTimeFormat.Simple;
                }
            }
        }
        protected bool Succinct { get; private set; }
        protected string SuccinctParameter { get { return Succinct ? "true" : null; } }

        protected DateTimeFormat DateTimeFormat { get; private set; }
        protected string DateTimeFormatParameter { get { return DateTimeFormat == DateTimeFormat.Simple ? null : DateTimeFormat.GetCmisValue(); } }

        protected string GetServiceUrl()
        {
            return Session.GetValue(SessionParameter.BrowserUrl) as string;
        }

        protected UrlBuilder GetRepositoryUrl(string repositoryId, string selector)
        {
            UrlBuilder result = GetRepositoryUrlCache().GetRepositoryUrl(repositoryId, selector);

            if (result == null)
            {
                GetRepositoriesInternal(repositoryId);
                result = GetRepositoryUrlCache().GetRepositoryUrl(repositoryId, selector);
            }

            if (result == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            return result;
        }

        protected UrlBuilder GetRepositoryUrl(string repositoryId)
        {
            UrlBuilder result = GetRepositoryUrlCache().GetRepositoryUrl(repositoryId);

            if (result == null)
            {
                GetRepositoriesInternal(repositoryId);
                result = GetRepositoryUrlCache().GetRepositoryUrl(repositoryId);
            }

            if (result == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            return result;
        }

        protected UrlBuilder GetObjectUrl(string repositoryId, string objectId, string selector)
        {
            UrlBuilder result = GetRepositoryUrlCache().GetObjectUrl(repositoryId, objectId, selector);

            if (result == null)
            {
                GetRepositoriesInternal(repositoryId);
                result = GetRepositoryUrlCache().GetObjectUrl(repositoryId, objectId, selector);
            }

            if (result == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            return result;
        }

        protected UrlBuilder GetObjectUrl(string repositoryId, string objectId)
        {
            UrlBuilder result = GetRepositoryUrlCache().GetObjectUrl(repositoryId, objectId);

            if (result == null)
            {
                GetRepositoriesInternal(repositoryId);
                result = GetRepositoryUrlCache().GetObjectUrl(repositoryId, objectId);
            }

            if (result == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            return result;
        }

        protected UrlBuilder GetPathUrl(string repositoryId, string path, string selector)
        {
            UrlBuilder result = GetRepositoryUrlCache().GetPathUrl(repositoryId, path, selector);

            if (result == null)
            {
                GetRepositoriesInternal(repositoryId);
                result = GetRepositoryUrlCache().GetPathUrl(repositoryId, path, selector);
            }

            if (result == null)
            {
                throw new CmisObjectNotFoundException("Unknown repository!");
            }

            return result;
        }


        protected RepositoryUrlCache GetRepositoryUrlCache()
        {
            RepositoryUrlCache repositoryUrlCache = Session.GetValue(CmisBrowserSpi.RepositoryUrlCache) as RepositoryUrlCache;
            if (repositoryUrlCache == null)
            {
                repositoryUrlCache = new RepositoryUrlCache();
                Session.PutValue(CmisBrowserSpi.RepositoryUrlCache, repositoryUrlCache);
            }

            return repositoryUrlCache;
        }

        protected void SetChangeToken(ref string changeToken, IObjectData obj)
        {
            if (changeToken == null)
            {
                return;
            }

            changeToken = null;

            if (obj == null || obj.Properties == null)
            {
                return;
            }

            IPropertyData ct = obj.Properties[PropertyIds.ChangeToken];
            if (ct != null && ct.PropertyType == PropertyType.String)
            {
                changeToken = (string)ct.FirstValue;
            }
        }

        // ---- exceptions ----

        /// <summary>
        /// Converts an error message or a HTTP status code into an Exception.
        /// </summary>
        protected CmisBaseException ConvertStatusCode(int code, string message, string errorContent, Exception e)
        {
            object obj = null;
            try
            {
                if (errorContent != null)
                {
                    JsonParser parser = new JsonParser();
                    StringReader sr = new StringReader(errorContent);
                    try
                    {
                        obj = parser.Parse(sr);
                    }
                    finally
                    {
                        sr.Dispose();
                    }
                }
            }
            catch (JsonParseException)
            {
                // error content is not valid JSON -> ignore
            }

            if (obj is JsonObject)
            {
                JsonObject json = (JsonObject)obj;
                object jsonError = json[BrowserConstants.ErrorException];
                if (jsonError is string)
                {
                    object jsonMessage = json[BrowserConstants.ErrorMessage];
                    if (jsonMessage != null)
                    {
                        message = jsonMessage.ToString();
                    }

                    if (CmisConstraintException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisConstraintException(message, errorContent, e);
                    }
                    else if (CmisContentAlreadyExistsException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisContentAlreadyExistsException(message, errorContent, e);
                    }
                    else if (CmisFilterNotValidException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisFilterNotValidException(message, errorContent, e);
                    }
                    else if (CmisInvalidArgumentException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisInvalidArgumentException(message, errorContent, e);
                    }
                    else if (CmisNameConstraintViolationException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisNameConstraintViolationException(message, errorContent, e);
                    }
                    else if (CmisNotSupportedException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisNotSupportedException(message, errorContent, e);
                    }
                    else if (CmisObjectNotFoundException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisObjectNotFoundException(message, errorContent, e);
                    }
                    else if (CmisPermissionDeniedException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisPermissionDeniedException(message, errorContent, e);
                    }
                    else if (CmisStorageException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisStorageException(message, errorContent, e);
                    }
                    else if (CmisStreamNotSupportedException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisStreamNotSupportedException(message, errorContent, e);
                    }
                    else if (CmisUpdateConflictException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisUpdateConflictException(message, errorContent, e);
                    }
                    else if (CmisVersioningException.ExceptionName.Equals((string)jsonError, StringComparison.OrdinalIgnoreCase))
                    {
                        return new CmisVersioningException(message, errorContent, e);
                    }
                    else if (code == 503)
                    {
                        return new CmisServiceUnavailableException(message, errorContent, e);
                    }
                }
            }

            // fall back to status code
            switch (code)
            {
                case 301:
                case 302:
                case 303:
                case 307:
                    return new CmisConnectionException("Redirects are not supported (HTTP status code " + code + "): " + message, errorContent, e);
                case 400:
                    return new CmisInvalidArgumentException(message, errorContent, e);
                case 401:
                    return new CmisUnauthorizedException(message, errorContent, e);
                case 403:
                    return new CmisPermissionDeniedException(message, errorContent, e);
                case 404:
                    return new CmisObjectNotFoundException(message, errorContent, e);
                case 405:
                    return new CmisNotSupportedException(message, errorContent, e);
                case 407:
                    return new CmisProxyAuthenticationException(message, errorContent, e);
                case 409:
                    return new CmisConstraintException(message, errorContent, e);
                case 503:
                    return new CmisServiceUnavailableException(message, errorContent, e);
                default:
                    return new CmisRuntimeException(message, errorContent, e);
            }
        }


        // ---- helpers ----

        /// <summary>
        /// Parses an object from an input stream.
        /// </summary>
        protected JsonObject ParseObject(Stream stream, string charset)
        {
            object obj = Parse(stream, charset);

            if (obj is JsonObject)
            {
                return (JsonObject)obj;
            }

            throw new CmisConnectionException("Unexpected object!");
        }

        /// <summary>
        /// Parses an array from an input stream.
        /// </summary>
        protected JsonArray ParseArray(Stream stream, string charset)
        {
            object obj = Parse(stream, charset);

            if (obj is JsonArray)
            {
                return (JsonArray)obj;
            }

            throw new CmisConnectionException("Unexpected object!");
        }

        /// <summary>
        /// Parses an input stream.
        /// </summary>
        protected object Parse(Stream stream, string charset)
        {
            Encoding enc;
            if (charset == null)
            {
                enc = Encoding.UTF8;
            }
            else
            {
                try
                {
                    enc = Encoding.GetEncoding(charset);
                }
                catch (Exception e)
                {
                    throw new CmisConnectionException("Unsupported charset: " + charset, e);
                }
            }

            StreamReader reader = null;

            object obj = null;
            try
            {
                reader = new StreamReader(stream, enc);
                JsonParser parser = new JsonParser();
                obj = parser.Parse(reader);
            }
            catch (Exception e)
            {
                throw new CmisConnectionException("Parsing exception!", e);
            }
            finally
            {
                IOUtils.ConsumeAndClose(reader);
                if (reader == null)
                {
                    stream.Dispose();
                }
            }

            return obj;
        }

        /// <summary>
        /// Performs a GET on an URL, checks the response code and returns the
        /// result.
        /// </summary>
        protected IResponse Read(UrlBuilder url)
        {
            // make the call
            IResponse resp = Session.GetHttpInvoker().InvokeGET(url, session);

            // check response code
            if (resp.StatusCode != 200)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            return resp;
        }


        /// <summary>
        /// Performs a POST on an URL, checks the response code and returns the
        /// result.
        /// </summary>
        protected IResponse Post(UrlBuilder url, HttpContent content)
        {
            // make the call
            IResponse resp = Session.GetHttpInvoker().InvokePOST(url, content, session);

            // check response code
            if (resp.StatusCode != 200 && resp.StatusCode != 201)
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            return resp;
        }

        /// <summary>
        /// Performs a POST on an URL, checks the response code and returns the
        /// result.
        /// </summary>
        protected void PostAndConsume(UrlBuilder url, HttpContent content)
        {
            IResponse resp = Post(url, content);
            IOUtils.ConsumeAndClose(resp.Stream);
        }

        // -----

        protected IList<IRepositoryInfo> GetRepositoriesInternal(string repositoryId)
        {
            UrlBuilder url = null;

            if (repositoryId == null)
            {
                // no repository id provided -> get all
                url = new UrlBuilder(GetServiceUrl());
            }
            else
            {
                // use URL of the specified repository
                url = GetRepositoryUrlCache().GetRepositoryUrl(repositoryId, BindingConstants.SelectorRepositoryInfo);
                if (url == null)
                {
                    // repository infos haven't been fetched yet -> get them all
                    url = new UrlBuilder(GetServiceUrl());
                }
            }

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            IList<IRepositoryInfo> repInfos = new List<IRepositoryInfo>();

            foreach (KeyValuePair<string, object> jri in json)
            {
                if (jri.Value is JsonObject)
                {
                    IRepositoryInfo ri = JsonConverter.ConvertRepositoryInfo((JsonObject)jri.Value);
                    string id = ri.Id;

                    if (ri is RepositoryInfoBrowserBinding)
                    {
                        string repositoryUrl = ((RepositoryInfoBrowserBinding)ri).RepositoryUrl;
                        string rootUrl = ((RepositoryInfoBrowserBinding)ri).RootUrl;

                        if (id == null || repositoryUrl == null || rootUrl == null)
                        {
                            throw new CmisConnectionException("Found invalid Repository Info! (id: " + id + ")");
                        }

                        GetRepositoryUrlCache().AddRepository(id, repositoryUrl, rootUrl);
                    }

                    repInfos.Add(ri);
                }
                else
                {
                    throw new CmisConnectionException("Found invalid Repository Info!");
                }
            }

            return repInfos;
        }

        /// <summary>
        /// Retrieves a type definition.
        /// </summary>
        public ITypeDefinition GetTypeDefinitionInternal(string repositoryId, string typeId)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId, BindingConstants.SelectorTypeDefinition);
            url.AddParameter(BindingConstants.ParamTypeId, typeId);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertTypeDefinition(json);
        }
    }

    internal class RepositoryService : AbstractBrowserBindingService, 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);

            if (repositoryInfos.Count == 0)
            {
                throw new CmisObjectNotFoundException("Repository '" + repositoryId + "'not found!");
            }

            if (repositoryInfos.Count == 1)
            {
                return repositoryInfos[0];
            }

            // find the repository
            foreach (IRepositoryInfo info in repositoryInfos)
            {
                if (info.Id == null)
                {
                    continue;
                }

                if (info.Id == repositoryId)
                {
                    return info;
                }
            }

            throw new CmisObjectNotFoundException("Repository '" + repositoryId + "'not found!");
        }

        public ITypeDefinitionList GetTypeChildren(string repositoryId, string typeId, bool? includePropertyDefinitions,
            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId, BindingConstants.SelectorTypeChildren);
            url.AddParameter(BindingConstants.ParamTypeId, typeId);
            url.AddParameter(BindingConstants.ParamPropertyDefinitions, includePropertyDefinitions);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSkipCount, skipCount);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertTypeChildren(json);
        }

        public IList<ITypeDefinitionContainer> GetTypeDescendants(string repositoryId, string typeId, BigInteger? depth,
            bool? includePropertyDefinitions, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId, BindingConstants.SelectorTypeDecendants);
            url.AddParameter(BindingConstants.ParamTypeId, typeId);
            url.AddParameter(BindingConstants.ParamDepth, depth);
            url.AddParameter(BindingConstants.ParamPropertyDefinitions, includePropertyDefinitions);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            return JsonConverter.ConvertTypeDescendants(json);
        }

        public ITypeDefinition GetTypeDefinition(string repositoryId, string typeId, IExtensionsData extension)
        {
            return GetTypeDefinitionInternal(repositoryId, typeId);
        }


        public ITypeDefinition CreateType(string repositoryId, ITypeDefinition type, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateType);
            if (type != null)
            {
                StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
                try
                {
                    JsonConverter.Convert(type, DateTimeFormat).WriteJsonString(sw);
                    composer.Parameters[BindingConstants.ControlType] = sw.ToString();
                }
                finally
                {
                    sw.Dispose();
                }
            }

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertTypeDefinition(json);
        }

        public ITypeDefinition UpdateType(string repositoryId, ITypeDefinition type, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionUpdateType);
            if (type != null)
            {
                StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
                try
                {
                    JsonConverter.Convert(type, DateTimeFormat).WriteJsonString(sw);
                    composer.Parameters[BindingConstants.ControlType] = sw.ToString();
                }
                finally
                {
                    sw.Dispose();
                }
            }

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertTypeDefinition(json);
        }

        public void DeleteType(string repositoryId, string typeId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionDeleteType);
            composer.Parameters[BindingConstants.ControlTypeId] = typeId;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }
    }

    internal class NavigationService : AbstractBrowserBindingService, 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, BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorChildren);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamOrderBy, orderBy);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPathSegment, includePathSegment);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSkipCount, skipCount);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjectInFolderList(json, typeCache);
        }

        public IList<IObjectInFolderContainer> GetDescendants(string repositoryId, string folderId, BigInteger? depth, string filter,
            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,
            bool? includePathSegment, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorDecendants);
            url.AddParameter(BindingConstants.ParamDepth, depth);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPathSegment, includePathSegment);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertDescendants(json, typeCache);
        }

        public IList<IObjectInFolderContainer> GetFolderTree(string repositoryId, string folderId, BigInteger? depth, string filter,
            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,
            bool? includePathSegment, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorFolderTree);
            url.AddParameter(BindingConstants.ParamDepth, depth);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPathSegment, includePathSegment);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertDescendants(json, typeCache);
        }

        public IList<IObjectParentData> GetObjectParents(string repositoryId, string objectId, string filter,
            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,
            bool? includeRelativePathSegment, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorParents);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamRelativePathSegment, includeRelativePathSegment);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjectParents(json, typeCache);
        }

        public IObjectData GetFolderParent(string repositoryId, string folderId, string filter, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorParent);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObject(json, typeCache);
        }

        public IObjectList GetCheckedOutDocs(string repositoryId, string folderId, string filter, string orderBy,
            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,
            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = (folderId != null ? GetObjectUrl(repositoryId, folderId, BindingConstants.SelectorCheckedout)
                    : GetRepositoryUrl(repositoryId, BindingConstants.SelectorCheckedout));
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamOrderBy, orderBy);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSkipCount, skipCount);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjectList(json, typeCache, false);
        }
    }

    internal class ObjectService : AbstractBrowserBindingService, 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)
        {
            // build URL
            UrlBuilder url = (folderId != null ? GetObjectUrl(repositoryId, folderId) : GetRepositoryUrl(repositoryId));

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateDocument);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Parameters[BindingConstants.ParamVersioningState] = versioningState;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;
            composer.Stream = contentStream;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);
            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public string CreateDocumentFromSource(string repositoryId, string sourceId, IProperties properties, string folderId,
            VersioningState? versioningState, IList<string> policies, IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = (folderId != null ? GetObjectUrl(repositoryId, folderId) : GetRepositoryUrl(repositoryId));

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateDocumentFromSource);
            composer.Parameters[BindingConstants.ParamSourceId] = sourceId;
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Parameters[BindingConstants.ParamVersioningState] = versioningState;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public string CreateFolder(string repositoryId, IProperties properties, string folderId, IList<string> policies,
            IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateFolder);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public string CreateRelationship(string repositoryId, IProperties properties, IList<string> policies, IAcl addAces,
            IAcl removeAces, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateRelationship);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public string CreatePolicy(string repositoryId, IProperties properties, string folderId, IList<string> policies,
            IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = (folderId != null ? GetObjectUrl(repositoryId, folderId) : GetRepositoryUrl(repositoryId));

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreatePolicy);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public string CreateItem(string repositoryId, IProperties properties, string folderId, IList<string> policies,
            IAcl addAces, IAcl removeAces, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = (folderId != null ? GetObjectUrl(repositoryId, folderId) : GetRepositoryUrl(repositoryId));

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCreateItem);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            return newObj?.Id;
        }

        public IAllowableActions GetAllowableActions(string repositoryId, string objectId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorAllowableActionS);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertAllowableActions(json);
        }

        public IProperties GetProperties(string repositoryId, string objectId, string filter, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorProperties);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            if (Succinct)
            {
                ITypeCache typeCache = new ClientTypeCache(repositoryId, this);
                return JsonConverter.ConvertSuccinctProperties(json, null, typeCache);
            }
            else
            {
                return JsonConverter.ConvertProperties(json, null);
            }
        }

        public IList<IRenditionData> GetRenditions(string repositoryId, string objectId, string renditionFilter,
            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorRenditions);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSkipCount, skipCount);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            return JsonConverter.ConvertRenditions(json);
        }

        public IObjectData GetObject(string repositoryId, string objectId, string filter, bool? includeAllowableActions,
            IncludeRelationships? includeRelationships, string renditionFilter, bool? includePolicyIds,
            bool? includeAcl, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorObject);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPolicyIds, includePolicyIds);
            url.AddParameter(BindingConstants.ParamAcl, includeAcl);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObject(json, typeCache);
        }

        public IObjectData GetObjectByPath(string repositoryId, string path, string filter, bool? includeAllowableActions,
            IncludeRelationships? includeRelationships, string renditionFilter, bool? includePolicyIds, bool? includeAcl,
            IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetPathUrl(repositoryId, path, BindingConstants.SelectorObject);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPolicyIds, includePolicyIds);
            url.AddParameter(BindingConstants.ParamAcl, includeAcl);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObject(json, typeCache);
        }

        public IContentStream GetContentStream(string repositoryId, string objectId, string streamId, BigInteger? offset, BigInteger? length,
            IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorContent);
            url.AddParameter(BindingConstants.ParamStreamId, streamId);

            // get the content
            IResponse resp = Session.GetHttpInvoker().InvokeGET(url, Session, (long?)offset, (long?)length);

            // check response code
            if ((resp.StatusCode != 200) && (resp.StatusCode != 206))
            {
                throw ConvertStatusCode(resp.StatusCode, resp.Message, resp.ErrorContent, null);
            }

            // build result object
            ContentStream result;
            if (resp.StatusCode == 206)
            {
                result = new PartialContentStream();
            }
            else
            {
                result = new ContentStream();
            }

            result.FileName = resp.Filename;
            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 (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionUpdateProperties);
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Parameters[BindingConstants.ParamChangeToken] =
                (changeToken == null || Session.GetValue(SessionParameter.OmitChangeTokens, false) ? null : changeToken);

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;

            SetChangeToken(ref changeToken, newObj);
        }

        public IList<IBulkUpdateObjectIdAndChangeToken> BulkUpdateProperties(string repositoryId,
                IList<IBulkUpdateObjectIdAndChangeToken> objectIdAndChangeToken, IProperties properties,
                IList<string> addSecondaryTypeIds, IList<string> removeSecondaryTypeIds, IExtensionsData extension)
        {
            // we need object ids
            if (objectIdAndChangeToken == null || objectIdAndChangeToken.Count == 0)
            {
                throw new CmisInvalidArgumentException("Object IDs must be set!");
            }

            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionBulkUpdate);
            composer.ObjectIdsAndChangeTokens = objectIdAndChangeToken;
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.AddSecondaryTypeIds = addSecondaryTypeIds;
            composer.RemoveSecondaryTypeIds = removeSecondaryTypeIds;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            return JsonConverter.ConvertBulkUpdate(json);
        }

        public void MoveObject(string repositoryId, ref string objectId, string targetFolderId, string sourceFolderId,
            IExtensionsData extension)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionMove);
            composer.Parameters[BindingConstants.ParamTargetFolderId] = targetFolderId;
            composer.Parameters[BindingConstants.ParamSourceFolderId] = sourceFolderId;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;
        }

        public void DeleteObject(string repositoryId, string objectId, bool? allVersions, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionDelete);
            composer.Parameters[BindingConstants.ParamAllVersions] = allVersions;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }

        public IFailedToDeleteData DeleteTree(string repositoryId, string folderId, bool? allVersions, UnfileObject? unfileObjects,
            bool? continueOnFailure, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, folderId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionDeleteTree);
            composer.Parameters[BindingConstants.ParamAllVersions] = allVersions;
            composer.Parameters[BindingConstants.ParamUnfileObjects] = unfileObjects;
            composer.Parameters[BindingConstants.ParamContinueOnFailure] = continueOnFailure;

            // send
            IResponse resp = Post(url, composer.CreateHttpContent());

            if (resp.StatusCode == 200 && resp.ContentLength > 0 && (!resp.Stream.CanSeek || resp.Stream.Length > 0))
            {
                try
                {
                    JsonObject json = ParseObject(resp.Stream, resp.Charset);
                    return JsonConverter.ConvertFailedToDelete(json);
                }
                catch (IOException e)
                {
                    throw new CmisConnectionException("Cannot read response!", e);
                }
            }

            return new FailedToDeleteData();
        }

        public void SetContentStream(string repositoryId, ref string objectId, bool? overwriteFlag, ref string changeToken,
            IContentStream contentStream, IExtensionsData extension)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionSetContent);
            composer.Stream = contentStream;
            composer.Parameters[BindingConstants.ParamOverwriteFlag] = overwriteFlag;
            composer.Succinct = Succinct;
            composer.Parameters[BindingConstants.ParamChangeToken] =
                (changeToken == null || Session.GetValue(SessionParameter.OmitChangeTokens, false) ? null : changeToken);


            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;

            SetChangeToken(ref changeToken, newObj);
        }

        public void AppendContentStream(string repositoryId, ref string objectId, bool? isLastChunk, ref string changeToken,
            IContentStream contentStream, IExtensionsData extension)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionAppendContent);
            composer.Stream = contentStream;
            composer.Parameters[BindingConstants.ControlIsLastChunk] = isLastChunk;
            composer.Succinct = Succinct;
            composer.Parameters[BindingConstants.ParamChangeToken] =
                (changeToken == null || Session.GetValue(SessionParameter.OmitChangeTokens, false) ? null : changeToken);

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;

            SetChangeToken(ref changeToken, newObj);
        }

        public void DeleteContentStream(string repositoryId, ref string objectId, ref string changeToken, IExtensionsData extension)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionDeleteContent);
            composer.Succinct = Succinct;
            composer.Parameters[BindingConstants.ParamChangeToken] =
                (changeToken == null || Session.GetValue(SessionParameter.OmitChangeTokens, false) ? null : changeToken);

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;

            SetChangeToken(ref changeToken, newObj);
        }
    }

    internal class VersioningService : AbstractBrowserBindingService, IVersioningService
    {
        public VersioningService(BindingSession session)
        {
            Session = session;
        }

        public void CheckOut(string repositoryId, ref string objectId, IExtensionsData extension, out bool? contentCopied)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCheckOut);
            composer.Succinct = Succinct;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;

            contentCopied = null;
        }

        public void CancelCheckOut(string repositoryId, string objectId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCancelCheckOut);

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }

        public void CheckIn(string repositoryId, ref string objectId, bool? major, IProperties properties,
            IContentStream contentStream, string checkinComment, IList<string> policies, IAcl addAces, IAcl removeAces,
            IExtensionsData extension)
        {
            // we need an object id
            if (string.IsNullOrEmpty(objectId))
            {
                throw new CmisInvalidArgumentException("Object ID must be set!");
            }

            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionCheckIn);
            composer.Stream = contentStream;
            composer.Parameters[BindingConstants.ParamMajor] = major;
            composer.Properties = properties;
            composer.Succinct = Succinct;
            composer.DateTimeFormat = DateTimeFormat;
            composer.Parameters[BindingConstants.ParamCheckinComment] = checkinComment;
            composer.Policies = policies;
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            IObjectData newObj = JsonConverter.ConvertObject(json, typeCache);

            objectId = newObj?.Id;
        }

        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)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorObject);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamRelationships, includeRelationships);
            url.AddParameter(BindingConstants.ParamRenditionfilter, renditionFilter);
            url.AddParameter(BindingConstants.ParamPolicyIds, includePolicyIds);
            url.AddParameter(BindingConstants.ParamAcl, includeAcl);
            url.AddParameter(BindingConstants.ParamReturnVersion, (major == true ? ReturnVersion.LatestMajor : ReturnVersion.Latest));
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);

            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObject(json, typeCache);
        }

        public IProperties GetPropertiesOfLatestVersion(string repositoryId, string objectId, string versionSeriesId, bool? major,
            string filter, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorProperties);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamReturnVersion, (major == true ? ReturnVersion.LatestMajor : ReturnVersion.Latest));
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            if (Succinct)
            {
                ITypeCache typeCache = new ClientTypeCache(repositoryId, this);
                return JsonConverter.ConvertSuccinctProperties(json, null, typeCache);
            }
            else
            {
                return JsonConverter.ConvertProperties(json, null);
            }
        }

        public IList<IObjectData> GetAllVersions(string repositoryId, string objectId, string versionSeriesId, string filter,
            bool? includeAllowableActions, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorVersions);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);

            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjects(json, typeCache);
        }
    }

    internal class DiscoveryService : AbstractBrowserBindingService, IDiscoveryService
    {
        public DiscoveryService(BindingSession session)
        {
            Session = session;
        }

        public IObjectList Query(string repositoryId, string statement, bool? searchAllVersions,
            bool? includeAllowableActions, IncludeRelationships? includeRelationships, string renditionFilter,
            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionQuery);
            composer.Parameters[BindingConstants.ParamStatement] = statement;
            composer.Parameters[BindingConstants.ParamSearchAllVersions] = searchAllVersions;
            composer.Parameters[BindingConstants.ParamAllowableActions] = includeAllowableActions;
            composer.Parameters[BindingConstants.ParamRelationships] = includeRelationships;
            composer.Parameters[BindingConstants.ParamRenditionfilter] = renditionFilter;
            composer.Parameters[BindingConstants.ParamMaxItems] = maxItems;
            composer.Parameters[BindingConstants.ParamSkipCount] = skipCount;
            composer.DateTimeFormat = DateTimeFormat;
            // Important: No succinct flag here!!!

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            JsonObject json = ParseObject(resp.Stream, resp.Charset);
            return JsonConverter.ConvertObjectList(json, typeCache, true);
        }

        public IObjectList GetContentChanges(string repositoryId, ref string changeLogToken, bool? includeProperties,
           string filter, bool? includePolicyIds, bool? includeAcl, BigInteger? maxItems, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetRepositoryUrl(repositoryId, BindingConstants.SelectorContentChanges);
            url.AddParameter(BindingConstants.ParamChangeLogToken, changeLogToken);
            url.AddParameter(BindingConstants.ParamProperties, includeProperties);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamPolicyIds, includePolicyIds);
            url.AddParameter(BindingConstants.ParamAcl, includeAcl);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            if (changeLogToken != null && json != null)
            {
                object token = json[BrowserConstants.JsonObjectListChangeLogToken];
                if (token is string)
                {
                    changeLogToken = (string)token;
                }
            }

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjectList(json, typeCache, false);
        }
    }

    internal class RelationshipService : AbstractBrowserBindingService, IRelationshipService
    {
        public RelationshipService(BindingSession session)
        {
            Session = session;
        }

        public IObjectList GetObjectRelationships(string repositoryId, string objectId, bool? includeSubRelationshipTypes,
            RelationshipDirection? relationshipDirection, string typeId, string filter, bool? includeAllowableActions,
            BigInteger? maxItems, BigInteger? skipCount, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorRelationships);
            url.AddParameter(BindingConstants.ParamSubRelationshipTypes, includeSubRelationshipTypes);
            url.AddParameter(BindingConstants.ParamRelationshipDirection, relationshipDirection);
            url.AddParameter(BindingConstants.ParamTypeId, typeId);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamAllowableActions, includeAllowableActions);
            url.AddParameter(BindingConstants.ParamMaxItems, maxItems);
            url.AddParameter(BindingConstants.ParamSkipCount, skipCount);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjectList(json, typeCache, false);
        }
    }

    internal class MultiFilingService : AbstractBrowserBindingService, IMultiFilingService
    {
        public MultiFilingService(BindingSession session)
        {
            Session = session;
        }

        public void AddObjectToFolder(string repositoryId, string objectId, string folderId, bool? allVersions, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionRemoveObjectToFolder);
            composer.Parameters[BindingConstants.ParamFolderId] = folderId;
            composer.Parameters[BindingConstants.ParamAllVersions] = allVersions;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }

        public void RemoveObjectFromFolder(string repositoryId, string objectId, string folderId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionRemoveObjectFromFolder);
            composer.Parameters[BindingConstants.ParamFolderId] = folderId;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }
    }

    internal class PolicyService : AbstractBrowserBindingService, IPolicyService
    {
        public PolicyService(BindingSession session)
        {
            Session = session;
        }

        public void ApplyPolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionApplyPolicy);
            composer.PolicyId = policyId;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }

        public void RemovePolicy(string repositoryId, string policyId, string objectId, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionRemovePolicy);
            composer.PolicyId = policyId;

            // send
            PostAndConsume(url, composer.CreateHttpContent());
        }

        public IList<IObjectData> GetAppliedPolicies(string repositoryId, string objectId, string filter, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorPolicies);
            url.AddParameter(BindingConstants.ParamFilter, filter);
            url.AddParameter(BindingConstants.ParamSuccinct, SuccinctParameter);
            url.AddParameter(BindingConstants.ParamDateTimeFormat, DateTimeFormatParameter);

            // read and parse
            IResponse resp = Read(url);
            JsonArray json = ParseArray(resp.Stream, resp.Charset);

            ITypeCache typeCache = new ClientTypeCache(repositoryId, this);

            return JsonConverter.ConvertObjects(json, typeCache);
        }
    }

    internal class AclService : AbstractBrowserBindingService, IAclService
    {
        public AclService(BindingSession session)
        {
            Session = session;
        }

        public IAcl GetAcl(string repositoryId, string objectId, bool? onlyBasicPermissions, IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId, BindingConstants.SelectorAcl);
            url.AddParameter(BindingConstants.ParamOnlyBasicPermissions, onlyBasicPermissions);

            // read and parse
            IResponse resp = Read(url);
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertAcl(json);
        }

        public IAcl ApplyAcl(string repositoryId, string objectId, IAcl addAces, IAcl removeAces, AclPropagation? aclPropagation,
            IExtensionsData extension)
        {
            // build URL
            UrlBuilder url = GetObjectUrl(repositoryId, objectId);

            // prepare form data
            FormDataComposer composer = new FormDataComposer(BindingConstants.CmisActionApplyAcl);
            composer.AddAces = addAces;
            composer.RemoveAces = removeAces;
            composer.Parameters[BindingConstants.ParamAclPropagation] = aclPropagation;

            // send and parse
            IResponse resp = Post(url, composer.CreateHttpContent());
            JsonObject json = ParseObject(resp.Stream, resp.Charset);

            return JsonConverter.ConvertAcl(json);
        }
    }
}