h1. Integration with eXo WCM {anchor:id=Dev_CMIS.features.Integration_with_eXoWCM}

eXo Web Content Management (WCM) system provides CMIS access to its content storage features:
* WCM drives
* Document files and folders
* Symlinks
* Categories

To expose WCM drives as CMIS repositories there is a special extension of _CmisRegistry_.
Read the admin guide for the configuration of _org.exoplatform.ecms.xcmis.sp.jcr.exo.DriveCmisRegistry_ component.

Work with CMIS is based on reference documents returned by services. 
Each CMIS service returns response containing links to other services describing the Document or operations on it. 
In most cases, a Document will be asked by its ID. Some services accepts a Document path.

{note}
Notes for use cases:
To access the eXo CMIS services from the client side, use the [Curl tool|http://curl.haxx.se/download.html].
The CMIS AtomPub binding which is based upon the Atom (RFC4287) and Atom Publishing Protocol (RFC5023) will be used.

SOAP binding is not implemented in eXo Platform 3.x.
{note}

h2. JCR namespaces and nodetypes {anchor:id=Dev_CMIS.features.JCR_namespaces_nodetypes}

CMIS uses special JCR namespaces _cmis_ and _xcmis_ internally. 

To expose drives content following nodetypes supported: 
* nt:file nodetype for representation of cmis:documents 
* nt:folder for representation of cmis:folder

Since the CMIS specification does not allow having more root types except ones described above (cmis:documents and cmis:folder), those two (nt:file and nt:folder) are mapped to CMIS types.

There are two more nodetypes which are used: cmis:policy and cmis:relationship which represent CMIS types with corresponded (see Services description for details).

Additionally, nodetypes used in WCM are mapped as follow:
* nt:unstructured + extensions as cmis:folder
* exo:taxonomy + extensions as cmis:folder

In other words only nodetypes extending nt:file, nt:folder, nt:unstructured and exo:taxonomy will be exposed correctly via CMIS API.

{warning}
  WCM's nodetype exo:article is not supported by eXo CMIS due to uncompliant structure to nt:file.
{warning}

h2. WCM drives as CMIS Repositories {anchor:id=Dev_CMIS.features.WCM_drives_as_CMIS_repositories}

The WCM drive is used to expose as an isolated repository via the CMIS service. Operations on the repository will reflect the drive immediately.
{tip}
When working with CMIS repositories, it is important to understand that a repository reflects a WCM Drive, which is a sub-tree in JCR workspace. Two or more drives can be mapped to a same workspace or a sub-tree.
As a result, changes in one repository can affect others.
Refer to the WCM drives mappings to know actual location of a content you will access or change.
{tip}

h3. Use Case: Browse Drives via _getRepository_ {anchor:id=Dev_CMIS.features.Use_case_browse_drives_via_getRepositort}

* Login to the website as a user with the developer role.
* Open *Group | Sites Explorer*, you can see the drives set of WCM, such as *Sites Management*, *DMS Administration*.
* Get the list of these WCM drives via CMIS using _Curl_, asking _getRepositories_ service:
{code}
curl -o getrepos.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/ 
{code}

The requested file (_getrepos.xml_) contains the set of Repositories in the AtomPub format.
The root element represents the set of *workspaces* representing *WCM drives* related to resources, 
for example, for *DMS Administration*, the response will contain data like:
{code:xml}
   <service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
   <workspace>
      <atom:title type="text">DMS Administration</atom:title>
      <cmisra:repositoryInfo xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
         <cmis:repositoryId>DMS Administration</cmis:repositoryId>
         <cmis:repositoryName>DMS Administration</cmis:repositoryName>
      </cmisra:repositoryInfo>
      <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query">
         <atom:title type="text">Query</atom:title>
         <cmisra:collectionType>query</cmisra:collectionType>
      </collection>
      <collection
         href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/children/00exo0jcr0root0uuid0000000000000">
         <atom:title type="text">Folder Children</atom:title>
         <cmisra:collectionType>root</cmisra:collectionType>
      </collection>
      <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/checkedout">
         <atom:title type="text">Checkedout collection</atom:title>
         <cmisra:collectionType>checkedout</cmisra:collectionType>
      </collection>
      <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/unfiled">
         <atom:title type="text">Unfiled collection</atom:title>
         <cmisra:collectionType>unfiled</cmisra:collectionType>
      </collection>
      <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/types">
         <atom:title type="text">Types Children</atom:title>
         <cmisra:collectionType>types</cmisra:collectionType>
      </collection>
      <cmisra:uritemplate>
         <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/object/{id}?filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}
         </cmisra:template>
         <cmisra:type>objectbyid</cmisra:type>
         <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
      </cmisra:uritemplate>
      <cmisra:uritemplate>
         <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}
         </cmisra:template>
         <cmisra:type>objectbypath</cmisra:type>
         <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
      </cmisra:uritemplate>
      <cmisra:uritemplate>
         <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query?q={q}&amp;searchAllVersions={searchAllVersions}&amp;maxItems={maxItems}&amp;skipCount={skipCount}&amp;includeAllowableActions={includeAllowableActions}=&amp;includeRelationships={includeRelationships}
         </cmisra:template>
         <cmisra:type>query</cmisra:type>
         <cmisra:mediatype>application/atom+xml;type=feed</cmisra:mediatype>
      </cmisra:uritemplate>
      <cmisra:uritemplate>
         <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/typebyid/{id}
         </cmisra:template>
         <cmisra:type>typebyid</cmisra:type>
         <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
      </cmisra:uritemplate>
   </workspace>
 </service>
{code}

Here are the collection of services and predefined templates which can be used from the client side to request resources related to this repository.
For example, to get the WCM node of the *DMS Administration* drive by path, the *objectbypath* template can be used:
{code}
http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}
{code}
where parameters include:
* Required:
** ID repositoryId: The identifier for the repository.
** String path: The path to the object.
* Optional:
** String filter
** Boolean includeAllowableActions
** Enum includeRelationships
** String renditionFilter
** Boolean includePolicyIds
** Boolean includeACL

{note}
Find full description of all specified services in the [CMIS specification|#Dev_CMIS.Specification].
{note}

h2. WCM Symlinks {anchor:id=Dev_CMIS.features.WCM_symlinks}

Symlinks are used to organize the virtual access to documents in WCM, which is implemented like links in Unix/Linux/Mac OS (refer to ln command for more details).
{note}
JCR exo:symlink nodetype is used for such nodetypes.
{note}

h3. Use Case: Follow Symlinks {anchor:id=Dev_CMIS.features.Use_case_follow_symlinks}

*1*. Login to the ACME website as a user with the developer role.
*2*. Open *Group > Sites Explorer > Sites Management*, go to the folder _/acme/documents_.
*3*. Upload any file (for example _test.txt_) to _/acme/documents_.
*4*. Add this file to the *acme/News* category. It will create a symlink to _/acme/documents/test.txt_ in _/acme/categories/acme/News_.
*5*. Get content of folder _/acme/categories/acme/News_ via CMIS:

{code}
curl -o news.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objectbypath?path=/acme/categories/acme/News
{code}

The requested file (_products.xml_) contains the entry with information about the folder.
* The list of properties for the object (such as node Id or type).
* Allowable actions can be performed on the document; for example, requesting the children list.
* ACL and policies information.

{code:xml}
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
   <id>f59a3539c0a80003625790bdadf566c5</id>
   <published>2010-09-09T18:11:57.707Z</published>
   <updated>2010-09-09T18:11:57.707Z</updated>
   <summary type="text"></summary>
   <author>
      <name>system</name>
   </author>
   <title type="text">News</title>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service" type="application/atomsvc+xml"></link>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5"
      rel="self"></link>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5"
      rel="edit"></link>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/exo%3Ataxonomy" rel="describedby"
      type="application/atom+xml; type=entry"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f59a3539c0a80003625790bdadf566c5"
      rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f59a3539c0a80003625790bdadf566c5"
      rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f59a3539c0a80003625790bdadf566c5"
      rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"></link>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f59a3539c0a80003625790bdadf566c5"
      rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5"
      rel="down" type="application/atom+xml; type=feed"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/descendants/f59a3539c0a80003625790bdadf566c5"
      rel="down" type="application/cmistree+xml"></link>
   <link
      href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/foldertree/f59a3539c0a80003625790bdadf566c5"
      rel="http://docs.oasis-open.org/ns/cmis/link/200908/foldertree" type="application/atom+xml; type=feed"></link>
   <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3533c0a8000339af97059f243a25"
      rel="up" type="application/atom+xml; type=entry"></link>
   <content type="text">News</content>
   <cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
      <cmis:properties>
         <cmis:propertyId propertyDefinitionId="cmis:allowedChildObjectTypeIds" localName="cmis:allowedChildObjectTypeIds"
            displayName="cmis:allowedChildObjectTypeIds" queryName="cmis:allowedChildObjectTypeIds"></cmis:propertyId>
         <cmis:propertyString propertyDefinitionId="cmis:path" localName="cmis:path"
            displayName="cmis:path" queryName="cmis:path">
            <cmis:value>/acme/categories/acme/News</cmis:value>
         </cmis:propertyString>
         <cmis:propertyId propertyDefinitionId="cmis:objectTypeId" localName="cmis:objectTypeId"
            displayName="cmis:objectTypeId" queryName="cmis:objectTypeId">
            <cmis:value>exo:taxonomy</cmis:value>
         </cmis:propertyId>
         <cmis:propertyString propertyDefinitionId="cmis:lastModifiedBy" localName="cmis:lastModifiedBy"
            displayName="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"></cmis:propertyString>
         <cmis:propertyString propertyDefinitionId="cmis:name" localName="cmis:name"
            displayName="cmis:name" queryName="cmis:name">
            <cmis:value>News</cmis:value>
         </cmis:propertyString>
         <cmis:propertyString propertyDefinitionId="cmis:createdBy" localName="cmis:createdBy"
            displayName="cmis:createdBy" queryName="cmis:createdBy"></cmis:propertyString>
         <cmis:propertyId propertyDefinitionId="cmis:objectId" localName="cmis:objectId"
            displayName="cmis:objectId" queryName="cmis:objectId">
            <cmis:value>f59a3539c0a80003625790bdadf566c5</cmis:value>
         </cmis:propertyId>
         <cmis:propertyDateTime propertyDefinitionId="cmis:creationDate" localName="cmis:creationDate"
            displayName="cmis:creationDate" queryName="cmis:creationDate"></cmis:propertyDateTime>
         <cmis:propertyString propertyDefinitionId="cmis:changeToken" localName="cmis:changeToken"
            displayName="cmis:changeToken" queryName="cmis:changeToken"></cmis:propertyString>
         <cmis:propertyId propertyDefinitionId="cmis:baseTypeId" localName="cmis:baseTypeId"
            displayName="cmis:baseTypeId" queryName="cmis:baseTypeId">
            <cmis:value>cmis:folder</cmis:value>
         </cmis:propertyId>
         <cmis:propertyId propertyDefinitionId="cmis:parentId" localName="cmis:parentId"
            displayName="cmis:parentId" queryName="cmis:parentId">
            <cmis:value>f59a3533c0a8000339af97059f243a25</cmis:value>
         </cmis:propertyId>
         <cmis:propertyDateTime propertyDefinitionId="cmis:lastModificationDate"
            localName="cmis:lastModificationDate" displayName="cmis:lastModificationDate" queryName="cmis:lastModificationDate"></cmis:propertyDateTime>
      </cmis:properties>
      <cmis:acl></cmis:acl>
      <cmis:exactACL>false</cmis:exactACL>
      <cmis:policyIds></cmis:policyIds>
      <cmis:rendition></cmis:rendition>
   </cmisra:object>
</entry>
{code}
 
To get the file which has been uploaded above, use the *children* service to get the list of child nodes of _/acme/documents_. Find this service URL in the response XML above:
{code}
curl -o childs.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5
{code}

In the requested file (_childs.xml_), find the entry related to _test.txt_ file uploaded via the *Sites Explorer*. Search for the "test.txt" name by title..
{code:xml}
   <entry xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
      <id>f708e208c0a80003554babb97bd934ba</id>
      <published>2010-09-09T18:06:31.987Z</published>
      <updated>2010-09-09T18:06:31.987Z</updated>
      <summary type="text"></summary>
      <author>
         <name>system</name>
      </author>
      <title type="text">test.txt</title>
      <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service"
         type="application/atomsvc+xml"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba"
         rel="self"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba"
         rel="edit"></link>
      <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/cmis%3Adocument"
         rel="describedby" type="application/atom+xml; type=entry"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f708e208c0a80003554babb97bd934ba"
         rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f708e208c0a80003554babb97bd934ba"
         rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f708e208c0a80003554babb97bd934ba"
         rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f708e208c0a80003554babb97bd934ba"
         rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/versions/f708a0f1c0a8000333e3681f99fab760"
         rel="version-history" type="application/atom+xml; type=feed"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba?returnVersion=latest"
         rel="current-version" type="application/atom+xml; type=entry"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/parents/f708e208c0a80003554babb97bd934ba"
         rel="up" type="application/atom+xml; type=feed"></link>
      <link
         href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba"
         rel="edit-media"></link>
      <content type="text/plain"
         src="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba"></content>
      <cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
         <cmis:properties>
            <cmis:propertyBoolean propertyDefinitionId="cmis:isLatestMajorVersion"
               localName="cmis:isLatestMajorVersion" displayName="cmis:isLatestMajorVersion" queryName="cmis:isLatestMajorVersion">
               <cmis:value>false</cmis:value>
            </cmis:propertyBoolean>
            <cmis:propertyInteger propertyDefinitionId="cmis:contentStreamLength"
               localName="cmis:contentStreamLength" displayName="cmis:contentStreamLength" queryName="cmis:contentStreamLength">
               <cmis:value>38</cmis:value>
            </cmis:propertyInteger>
            <cmis:propertyId propertyDefinitionId="cmis:contentStreamId" localName="cmis:contentStreamId"
               displayName="cmis:contentStreamId" queryName="cmis:contentStreamId">
               <cmis:value>f708a0c2c0a800033bedeb35caddeed1</cmis:value>
            </cmis:propertyId>
            <cmis:propertyId propertyDefinitionId="cmis:objectTypeId" localName="cmis:objectTypeId"
               displayName="cmis:objectTypeId" queryName="cmis:objectTypeId">
               <cmis:value>cmis:document</cmis:value>
            </cmis:propertyId>
            <cmis:propertyString propertyDefinitionId="cmis:versionSeriesCheckedOutBy"
               localName="cmis:versionSeriesCheckedOutBy" displayName="cmis:versionSeriesCheckedOutBy"
               queryName="cmis:versionSeriesCheckedOutBy"></cmis:propertyString>
            <cmis:propertyId propertyDefinitionId="cmis:versionSeriesCheckedOutId" localName="cmis:versionSeriesCheckedOutId"
               displayName="cmis:versionSeriesCheckedOutId" queryName="cmis:versionSeriesCheckedOutId"></cmis:propertyId>
            <cmis:propertyString propertyDefinitionId="cmis:name" localName="cmis:name"
               displayName="cmis:name" queryName="cmis:name">
               <cmis:value>test.txt</cmis:value>
            </cmis:propertyString>
            <cmis:propertyString propertyDefinitionId="cmis:contentStreamMimeType"
               localName="cmis:contentStreamMimeType" displayName="cmis:contentStreamMimeType" queryName="cmis:contentStreamMimeType">
               <cmis:value>text/plain</cmis:value>
            </cmis:propertyString>
            <cmis:propertyId propertyDefinitionId="cmis:versionSeriesId" localName="cmis:versionSeriesId"
               displayName="cmis:versionSeriesId" queryName="cmis:versionSeriesId">
               <cmis:value>f708a0f1c0a8000333e3681f99fab760</cmis:value>
            </cmis:propertyId>
            <cmis:propertyDateTime propertyDefinitionId="cmis:creationDate" localName="cmis:creationDate"
               displayName="cmis:creationDate" queryName="cmis:creationDate">
               <cmis:value>2010-09-09T18:06:31.987Z</cmis:value>
            </cmis:propertyDateTime>
            <cmis:propertyString propertyDefinitionId="cmis:changeToken" localName="cmis:changeToken"
               displayName="cmis:changeToken" queryName="cmis:changeToken"></cmis:propertyString>
            <cmis:propertyBoolean propertyDefinitionId="cmis:isLatestVersion" localName="cmis:isLatestVersion"
               displayName="cmis:isLatestVersion" queryName="cmis:isLatestVersion">
               <cmis:value>true</cmis:value>
            </cmis:propertyBoolean>
            <cmis:propertyString propertyDefinitionId="cmis:versionLabel" localName="cmis:versionLabel"
               displayName="cmis:versionLabel" queryName="cmis:versionLabel">
               <cmis:value>latest</cmis:value>
            </cmis:propertyString>
            <cmis:propertyBoolean propertyDefinitionId="cmis:isVersionSeriesCheckedOut"
               localName="cmis:isVersionSeriesCheckedOut" displayName="cmis:isVersionSeriesCheckedOut"
               queryName="cmis:isVersionSeriesCheckedOut">
               <cmis:value>false</cmis:value>
            </cmis:propertyBoolean>
            <cmis:propertyString propertyDefinitionId="cmis:lastModifiedBy" localName="cmis:lastModifiedBy"
               displayName="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"></cmis:propertyString>
            <cmis:propertyString propertyDefinitionId="cmis:createdBy" localName="cmis:createdBy"
               displayName="cmis:createdBy" queryName="cmis:createdBy"></cmis:propertyString>
            <cmis:propertyString propertyDefinitionId="cmis:checkinComment" localName="cmis:checkinComment"
               displayName="cmis:checkinComment" queryName="cmis:checkinComment"></cmis:propertyString>
            <cmis:propertyId propertyDefinitionId="cmis:objectId" localName="cmis:objectId"
               displayName="cmis:objectId" queryName="cmis:objectId">
               <cmis:value>f708e208c0a80003554babb97bd934ba</cmis:value>
            </cmis:propertyId>
            <cmis:propertyBoolean propertyDefinitionId="cmis:isImmutable" localName="cmis:isImmutable"
               displayName="cmis:isImmutable" queryName="cmis:isImmutable">
               <cmis:value>false</cmis:value>
            </cmis:propertyBoolean>
            <cmis:propertyBoolean propertyDefinitionId="cmis:isMajorVersion" localName="cmis:isMajorVersion"
               displayName="cmis:isMajorVersion" queryName="cmis:isMajorVersion">
               <cmis:value>false</cmis:value>
            </cmis:propertyBoolean>
            <cmis:propertyId propertyDefinitionId="cmis:baseTypeId" localName="cmis:baseTypeId"
               displayName="cmis:baseTypeId" queryName="cmis:baseTypeId">
               <cmis:value>cmis:document</cmis:value>
            </cmis:propertyId>
            <cmis:propertyString propertyDefinitionId="cmis:contentStreamFileName"
               localName="cmis:contentStreamFileName" displayName="cmis:contentStreamFileName" queryName="cmis:contentStreamFileName">
               <cmis:value>test.txt</cmis:value>
            </cmis:propertyString>
            <cmis:propertyDateTime propertyDefinitionId="cmis:lastModificationDate"
               localName="cmis:lastModificationDate" displayName="cmis:lastModificationDate" queryName="cmis:lastModificationDate">
               <cmis:value>2010-09-09T18:06:31.987Z</cmis:value>
            </cmis:propertyDateTime>
         </cmis:properties>
         <cmis:acl></cmis:acl>
         <cmis:exactACL>false</cmis:exactACL>
         <cmis:policyIds></cmis:policyIds>
         <cmis:rendition></cmis:rendition>
      </cmisra:object>
   </entry>
{code}

Then, get the _test.txt_ file content via CMIS by using the *file* service and *id* of the file _test.txt_ from _childs.xml_:
{code}
curl -o test.txt -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba
{code}

Get results in the _test.txt_ file in the local folder.
In this way, you will get file stored in the *Sites Explorer* to folder _/acme/documents/test.txt_ via *eXo CMIS* by symlink path _/acme/categories/acme/News/test.txt_.
As file's actual content referenced by id in CMIS, the path has no matter for content read or change.


h2. Modify WCM via CMIS {anchor:id=Dev_CMIS.features.Modify_WCM_via_CMIS}

{note}
Upload the modified local file using the command with id of the file stored in WCM (it is jcr:uuid of the file in JCR Workspace). Note that you should run this command from the folder where the local file is stored.
{note}

To update any file via CMIS, use the *file* service and the PUT request. Use the same file as in the previous use case (_/acme/documents/test.txt_, id:f708e208c0a80003554babb97bd934ba).

{code}
curl -T test.txt -X PUT -H "Content-Type:text/plain; charset=UTF-8" -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba
{code}

Go to the *Sites Explorer* to see changes applied from the local file in _/acme/documents/test.txt_.

h2. CMIS search {anchor:id=Dev_CMIS.features.Search}
CMIS provides a type-based query service for discovering objects that match specified criteria by defining a read-only projection of the CMIS data model into a Relational View.

CMIS query languages are based on a subset of the SQL-92 grammar. CMIS-specific language extensions to SQL-92 are called out explicitly.
The basic structure of a CMIS query is a SQL statement that MUST include the following clauses:
* SELECT (virtual columns): This clause identifies the set of virtual columns that will be included in the query results for each row.
* FROM  (Virtual Table Names): This clause identifies which Virtual Table(s) the query will run against.

Additionally, a CMIS query MAY include the following clauses: 
* WHERE (conditions): This clause identifies the constraints that rows MUST satisfy to be considered a result for the query.
* ORDER BY (sort specification): This clause identifies the order in which the result rows MUST be sorted in the result row set.

Each CMIS ObjectType definition has the following query attributes:
|| Name || Description ||
|*query name (String)|Used for query operations on object types. In our SQL statement examples, all objecttypes is a queryName. For example, the given queryName matches the specific type of document. For example, in query like "SELECT * FROM cmis:document" ,"cmis:document" is queryName preconfigured in Document object type definition.|
|*queryable (Boolean)*|Indicate whether or not this object type is queryable. A non-queryable object type is not visible through the relational view that is used for query, and can not appear in the FROM clause of a query statement.|
|*fulltextIndexed (Boolean)*|Indicate whether objects of this type are full-text indexed for querying via the CONTAINS() query predicate.|
|*includedInSupertypeQuery (Boolean)*|Indicate whether this type and its subtypes appear in a query of this type's ancestor types. For example, if Invoice is a sub-type of Document, and its value is TRUE for a query on Document type, the matched instances of Invoice will be returned. If this attribute is FALSE, no instances (including matched ones) of Invoice will be returned.|

Property definition also contains queryName and queryable attributes with the same usage.

h3. Query examples {anchor:id=Dev_CMIS.features.Query_examples}
h4. Simple query {anchor:id=Dev_CMIS.features.Simple_query}

Query: Select all {{{cmis:document}}}.

{code}
SELECT * FROM cmis:document
{code}

Query result:
* All documents from the Apollo program.


h4. Find document by several constraints {anchor:id=Dev_CMIS.features.Find_document_by_several_constraints}

Query: Select all documents where apollo:propertyBooster is 'Saturn V' and apollo:propertyCommander is Frank F. Borman, II or James A. Lovell, Jr.

Initial data:
* document1: {{{apollo:propertyBooster}}} - Saturn 1B, {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyBooster}}} - Saturn V,  {{{apollo:propertyCommander}}} - Frank F. Borman, II
* document3: {{{apollo:propertyBooster}}} - Saturn V,  {{{apollo:propertyCommander}}} - James A. Lovell, Jr.

{code}
SELECT * FROM cmis:document WHERE apollo:propertyBooster = 'Saturn V' AND (apollo:propertyCommander = 'Frank F. Borman, II' OR  apollo:propertyCommander = 'James A. Lovell, Jr.')
{code}

Query result:
* document2 and document3.

h4. Full-text search {anchor:id=Dev_CMIS.features.Fulltext_search}

Query: Select all documents that contains the "here" word.

Initial data:
* document1: content - "There must be test word"
* document2: content - "Test word is not here"

{code}
SELECT * FROM cmis:document WHERE CONTAINS('here')
{code}

Query result:
* document2.

h4. Extended full-text search {anchor:id=Dev_CMIS.features.Extended_fulltext_search}

Query: Select all documents that contains "There must" phrase and do not contain the "check-word" term.

Initial data:
* document1: content - "There must be test word."
* document2: content - "Test word is not here. Another check-word."
* document3: content - "There must be check-word."

{code}
SELECT * FROM cmis:document WHERE CONTAINS(\"\\\"There must\\\" -\\\"check\\-word\\\"\")
{code}

Query result:
* document1.


h4. Date property comparison {anchor:id=Dev_CMIS.features.Data_property_comparison}

Query: Select all documents where cmis:lastModificationDate is more than 2007-01-01.

Initial data:
* document1: cmis:lastModificationDate - 2006-08-08
* document2: cmis:lastModificationDate - 2009-08-08

{code}
SELECT * FROM cmis:document WHERE (cmis:lastModificationDate >= TIMESTAMP '2007-01-01T00:00:00.000Z')"
{code}

Query result:
* document2.

h4. Boolean property comparison {anchor:id=Dev_CMIS.features.Boolean_property_comparison}

Query: Select all documents where property {{{apollo:someProperty}}} equals to false.

Initial data:
* document1: {{{apollo:someProperty}}} - true
* document2: {{{apollo:someProperty}}} - false

{code}
SELECT * FROM cmis:document WHERE (apollo:someProperty = FALSE)
{code}
  
Query result:
* document2.

h4. IN Constraint {anchor:id=Dev_CMIS.features.In_constraint}

Query: Select all documents where {{{apollo:propertyCommander}}} is in set {'Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.'}.

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. Borman, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. Cernan

{code}
SELECT * FROM cmis:document WHERE apollo:propertyCommander IN ('Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.')
{code}

Query result:
* document2, document3.

h4. Select all documents where longprop property is not in set {anchor:id=Dev_CMIS.features.Select_all_documents_where_longprop_NOTIN_set}

Query: Select all documents where {{{apollo:propertyCommander}}} property is not in set {'Walter M. Schirra', 'James A. Lovell, Jr.'}.

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. Borman, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. Cerna

{code}
SELECT * FROM cmis:document WHERE apollo:PropertyCommander NOT IN ('Walter M. Schirra', 'James A. Lovell, Jr.')
{code}

Query result:
* document2, document4.

h4. Select all documents where longprop property is not in set {anchor:id=Dev_CMIS.features.Select_all_documents_where_longprop_property_NOTNOTIN_set}

Query: Select all documents where _apollo:propertyCommander_ property is not in set {'James A. Lovell, Jr.'}.

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. Borman, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. Cerna

{code}
SELECT * FROM cmis:document WHERE  NOT (apollo:propertyCommander NOT IN ('James A. Lovell, Jr.'))
{code}

Query result:
* document3.

h4. {{{IN_FOLDER}}} constraint {anchor:id=Dev_CMIS.features.INFOLDER_constraint}

Query: Select all folders that are in folder1.

Initial data:
* folder1: id - 123456789
** document1:  Title - node1
* folder3:
** folder4: 
* folder2:
** document2: Title - node2

{code}
SELECT * FROM cmis:folder WHERE IN_FOLDER('123456789')
{code}

Query result:
* folder3.

h4. Select all documents that are in a specified folder {anchor:id=Dev_CMIS.features.Select_all_documents_in_specified_folder}

Query: Select all documents that are in folder1.

Initial data:
* folder1: id - 123456789
** document1: Title - node1
* folder2:
** document2: Title - node2

{code}
SELECT * FROM cmis:document WHERE IN_FOLDER('123456789')
{code}

Query result:
* document1.

h4. Select all documents where query supertype is cmis:article {anchor:id=Dev_CMIS.features.Select_all_documents_where_query_supertype_cmisArticle}

Initial data:
* testRoot:  id - 123456789
* document1: Title - node1 typeID - cmis:article-sports
* document2: Title - node2 typeID - cmis:article-animals

{code}
SELECT * FROM cmis:article WHERE IN_FOLDER('123456789')
{code}

Query result:
* document1, document2.

h4. {{{IN_TREE}}} constraint {anchor:id=Dev_CMIS.features.INTREE_constraint}

Query: Select all documents that are in the tree of folder1.

Initial data:
* folder1: id - 123456789
** document1
* folder2:
** document2

{code}
SELECT * FROM cmis:document WHERE IN_TREE('123456789')
{code}

Query result:
* document1, document2.

h4. LIKE Comparison {anchor:id=Dev_CMIS.features.LIKE_comparison}

Query: Select all documents where {{{apollo:propertyCommander}}} begins with "James".

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. James, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. James


{code}
SELECT * FROM cmis:document AS doc WHERE apollo:PropertyCommander LIKE 'James%'
{code}

Query result:
* document3.

h4. Test LIKE constraint with escape symbols {anchor:id=Dev_CMIS.features.Test_LIKE_constraint_with_escape_symbols}

Query : Select all documents where apollo:someProperty like 'ad\%min%'.

Initial data:
* document1: Title - node1, apollo:someProperty - ad%min master
* document2: Title - node2, apollo:someProperty - admin operator
* document3: Title - node2, apollo:someProperty - radmin

{code}
SELECT * FROM cmis:document AS doc WHERE apollo:someProperty  LIKE 'ad\\%min%'
{code}

Query result:
* document1.

h4. NOT constraint {anchor:id=Dev_CMIS.features.NOT_constraint}

Query: Select all documents that do not contain the "world" word.

Initial data:
* document1: Title - node1, content - hello world
* document2: Title - node2, content - hello

{code}
SELECT * FROM cmis:document WHERE NOT CONTAINS('world')
{code}

Query result:
* document2.

h4. Property existence {anchor:id=Dev_CMIS.features.Property_existence}

Query: Select all documents that has apollo:propertyCommander property is NOT NULL.

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - 
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - 

{code}
SELECT * FROM cmis:document WHERE apollo:propertyCommander IS NOT NULL
{code}

Query result:
* document1, document3.

h4. ORDER BY {anchor:id=Dev_CMIS.features.ORDERBY}

Query: Select all documents in default order (by document name).

Initial data:
* document1: Title - Apollo 7
* document2: Title - Apollo 8
* document3: Title - Apollo 13
* document4: Title - Apollo 17

{code}
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document
{code}

Query result:
* document3, document4, document1, document2.

h4. ORDER BY ASC {anchor:id=Dev_CMIS.features.ORDER_BY_ASC}

Query: Order by {{{apollo:propertyCommander}}} property value (in ascending order).

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. Borman, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. Cerna

{code}
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY apollo:propertyCommander
{code}

Query result:
* document4, document2, document3, document1.


h4. ORDER BY DESC {anchor:id=Dev_CMIS.features.ORDER_BY_DESC}

Query: Order by {{{apollo:propertyCommander}}} property value (in descending order).

Initial data:
* document1: {{{apollo:propertyCommander}}} - Walter M. Schirra
* document2: {{{apollo:propertyCommander}}} - Frank F. James, II
* document3: {{{apollo:propertyCommander}}} - James A. Lovell, Jr.
* document4: {{{apollo:propertyCommander}}} - Eugene A. James

{code}
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY cmis:propertyCommander DESC
{code}

Query result:
* document1, document3, document2, document4.

h4. ORDER BY SCORE (as columns) {anchor:id=Dev_CMIS.features.ORDER_BY_SCORE}

Query: Select all documents which contains word "moon" ordered by score.

Initial data:
* document1: content - "Earth-orbital mission, the first manned launch"
* document2: content - "from another celestial body - Earth's Moon"
* document3: content - "NASA intended to land on the Moon, but a mid-mission technical"
* document4: content - "It was the first night launch of a U.S. human"

{code}
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document WHERE CONTAINS('moon') ORDER BY SCORE()
{code}

Query result:
* document2, document3.


h4. Not equal comparison (decimal) {anchor:id=Dev_CMIS.features.Not_equal_comparison_decimal}

Query: Select all documents which have {{{apollo:propertyBooster}}} peroperty that does not equal to 3.

Initial data:
* document1: Title - node1, {{{apollo:propertyBooster}}} - 3
* document2: Title - node2, {{{apollo:propertyBooster}}} - 15

{code}
SELECT * FROM cmis:document WHERE apollo:propertyBooster <> 3
{code}

Query result:
* document2.

h4. Not equal comparison (string) {anchor:id=Dev_CMIS.features.Not_equal_comparison_string}

Query: Select all documents property apollo:someProperty that does not equals to "test word second".

Initial data:
* document1: apollo:someProperty - "test word first"
* document2: apollo:someProperty - "test word second"

{code}
SELECT * FROM cmis:document WHERE apollo:someProperty <> 'test word second'
{code}

Query result:
* document1.

h4. More than comparison (>) {anchor:id=Dev_CMIS.features.More_than_comparison}

Query: Select all documents wihch have {{{apollo:propertyBooster}}} property which is more than 5.

Initial data:
* document1: {{{apollo:propertyBooster}}} - 3
* document2: {{{apollo:propertyBooster}}} - 15

{code}
SELECT * FROM cmis:document WHERE apollo:propertyBooster > 5
{code}

Query result:
* document2.


