/*
 * 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.
 */
package org.apache.chemistry.opencmis.client.api;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.spi.CmisBinding;

/**
 * A session is a connection to a CMIS repository with a specific user.
 * <p>
 * CMIS itself is stateless. OpenCMIS uses the concept of a session to cache
 * data across calls and to deal with user authentication. The session object is
 * also used as entry point to all CMIS operations and objects. Because a
 * session is only a client side concept, the session object needs not to be
 * closed or released when it's not needed anymore.
 * <p>
 * Not all operations provided by this API might be supported by the connected
 * repository. Either OpenCMIS or the repository will throw an exception if an
 * unsupported operation is called. The capabilities of the repository can be
 * discovered by evaluating the repository info (see
 * {@link #getRepositoryInfo()}).
 * <p>
 * Almost all methods might throw exceptions derived from
 * {@link CmisBaseException} which is a runtime exception. See the CMIS
 * specification for a list of all operations and their exceptions. Note that
 * some incompliant repositories might throw other exception than you expect.
 * <p>
 * Refer to the <a href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/">CMIS 1.0
 * specification</a> or the <a
 * href="http://docs.oasis-open.org/cmis/CMIS/v1.0/os/">CMIS 1.1
 * specification</a> for details about the domain model, terms, concepts, base
 * types, properties, IDs and query names, query language, etc.
 * </p>
 */
public interface Session extends Serializable {

    /**
     * Clears all cached data.
     */
    void clear();

    // session context

    /**
     * Returns the underlying binding object.
     * 
     * @return the binding object, not {@code null}
     */
    CmisBinding getBinding();

    /**
     * Returns the current default operation parameters for filtering, paging
     * and caching.
     * 
     * <p>
     * <em>Please note:</em> The returned object is not thread-safe and should
     * only be modified right after the session has been created and before the
     * session object has been used. In order to change the default context in
     * thread-safe manner, create a new {@link OperationContext} object and use
     * {@link #setDefaultContext(OperationContext)} to apply it.
     * </p>
     * 
     * @return the default operation context, not {@code null}
     */
    OperationContext getDefaultContext();

    /**
     * Sets the current session parameters for filtering, paging and caching.
     * 
     * @param context
     *            the {@code OperationContext} to be used for the session; if
     *            {@code null}, a default context is used
     */
    void setDefaultContext(OperationContext context);

    /**
     * Creates a new operation context object.
     * 
     * @return the newly created operation context object
     */
    OperationContext createOperationContext();

    /**
     * Creates a new operation context object with the given properties.
     * 
     * @param filter
     *            the property filter, a comma separated string of
     *            <em>query names</em> or "*" for all properties or {@code null}
     *            to let the repository determine a set of properties
     * @param includeAcls
     *            indicates whether ACLs should be included or not
     * @param includeAllowableActions
     *            indicates whether Allowable Actions should be included or not
     * @param includePolicies
     *            indicates whether policies should be included or not
     * @param includeRelationships
     *            enum that indicates if and which relationships should be
     *            includes
     * @param renditionFilter
     *            the rendition filter or {@code null} for no renditions
     * @param includePathSegments
     *            indicates whether path segment or the relative path segment
     *            should be included or not
     * @param orderBy
     *            the object order, a comma-separated list of
     *            <em>query names</em> and the ascending modifier "ASC" or the
     *            descending modifier "DESC" for each query name
     * @param cacheEnabled
     *            flag that indicates if the object cache should be used
     * @param maxItemsPerPage
     *            the max items per batch
     * 
     * @return the newly created operation context object
     * 
     * @see OperationContext
     */
    OperationContext createOperationContext(Set<String> filter, boolean includeAcls, boolean includeAllowableActions,
            boolean includePolicies, IncludeRelationships includeRelationships, Set<String> renditionFilter,
            boolean includePathSegments, String orderBy, boolean cacheEnabled, int maxItemsPerPage);

    /**
     * Creates an object ID from a String.
     * 
     * @return the object ID object
     */
    ObjectId createObjectId(String id);

    // localization

    /**
     * Get the current locale to be used for this session.
     * 
     * @return the current locale, may be {@code null}
     */
    Locale getLocale();

    // services

    /**
     * Returns the repository info of the repository associated with this
     * session.
     * 
     * @return the repository info, not {@code null}
     * 
     * @cmis 1.0
     */
    RepositoryInfo getRepositoryInfo();

    /**
     * Gets a factory object that provides methods to create the objects used by
     * this API.
     * 
     * @return the repository info, not {@code null}
     */
    ObjectFactory getObjectFactory();

    // types

    /**
     * Gets the definition of a type.
     * 
     * @param typeId
     *            the ID of the type
     * 
     * @return the type definition
     * 
     * @throws CmisObjectNotFoundException
     *             if a type with the given type ID doesn't exist
     * 
     * @cmis 1.0
     */
    ObjectType getTypeDefinition(String typeId);

    /**
     * Gets the definition of a type.
     * 
     * @param typeId
     *            the ID of the type
     * @param useCache
     *            specifies if the type definition should be first looked up in
     *            the type definition cache, if it is set to {@code false} or
     *            the type definition is not in the cache, the type definition
     *            is loaded from the repository
     * 
     * @return the type definition
     * 
     * @throws CmisObjectNotFoundException
     *             if a type with the given type ID doesn't exist
     * 
     * @cmis 1.0
     */
    ObjectType getTypeDefinition(String typeId, boolean useCache);

    /**
     * Gets the type children of a type.
     * 
     * @param typeId
     *            the type ID or {@code null} to request the base types
     * @param includePropertyDefinitions
     *            indicates whether the property definitions should be included
     *            or not
     * @return the type iterator, not {@code null}
     * 
     * @throws CmisObjectNotFoundException
     *             if a type with the given type ID doesn't exist
     * 
     * @cmis 1.0
     */
    ItemIterable<ObjectType> getTypeChildren(String typeId, boolean includePropertyDefinitions);

    /**
     * Gets the type descendants of a type.
     * 
     * @param typeId
     *            the type ID or {@code null} to request the base types
     * @param includePropertyDefinitions
     *            indicates whether the property definitions should be included
     *            or not
     * @param depth
     *            the tree depth, must be greater than 0 or -1 for infinite
     *            depth
     * 
     * @throws CmisObjectNotFoundException
     *             if a type with the given type ID doesn't exist
     * 
     * @cmis 1.0
     */
    List<Tree<ObjectType>> getTypeDescendants(String typeId, int depth, boolean includePropertyDefinitions);

    /**
     * Creates a new type.
     * 
     * @param type
     *            the type definition
     * 
     * @return the new type definition
     * 
     * @cmis 1.1
     */
    ObjectType createType(TypeDefinition type);

    /**
     * Updates an existing type.
     * 
     * @param type
     *            the type definition updates
     * 
     * @return the updated type definition
     * 
     * @cmis 1.1
     */
    ObjectType updateType(TypeDefinition type);

    /**
     * Deletes a type.
     * 
     * @param typeId
     *            the ID of the type to delete
     * 
     * @cmis 1.1
     */
    void deleteType(String typeId);

    // navigation

    /**
     * Gets the root folder of the repository.
     * 
     * @return the root folder object, not {@code null}
     * 
     * @cmis 1.0
     */
    Folder getRootFolder();

    /**
     * Gets the root folder of the repository with the given
     * {@link OperationContext}.
     * 
     * @return the root folder object, not {@code null}
     * 
     * @cmis 1.0
     */
    Folder getRootFolder(OperationContext context);

    /**
     * Returns all checked out documents.
     * 
     * @see Folder#getCheckedOutDocs()
     * 
     * @cmis 1.0
     */
    ItemIterable<Document> getCheckedOutDocs();

    /**
     * Returns all checked out documents with the given {@link OperationContext}
     * .
     * 
     * @see Folder#getCheckedOutDocs(OperationContext)
     * 
     * @cmis 1.0
     */
    ItemIterable<Document> getCheckedOutDocs(OperationContext context);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the cache is turned off per default {@link OperationContext}, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param objectId
     *            the object ID
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @see #getObject(String)
     * 
     * @cmis 1.0
     */
    CmisObject getObject(ObjectId objectId);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the given {@link OperationContext} has caching turned off, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param objectId
     *            the object ID
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @see #getObject(String, OperationContext)
     * 
     * @cmis 1.0
     */
    CmisObject getObject(ObjectId objectId, OperationContext context);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the cache is turned off per default {@link OperationContext}, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param objectId
     *            the object ID
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @see #getObject(ObjectId)
     * 
     * @cmis 1.0
     */
    CmisObject getObject(String objectId);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the given {@link OperationContext} has caching turned off, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param objectId
     *            the object ID
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @see #getObject(ObjectId, OperationContext)
     * 
     * @cmis 1.0
     */
    CmisObject getObject(String objectId, OperationContext context);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the cache is turned off per default {@link OperationContext}, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param path
     *            the object path
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @cmis 1.0
     */
    CmisObject getObjectByPath(String path);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the given {@link OperationContext} has caching turned off, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param path
     *            the object path
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @cmis 1.0
     */
    CmisObject getObjectByPath(String path, OperationContext context);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the cache is turned off per default {@link OperationContext}, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param parentPath
     *            the path of the parent folder
     * @param name
     *            the (path segment) name of the object in the folder
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @cmis 1.0
     */
    CmisObject getObjectByPath(String parentPath, String name);

    /**
     * Returns a CMIS object from the session cache. If the object is not in the
     * cache or the given {@link OperationContext} has caching turned off, it
     * will load the object from the repository and puts it into the cache.
     * <p>
     * This method might return a stale object if the object has been found in
     * the cache and has been changed in or removed from the repository. Use
     * {@link CmisObject#refresh()} and {@link CmisObject#refreshIfOld(long)} to
     * update the object if necessary.
     * 
     * @param parentPath
     *            the path of the parent folder
     * @param name
     *            the (path segment) name of the object in the folder
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the requested object
     * 
     * @throws CmisObjectNotFoundException
     *             if an object with the given ID doesn't exist
     * 
     * @cmis 1.0
     */
    CmisObject getObjectByPath(String parentPath, String name, OperationContext context);

    /**
     * Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(ObjectId objectId);

    /**
     * Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(ObjectId objectId, OperationContext context);

    /**
     * Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * @param major
     *            if {@code true} the latest major version will be returned,
     *            otherwise the very last version will be returned
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(ObjectId objectId, boolean major, OperationContext context);

    /**
     * /** Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(String objectId);

    /**
     * Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(String objectId, OperationContext context);

    /**
     * Returns the latest version in a version series.
     * 
     * @param objectId
     *            the document ID of an arbitrary version in the version series
     * @param major
     *            if {@code true} the latest major version will be returned,
     *            otherwise the very last version will be returned
     * @param context
     *            the {@link OperationContext} to use
     * 
     * @return the latest document version
     * 
     * @cmis 1.0
     */
    Document getLatestDocumentVersion(String objectId, boolean major, OperationContext context);

    /**
     * Removes the given object from the cache.
     * 
     * @param objectId
     *            object ID
     * 
     * @see #removeObjectFromCache(String)
     */
    void removeObjectFromCache(ObjectId objectId);

    /**
     * Removes the given object from the cache.
     * 
     * @param objectId
     *            object ID
     */
    void removeObjectFromCache(String objectId);

    // discovery

    /**
     * Sends a query to the repository. Refer to the CMIS specification for the
     * CMIS query language syntax.
     * 
     * @param statement
     *            the query statement (CMIS query language)
     * @param searchAllVersions
     *            specifies whether non-latest document versions should be
     *            included or not, {@code true} searches all document versions,
     *            {@code false} only searches latest document versions
     * 
     * @cmis 1.0
     */
    ItemIterable<QueryResult> query(String statement, boolean searchAllVersions);

    /**
     * Sends a query to the repository using the given {@link OperationContext}.
     * (See CMIS spec "2.1.10 Query".)
     * 
     * @param statement
     *            the query statement (CMIS query language)
     * @param searchAllVersions
     *            specifies whether non-latest document versions should be
     *            included or not, {@code true} searches all document versions,
     *            {@code false} only searches latest document versions
     * @param context
     *            the operation context to use
     * 
     * @cmis 1.0
     */
    ItemIterable<QueryResult> query(String statement, boolean searchAllVersions, OperationContext context);

    /**
     * Builds a CMIS query and returns the query results as an iterator of
     * {@link CmisObject} objects.
     * 
     * @param type
     *            the ID of the object type
     * @param where
     *            the WHERE part of the query
     * @param searchAllVersions
     *            specifies whether non-latest document versions should be
     *            included or not, {@code true} searches all document versions,
     *            {@code false} only searches latest document versions
     * @param context
     *            the operation context to use
     * 
     * @cmis 1.0
     */
    ItemIterable<CmisObject> queryObjects(String typeId, String where, boolean searchAllVersions,
            OperationContext context);

    /**
     * Creates a query statement.
     * <p>
     * Sample code:
     * 
     * <pre>
     * QueryStatement stmt = session
     *         .createQueryStatement(&quot;SELECT ?, ? FROM ? WHERE ? &gt; TIMESTAMP ? AND IN_FOLDER(?) OR ? IN (?)&quot;);
     * </pre>
     * 
     * @param statement
     *            the query statement with placeholders ('?'), see
     *            {@link QueryStatement} for details
     * 
     * @return a new query statement object
     * 
     * @see QueryStatement
     * 
     * @cmis 1.0
     */
    QueryStatement createQueryStatement(String statement);

    /**
     * Creates a query statement for a query of one primary type joined by zero
     * or more secondary types.
     * <p>
     * Sample code:
     * 
     * <pre>
     * List&lt;String&gt; select = new ArrayList&lt;String&gt;();
     * select.add(&quot;cmis:name&quot;);
     * select.add(&quot;SecondaryStringProp&quot;);
     * 
     * Map&lt;String, String&gt; from = new HashMap&lt;String, String&gt;();
     * from.put(&quot;d&quot;, &quot;cmis:document&quot;);
     * from.put(&quot;s&quot;, &quot;MySecondaryType&quot;);
     * 
     * String where = &quot;d.cmis:name LIKE ?&quot;;
     * 
     * List&lt;String&gt; orderBy = new ArrayList&lt;String&gt;();
     * orderBy.add(&quot;cmis:name&quot;);
     * orderBy.add(&quot;SecondaryIntegerProp&quot;);
     * 
     * QueryStatement stmt = session.createQueryStatement(select, from, where, orderBy);
     * </pre>
     * 
     * Generates something like this:
     * 
     * <pre>
     * SELECT d.cmis:name,s.SecondaryStringProp FROM cmis:document AS d JOIN MySecondaryType AS s ON d.cmis:objectId=s.cmis:objectId WHERE d.cmis:name LIKE ? ORDER BY d.cmis:name,s.SecondaryIntegerProp
     * </pre>
     * 
     * @param selectPropertyIds
     *            the property IDs in the SELECT statement, if {@code null} all
     *            properties are selected
     * @param fromTypes
     *            a Map of type aliases (keys) and type IDs (values), the Map
     *            must contain exactly one primary type and zero or more
     *            secondary types
     * @param whereClause
     *            an optional WHERE clause with placeholders ('?'), see
     *            {@link QueryStatement} for details
     * @param orderByPropertyIds
     *            an optional list of properties IDs for the ORDER BY clause
     * 
     * @return a new query statement object
     * 
     * @see QueryStatement
     * 
     * @cmis 1.0
     */
    QueryStatement createQueryStatement(Collection<String> selectPropertyIds, Map<String, String> fromTypes,
            String whereClause, List<String> orderByPropertyIds);

    /**
     * Returns the content changes.
     * 
     * @param changeLogToken
     *            the change log token to start from or {@code null} to start
     *            from the first available event in the repository
     * @param includeProperties
     *            indicates whether changed properties should be included in the
     *            result or not
     * @param maxNumItems
     *            maximum numbers of events
     * 
     * @return the change events
     * 
     * @cmis 1.0
     */
    ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems);

    /**
     * Returns the content changes.
     * 
     * @param changeLogToken
     *            the change log token to start from or {@code null} to start
     *            from the first available event in the repository
     * @param includeProperties
     *            indicates whether changed properties should be included in the
     *            result or not
     * @param maxNumItems
     *            maximum numbers of events
     * @param context
     *            the OperationContext
     * 
     * @return the change events
     * 
     * @cmis 1.0
     */
    ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems,
            OperationContext context);

    /**
     * Returns an iterator of content changes, starting from the given change
     * log token to the latest entry in the change log.
     * <p>
     * Note: Paging and skipping are not supported.
     * 
     * @param changeLogToken
     *            the change log token to start from or {@code null} to start
     *            from the first available event in the repository
     * @param includeProperties
     *            indicates whether changed properties should be included in the
     *            result or not
     * 
     * @cmis 1.0
     */
    ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, boolean includeProperties);

    /**
     * Returns an iterator of content changes, starting from the given change
     * log token to the latest entry in the change log.
     * <p>
     * Note: Paging and skipping are not supported.
     * 
     * @param changeLogToken
     *            the change log token to start from or {@code null} to start
     *            from the first available event in the repository
     * @param includeProperties
     *            indicates whether changed properties should be included in the
     *            result or not
     * @param context
     *            the OperationContext
     * 
     * @cmis 1.0
     */
    ItemIterable<ChangeEvent> getContentChanges(final String changeLogToken, final boolean includeProperties,
            OperationContext context);

    /**
     * Returns the latest change log token.
     * <p>
     * In contrast to the repository info, this change log token is not cached.
     * This method requests the token from the repository every single time it
     * is called.
     * 
     * @return the latest change log token or {@code null} if the repository
     *         doesn't provide one
     * 
     * @cmis 1.0
     */
    String getLatestChangeLogToken();

    // create

    /**
     * Creates a new document.
     * 
     * The stream in {@code contentStream} is consumed but not closed by this
     * method.
     * 
     * @return the object ID of the new document
     * 
     * @see Folder#createDocument(Map, ContentStream, VersioningState, List,
     *      List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces);

    /**
     * Creates a new document.
     * 
     * The stream in {@code contentStream} is consumed but not closed by this
     * method.
     * 
     * @return the object ID of the new document
     * 
     * @see Folder#createDocument(Map, ContentStream, VersioningState, List,
     *      List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream,
            VersioningState versioningState);

    /**
     * Creates a new document from a source document.
     * 
     * @return the object ID of the new document
     * 
     * @see Folder#createDocumentFromSource(ObjectId, Map, VersioningState,
     *      List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces);

    /**
     * Creates a new document from a source document.
     * 
     * @return the object ID of the new document
     * 
     * @see Folder#createDocumentFromSource(ObjectId, Map, VersioningState,
     *      List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId,
            VersioningState versioningState);

    /**
     * Creates a new folder.
     * 
     * @return the object ID of the new folder
     * 
     * @see Folder#createFolder(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createFolder(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces,
            List<Ace> removeAces);

    /**
     * Creates a new folder.
     * 
     * @return the object ID of the new folder
     * 
     * @see Folder#createFolder(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createFolder(Map<String, ?> properties, ObjectId folderId);

    /**
     * Creates a new policy.
     * 
     * @return the object ID of the new policy
     * 
     * @see Folder#createPolicy(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces,
            List<Ace> removeAces);

    /**
     * Creates a new policy.
     * 
     * @return the object ID of the new policy
     * 
     * @see Folder#createPolicy(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.0
     */
    ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId);

    /**
     * Creates a new item.
     * 
     * @return the object ID of the new policy
     * 
     * @see Folder#createItem(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.1
     */
    ObjectId createItem(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces,
            List<Ace> removeAces);

    /**
     * Creates a new item.
     * 
     * @return the object ID of the new item
     * 
     * @see Folder#createItem(Map, List, List, List, OperationContext)
     * 
     * @cmis 1.1
     */
    ObjectId createItem(Map<String, ?> properties, ObjectId folderId);

    /**
     * Creates a new relationship.
     * 
     * @return the object ID of the new relationship
     * 
     * @cmis 1.0
     */
    ObjectId createRelationship(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
            List<Ace> removeAces);

    /**
     * Creates a new relationship.
     * 
     * @return the object ID of the new relationship
     * 
     * @cmis 1.0
     */
    ObjectId createRelationship(Map<String, ?> properties);

    /**
     * Fetches the relationships from or to an object from the repository.
     * 
     * @cmis 1.0
     */
    ItemIterable<Relationship> getRelationships(ObjectId objectId, boolean includeSubRelationshipTypes,
            RelationshipDirection relationshipDirection, ObjectType type, OperationContext context);

    /**
     * Updates multiple objects in one request.
     * 
     * @cmis 1.0
     */
    List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(List<CmisObject> objects, Map<String, ?> properties,
            List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds);

    /**
     * Deletes an object and, if it is a document, all versions in the version
     * series.
     * 
     * @param objectId
     *            the ID of the object
     * 
     * @cmis 1.0
     */
    void delete(ObjectId objectId);

    /**
     * Deletes an object.
     * 
     * @param objectId
     *            the ID of the object
     * @param allVersions
     *            if this object is a document this parameter defines if only
     *            this version or all versions should be deleted
     * 
     * @cmis 1.0
     */
    void delete(ObjectId objectId, boolean allVersions);

    /**
     * Retrieves the main content stream of a document.
     * 
     * @param docId
     *            the ID of the document
     * 
     * @return the content stream or {@code null} if the document has no content
     *         stream
     * 
     * @cmis 1.0
     */
    ContentStream getContentStream(ObjectId docId);

    /**
     * Retrieves the content stream of a document.
     * 
     * @param docId
     *            the ID of the document
     * @param streamId
     *            the stream ID
     * @param offset
     *            the offset of the stream or {@code null} to read the stream
     *            from the beginning
     * @param length
     *            the maximum length of the stream or {@code null} to read to
     *            the end of the stream
     * 
     * @return the content stream or {@code null} if the document has no content
     *         stream
     * 
     * @cmis 1.0
     */
    ContentStream getContentStream(ObjectId docId, String streamId, BigInteger offset, BigInteger length);

    /**
     * Fetches the ACL of an object from the repository.
     * 
     * @param objectId
     *            the ID the object
     * @param onlyBasicPermissions
     *            if {@code true} the repository should express the ACL only
     *            with the basic permissions defined in the CMIS specification;
     *            if {@code false} the repository can express the ACL with basic
     *            and repository specific permissions
     * 
     * @return the ACL of the object
     * 
     * @cmis 1.0
     */
    Acl getAcl(ObjectId objectId, boolean onlyBasicPermissions);

    /**
     * Applies ACL changes to an object and dependent objects.
     * 
     * Only direct ACEs can be added and removed.
     * 
     * @param objectId
     *            the ID the object
     * @param addAces
     *            list of ACEs to be added or {@code null} if no ACEs should be
     *            added
     * @param removeAces
     *            list of ACEs to be removed or {@code null} if no ACEs should
     *            be removed
     * @param aclPropagation
     *            value that defines the propagation of the ACE changes;
     *            {@code null} is equal to
     *            {@link AclPropagation#REPOSITORYDETERMINED}
     * 
     * @return the new ACL of the object
     * 
     * @cmis 1.0
     */
    Acl applyAcl(ObjectId objectId, List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation);

    /**
     * Removes the direct ACEs of an object and sets the provided ACEs.
     * 
     * The changes are local to the given object and are not propagated to
     * dependent objects.
     * 
     * @param objectId
     *            the ID the object
     * @param aces
     *            list of ACEs to be set
     * 
     * @return the new ACL of the object
     * 
     * @cmis 1.0
     */
    Acl setAcl(ObjectId objectId, List<Ace> aces);

    /**
     * Applies a set of policies to an object.
     * 
     * This operation is not atomic. If it fails some policies might already be
     * applied.
     * 
     * @param objectId
     *            the ID the object
     * @param policyIds
     *            the IDs of the policies to be applied
     * 
     * @cmis 1.0
     */
    void applyPolicy(ObjectId objectId, ObjectId... policyIds);

    /**
     * Removes a set of policies from an object.
     * 
     * This operation is not atomic. If it fails some policies might already be
     * removed.
     * 
     * @param objectId
     *            the ID the object
     * @param policyIds
     *            the IDs of the policies to be removed
     * 
     * @cmis 1.0
     */
    void removePolicy(ObjectId objectId, ObjectId... policyIds);
}
