1
Binding
2
1.1 Overview
3
4
5
6
The CMIS Browser Binding is designed to allow developers build browser based applications that use
CMIS content. It is based on technologies that developers who build such applications already
understand, including HTML, HTML Forms, JavaScript and JSON. Importantly, it does not require a
JavaScript library, but rather takes advantage of capabilities already built into modern browsers.
7
8
9
While this binding is optimized for use in browser applications; it can also be useful as a simpler HTTP
based binding in other application models.
10
11
1.2 Common Service Elements
12
1.2.1 Protocol
13
14
15
16
HTTP SHALL be used as the protocol for service requests. HTTP GET SHALL be used for reading
content and HTTP POST SHALL be used for creating, updating and deleting content. Using just those
two HTTP verbs makes it possible to develop applications that rely on built-in browser capabilities (e.g.
HTML Forms) and typical server configurations.
17
1.2.2 Data Representation
18
19
20
21
Browser applications are typically written in JavaScript. A popular lightweight data representation format
amongst JavaScript developers is JavaScript Object Notation (JSON) as described in RFC 4627 (see
http://www.ietf.org/rfc/rfc4627.txt). JSON SHALL be used to represent the various CMIS objects
described by the data model.
22
1.2.2.1 Schema
23
24
25
It is useful to formally define CMIS elements as they appear in JSON using a schema language. This
makes the definition more precise and concise, and also allows implementations to validate CMIS JSON
instances at run-time.
26
27
28
29
30
31
Since there is not yet a JSON schema language approved by a standards body, this specification uses a
schema language called Orderly that is introduced by Lloyd Hilaiel on http://orderly-json.org/. Since the
definition of Orderly on http://orderly-json.org/ may proceed independently of this specification, and
because we may need to extend Orderly to define some elements of CMIS, we provide a description of
Orderly in Appendix B of this document.
32
1.2.2.2 Mapping Schema Elements to JSON
33
34
35
JSON only defines a few types, including Object, String, Number, Boolean, Null and Arrays. Since not all
the types used in the CMIS schema have direct JSON equivalents, some explanation of mapping is
necessary.
36
CMIS
JSON
String
string
boolean
boolean
Decimal
number
Integer
number
Datetime
number (milliseconds since 1970/01/01, UTC)
Uri
string
Id
string
Html
string
37
1.2.3 URL Patterns
38
39
40
The URL’s used by the Browser Binding are meant to be predictable in order to simplify client
development. The URL patterns allow objects to be referenced both by object ID and by path. Section
1.3 provides the details of how clients can construct these URL’s.
41
1.2.4 Multipart Forms
42
43
44
45
Browser applications also typically use HTTP multipart forms as described in RFC 2388 (see
http://tools.ietf.org/html/rfc2388) to create and update content. This is especially useful for updating file
content with the addition of the FILE attribute in RFC 1867 (see http://tools.ietf.org/html/rfc1867). In this
binding, HTTP POST of multipart/form-data SHALL be used to update content streams.
46
1.2.5 Properties in a “value not set” state
47
The JSON value “null” SHALL be used by the server when returning values that have not been set.
48
1.2.6 Client Token
49
50
51
52
53
The JSONP (JSON with Padding) pattern allows a client to fetch JSON content from a server, wrapped in
a client provided token. For example, this pattern allows JSON content fetched by using the src attribute
in JavaScript to be passed directly to a JavaScript function in an HTML page. This allows the handling of
content from multiple servers which otherwise would be rejected by the browser following the “same origin
policy”.
54
55
This binding introduces a parameter called clientToken to allow CMIS clients to use this pattern.
56
57
58
59
60
61
62
63
64
65
The clientToken MAY be included by clients on read operations defined by this protocol that answer a
JSON object. The server SHALL respond to valid read requests containing this token by answering the
token, followed by an open parenthesis, followed by the JSON object returned, followed by a close
parenthesis. If the parameter is included in a request, the server SHALL validate that its value is not
empty but the server SHALL NOT do any additional validation of the token, such as, for example,
assuring it conforms to JavaScript function naming conventions. If the parameter value is empty, or if the
parameter is used on a service for which it is not allowed, then the invalidArgument exception SHALL be
used to signal the error.
66
67
68
69
70
71
72
1.2.7 Authentication
Authentication SHOULD be handled by the transport protocol. Please see AtomPub (RFC5023) section
14.
1.2.8 Error Handling and Return Codes
HTTP Return Codes SHALL be used to indicate success or failure of an operation. Please see the HTTP
specification for more information on the HTTP status codes. These are provided as guidance from the
HTTP specification. If any conflict arises, the HTTP specification is authoritative.
73
74
CMIS Services Exception
HTTP Status Code
75
invalidArgument
400
76
objectNotFound
404
77
permissionDenied
403
78
notSupported
405
79
runtime
500
80
constraint
409
81
filterNotValid
400
82
streamNotSupported
403
83
storage
500
84
contentAlreadyExists
409
85
versioning
409
86
updateConflict
409
87
nameConstraintViolation
409
88
89
90
91
This binding also introduces an object to return additional information about the response. CMIS
repositories SHOULD include this object in responses. When present, the object SHALL include the
following JSON properties.
92
93
94
95
96
string exception
A string containing one of the CMIS services exceptions describe in section 1.2.8
string message
A string containing a message that provides more information about what caused the exception.
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
Example:
GET /cmis/repository/123/myFolder?foo=bar&maxItems=20 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
HTTP/1.1 400 OK
Content-Type: application/json
Content-Length: xxxx
{
"exception": "invalidArgument",
"message": "The parameter ‘foo’ is not valid."
}
114
115
1.3 Services
116
1.3.1 Service URL
117
118
The document returned by the Service URL provides the repository information for all available
repositories. How the client will get the Service URL is repository specific.
119
120
In this document the abbreviation used for the Service URL is <service>.
121
122
123
124
In addition to the repository information described by the CMIS 1.0 specification, the document answered
by the Service URL MUST contain two additional properties:
125
The Repository URL (repository info property: repositoryUrl)
126
The Root URL (repository info property: rootUrl)
127
1.3.1 Repository URL
128
129
130
The Repository URL provides access to data that is independent of the folder hierarchy such as type
definitions, query and content changes. It can be obtained using the getRepositories or getRepository
services.
131
In this document the abbreviation used for the Repository URL is <repository>.
132
1.3.2 Root URL
133
The Root URL is used to build Object URL’s.
134
In this document the abbreviation used for the Root URL is <root>.
135
136
137
1.3.3 Object URL’s
An object is either identified by a parameter “objectId” added to the Root URL or by a path that is
appended to the Root URL. If the parameter “objectId” is set, it takes precedence over the path.
138
139
The two forms of an Object URL are:
140
141
<root>?objectId=<objectId>
where <objectId> is a CMIS object id.
142
143
<root>/<path>
where <path> is an absolute CMIS path to an object.
144
145
In this document the abbreviation used for the Root URL is <object>.
146
147
Examples:
148
149
150
151
If the Root URL is “http://myrepository/cmis/repository/123” and the object id is “1a2b-3c4d-5e6f”
the Object URL is:
http://myrepository/cmis/repository/123?objectId=1a2b-3c4d-5e6f
152
153
154
If the Root URL is “http://myrepository/cmis/repository/123” and the object path is
“/myFolder/myDocument” the Object URL is:
http://myrepository/cmis/repository/123/myFolder/myDocument
155
156
1.4 CMIS Operations
157
158
1.4.1 Read Operations
159
160
Read operations use HTTP GET. The particular data that is returned by a read operation is determined
by the query parameter “cmisselector”.
161
If the "cmisselector" parameter is absent, the following default values are used:
162
For document objects: content
163
For folder objects: children
164
For relationship objects: object
165
For policies objects: object
166
167
The value of the "cmisselector" parameter is case insensitive.
168
1.4.1.1 Read Operations Summary Table
169
The following table defines the GET request responses.
170
171
172
173
The arguments supplied to the GET service requests SHALL be encoded as URL parameters. The
name of each such parameter SHALL be the name of the argument as defined in the schema element
enumArguments in the CMIS REST Atom schema (e.g. skipCount, includeRelationships, etc).
174
175
In all cases, the HTTP status code of 200 indicates a successful operation.
176
Service
CMIS Operation
Response Body
Description
Response Schema Element
Repository
Services
getRepositories
JSON representation
of the list of
repositories
http://docs.oasisopen.org/ns/cmis/browser/201103
/repositories
getRepository
JSON representation
of the specified
repository
http://docs.oasisopen.org/ns/cmis/browser/201103
/repositoryInfo
getTypeChildren
JSON representation
of the types that are
immediate children of
the specified typeId,
or the base types if no
typeId is provided
http://docs.oasisopen.org/ns/cmis/browser/201103
/typeList
getTypeDescendants
JSON representation
of all types
descended from the
specified typeId, or all
the types in the
repository if no typeId
is provided
http://docs.oasisopen.org/ns/cmis/browser/201103
/typeContainer
getTypeDefinition
JSON representation
of the specified type
http://docs.oasisopen.org/ns/cmis/browser/201103
/typeDefinitionType
Navigation
Services
Object Services
getChildren
JSON representation
of the children of the
specified folder
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
getDescendants
JSON representation
of the descendants of
the specified folder
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectContainer
getFolderTree
JSON representation
of the folders
descended from the
specified folder
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectContainer
getFolderParent
JSON representation
of the parent folder of
the specified folder
http://docs.oasisopen.org/ns/cmis/browser/201103
/object
getObjectParents
JSON representation
of the folders that are
the parents of the
specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectParentList
getCheckedOutDocs
JSON representation
of the documents that
have been checked
out in the repository
or in the specified
folder
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
getAllowableActions
JSON representation
of the actions allowed
on the specified
object
http://docs.oasisopen.org/ns/cmis/browser/201103
/allowableActions
getObject
JSON representation
of the specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/object
getProperties
JSON representation
of the properties of
the specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/properties
getObjectByPath
JSON representation
of the specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/object
getContentStream
Stream of the
document
N/A
getRenditions
JSON representation
of the renditions for
the specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/object
Discovery
Services
query
A JSON
representation of the
results of the query
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
getContentChanges
A JSON
representation of the
changed objects
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
getObjectOfLatestVersion
JSON representation
of the latest version of
the document in the
Version Series
http://docs.oasisopen.org/ns/cmis/browser/201103
/object
getPropertiesOfLatestVersion
JSON representation
of the properties of
the latest version of
the document in the
Version Series
http://docs.oasisopen.org/ns/cmis/browser/201103
/properties
getAllVersions
JSON representation
of all the versions in
the Version Series
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
Relationship
Services
getObjectRelationships
JSON representation
of the relationships of
the specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
Policy Services
getAppliedPolicies
A JSON object
representing the
policies applied to the
specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/objectInFolderList
ACL Service
getACL
JSON representation
of the Access Control
Entries for the
specified object
http://docs.oasisopen.org/ns/cmis/browser/201103
/acl
Versioning
Services
177
178
179
180
1.4.2 Write Operations
181
182
183
184
All operations that create, modify or delete objects or change the state of the repository in any way use
HTTP POST. Since this binding is optimized for use in browser applications, the format of the
transferred data is aligned to the capabilities of HTML forms and described in this specification in HTML
terms. See section 1.4.4 for a description of how HTML forms are used for CMIS operations
185
1.4.2.1 Write Operations Summary Table
186
The following table defines the POST request responses:
187
Service
Object
Service
CMIS Operation
Success
HTTP
status
code
Response
body
HTTP
Location
Header
Last
response
available
Comment
(see
section
1.4.4.4)
createDocument
201
JSON
representation
of the newly
created
document
yes
yes
createDocumentFromSource
201
JSON
representation
of the newly
created
document
yes
yes
createFolder
201
JSON
representation
of the newly
created folder
yes
yes
createRelationship
201
JSON
representation
of the newly
created
relationship
yes
yes
createPolicy
201
JSON
representation
of the newly
created policy
yes
yes
updateProperties
200
JSON
representation
of the
updated
object
no
yes
moveObject
201
JSON
representation
of the moved
object
yes
yes
deleteObject
204
Empty
no
yes
deleteTree
204
Empty
no
yes
If a ‘file’ control is
included in the form, the
content stream of the
object MAY be updated
with the content of the file
in the same operation.
When the operation
partially succeeds,
meaning that a 204 is
returned but some
objects in the tree are not
deleted, an instance of
type http://docs.oasisopen.org/ns/cmis/browse
r/201103/ids containing a
list of id’s of the objects
not deleted SHALL be
returned.
setContentStream
201
JSON
representation
of the object
yes
yes
deleteContentStream
204
Empty
no
yes
addObjectToFolder
201
JSON
representation
of the added
object
yes
yes
removeObjectFromFolder
201
JSON
representation
of the
removed
object
yes
yes
Discovery
Service
query
200
Query results
no
no
Versioning
Service
checkOut
201
JSON
representation
of the PWC
yes
yes
cancelCheckOut
204
Empty
no
yes
checkIn
201
JSON
representation
of the
checked-in
object
yes
yes
applyPolicy
200
JSON
representation
of the
updated
object
no
yes
removePolicy
200
JSON
representation
of the
updated
object
no
yes
applyACL
200
JSON
representation
of the new
ACL
no
yes
Multi-filing
Service
Policy
Service
ACL
Service
188
189
190
1.4.3 Operations Summary Table
191
The following table assigns “selector” and “action” values to CMIS operations:
192
Service
CMIS Operation
HTTP
Method
Repository
Service
getRepositories
GET
<service>
getRepositoryInfo
GET
<repository>
repositoryInfo
getTypeChildren
GET
<repository>
typeChildren
getTypeDescendants
GET
<repository>
typeDescendants
getTypeDefinition
GET
<repository>
typeDefinition
getChildren
GET
<object>
children
getDescendants
GET
<object>
descendants
getFolderTree
GET
<object>
folder
getFolderParent
GET
<object>
parent
getObjectParents
GET
<object>
parents
getCheckedOutDocs
GET
<object>
checkedout
Returns
Checked out
documents in
this folder
getCheckedOutDocs
GET
<repository>
checkedout
Returns
Checked out
documents in
the
repository
Navigation
Service
Object
Service
URL
Selector
Action
Comment
No selector
The selector
can be
omitted since
getChildren
only works
on folders
createDocument
POST
<object>
createDocument
Creates a
document in
this folder
createDocument
POST
<repository>
createDocument
Creates an
unfiled
document
createDocumentFromSource
POST
<object>
createDocumentFromSource
Creates a
document in
this folder
createDocumentFromSource
POST
<repository>
createDocumentFromSource
Creates an
unfiled
document
createFolder
POST
<object>
createFolder
createRelationship
POST
<repository>
createRelationship
createPolicy
POST
<object>
createPolicy
Creates a
policy in this
folder
createPolicy
POST
<repository>
createPolicy
Creates an
unfiled policy
getAllowableActions
GET
<object>
allowableActions
getObject
GET
<object>
object
If the object
is a policy or
a
relationship,
the selector
can be
omitted.
getContentStream
GET
<object>
content
If the object
is a
document,
the selector
can also be
omitted.
getRenditions
GET
<object>
renditions
getProperties
getObjectByPath
Multi-filing
Service
Discovery
Service
Versioning
Service
updateProperties
POST
updateProperties
moveObject
POST
<object>
move
deleteObject
POST
<object>
delete
deleteTree
POST
<object>
deleteTree
setContentStream
POST
<object>
setContent
deleteContentStream
POST
<object>
deleteContent
addObjectToFolder
POST
<object>
addObjectToFolder
removeObjectFromFolder
POST
<object>
removeObjectFromFolder
query
POST
<repository>
query
query
GET
<repository>
query
getContentChanges
GET
<repository>
contentChanges
checkOut
POST
<object>
checkOut
cancelCheckOut
POST
<object>
cancelCheckOut
checkIn
POST
<object>
checkIn
GET
<object>
object
getAllVersions
GET
<object>
versions
Relationship
Service
getObjectRelationships
GET
<object>
relationships
Policy
Service
applyPolicy
POST
<object>
applyPolicy
removePolicy
POST
<object>
removePolicy
GET
<object>
getObjectOfLatestVersion
Parameter
returnVersion
must be set
getPropertiesOfLatestVersion
ACL
getACL
acl
Service
applyACL
POST
<object>
applyACL
193
1.4.4 Use of HTML Forms
194
As described in section 1.4.2 HTML forms are used to create, update and delete CMIS content.
195
196
197
198
199
The form submission method (HTML form attribute “method”) MUST be “POST”. The encoding type
(HTML form attribute “enctype”) MUST be either "application/x-www-form-urlencoded" or "multipart/formdata" if no content stream is attached to the form. The encoding type MUST be “multipart/form-data” if a
content stream is attached to the form data.
200
201
202
203
204
The names of the controls within the form are defined by the patterns in the following sections. All control
names are case-insensitive as defined by the HTML specification. Control names MUST be unique within
a form. If the control value of an optional parameter is set to an empty string (“”) the default value MUST
be used.
205
206
207
A client MAY add controls to a form that are not defined by CMIS as long as the control names don’t
conflict with the patterns described in this specification.
208
209
Since control values are strings, all other data types have to be serialized to strings.
210
The same rules that apply to the serialization to JSON apply here.
211
212
1.4.4.1 Action
213
214
215
An HTML form used to POST CMIS content MUST include a control named “cmisaction” that indicates
the CMIS operation to be performed. See section 1.4.3 for valid control values. The value of the control is
case insensitive.
216
217
218
219
220
221
Example:
<input name="cmisaction" type="hidden" value="createDocument" />
222
1.4.4.2 Structured and Array Parameters
223
224
Some CMIS operations require structured parameters and arrays of values. Since HTML forms don’t
support that usage, some CMIS operation parameters are split into multiple controls in a form.
225
226
227
For example, a CMIS property is split into a control that holds the property id and another control that hold
property value. The association between the two controls is done by convention.
228
229
The entirety of all properties is made up of an array of these property controls.
230
231
232
Names of controls that are part of an array end with “[<index>]” where <index> is a positive integer.
Arrays MUST always start with the index 0 and MUST be gapless.
233
234
235
Example:
236
237
238
239
240
241
242
243
244
245
246
247
248
An array of three properties looks like this in a HTML form:
<input name="propertyId[0]"
type="hidden" value="cmis:name" />
<input name="propertyValue[0]" type="text"
value="my document" />
<input name="propertyId[1]"
type="hidden" value="cmis:objectTypeId" />
<input name="propertyValue[1]" type="hidden" value="my:firstObjectType" />
<input name="propertyId[2]"
type="hidden" value="my:intProperty" />
<input name="propertyValue[2]" type="text"
value="42" />
249
250
251
252
If a client sends invalid, incomplete or inconsistent data the repository SHOULD return an
invalidArgument error.
253
254
1.4.4.3 CMIS Controls
255
This section lists all HTML form controls used by CMIS operations.
256
1.4.4.3.1 ID’s
257
1.4.4.3.1.1 Object id:
258
Control name: “objectId”
259
Control value:
Object id
260
261
262
263
264
Example:
<input name="objectId" type="hidden" value="1234-abcd-5678" />
265
266
1.4.4.3.1.2 Folder id:
267
Control name: “folderId”
268
Control value:
Folder id
269
270
271
272
273
Example:
<input name="folderId" type="hidden" value="1234-abcd-5678" />
274
275
1.4.4.3.1.3 Source folder id:
276
Control name: “sourceFolderId”
277
Control value:
278
279
280
281
Example:
Folder id
282
283
<input name="sourceFolderId" type="hidden" value="1234-abcd-5678" />
284
285
286
1.4.4.3.1.4 Target folder id:
287
Control name: “targetFolderId”
288
Control value:
Folder id
289
290
291
292
293
294
Example:
<input name="targetFolderId" type="hidden" value="1234-abcd-5678" />
295
296
297
1.4.4.3.2 Single-value Properties
298
299
A single-value property is made up of a pair of a “propertyId” control and a “propertyValue” control with
the same <propIndex>. To unset the property, the “propertyValue” control MUST NOT be present.
300
<propIndex> does not imply any order.
301
1.4.4.3.2.1 Property Id:
302
Control name: “propertyId[<propIndex>]”
303
Control value:
304
1.4.4.3.2.2 Property value:
305
Control name: “propertyValue[<propIndex>]”
306
Control value:
Property id
Property value
307
308
309
310
311
312
313
314
315
Example:
316
1.4.4.3.3 Multi-value Properties
317
318
A multi-value property is made up a “propertyId” control and a series of “propertyValue” controls with the
same <propIndex>. To unset the property, no “propertyValue” control MUST be present.
319
<propIndex> does not imply any order, but <seqIndex> defines the order of the values.
320
1.4.4.3.3.1 Property Id:
321
Control name: “propertyId[<propIndex>]”
322
Control value:
323
1.4.4.3.3.2 Property values:
324
Control name: “propertyValue[<propIndex>][<seqIndex>]”
<input name="propertyId[0]"
type="hidden" value="my:firstname" />
<input name="propertyValue[0]" type="text"
value="John" />
<input name="propertyId[1]"
type="hidden" value="my:lastname" />
<input name="propertyValue[1]" type="text"
value="Smith" />
Property id
325
Control value:
Property value at position <seqIndex>
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
Example:
341
1.4.4.3.4 Access Control
342
1.4.4.3.4.1 Adding Access Control Entries (ACEs)
343
344
345
To add an ACE to a CMIS object, a control named “addACEPrincipal” control is used with an
<addACEIndex>, with zero or more “addACEPermission” controls, each with the same
<removeACEIndex> and another subindex, <permIndex>.
<input
<input
<input
<input
<input
<input
name="propertyId[0]"
name="propertyValue[0][0]"
name="propertyValue[0][1]"
name="propertyValue[0][2]"
name="propertyValue[0][3]"
name="propertyValue[0][4]"
type="hidden"
type="text"
type="text"
type="text"
type="text"
type="text"
value="my:countries" />
value="Germany" />
value="United States" />
value="France" />
value="United Kingdom" />
value="Switzerland" />
<input
<input
<input
<input
name="propertyId[1]"
name="propertyValue[1][0]"
name="propertyValue[1][1]"
name="propertyValue[1][2]"
type="hidden"
type="text"
type="text"
type="text"
value="my:colors" />
value="red" />
value="green" />
value="blue" />
346
347
<addACEIndex> and <permIndex> don’t imply any order.
348
1.4.4.3.4.1.1 Principal:
349
Control name: “addACEPrincipal[<addACEIndex>]”
350
Control value:
351
1.4.4.3.4.1.2 Permission:
352
Control name: “addACEPermission[<addACEIndex>][<permIndex>]”
353
Control value:
Principal id
Permission id
354
355
356
357
358
359
360
361
362
363
364
365
Example:
<input
<input
<input
<input
name="propertyValue"
name="addACEPrincipal[0]"
type="hidden" value="john" />
name="addACEPermission[0][0]" type="hidden" value="cmis:read" />
name="addACEPermission[0][1]" type="hidden" value="perm:publish" />
<input name="addACEPrincipal[1]"
type="hidden" value="mary" />
<input name="addACEPermission[1][0]" type="hidden" value="cmis:all" />
366
367
1.4.4.3.4.2 Removing Access Control Entries (ACEs)
368
369
370
To remove an ACE from a CMIS object, a control named “removeACEPrincipal” is used with an
<addACEIndex>, and zero or more “removeACEPermission” controls, each with the same
<removeACEIndex> and another subindex, <permIndex>.
371
372
<removeACEIndex> and <permIndex> don’t imply any order.
373
1.4.4.3.4.2.1 Principal
374
Control name: “removeACEPrincipal[<removeACEIndex>]”
375
Control value:
376
1.4.4.3.4.2.2 Permission
377
Control name: “removeACEPermission[<removeACEIndex>][<permIndex>]”
378
Control value:
Principal id
Permission id
379
380
381
382
383
384
385
386
387
388
389
Example:
<input name="removeACEPrincipal[0]"
type="hidden" value="tom" />
<input name="removeACEPermission[0][0]" type="hidden" value="cmis:write" />
<input name="removeACEPermission[0][1]" type="hidden" value="perm:publish" />
<input name="removeACEPrincipal[1]"
type="hidden" value="bob" />
<input name="removeACEPermission[1][0]" type="hidden" value="perm:forward" />
390
391
1.4.4.3.4.3 ACL propagation
392
To specify how to propagate ACE’s, a control named “ACLPropagation” is used.
393
394
Control name: “ACLPropagation”
395
Control value:
ACL propagation enum ("objectonly", "propagate", "repositorydetermined")
396
397
398
399
400
Example:
<input name="ACLPropagation" type="hidden" value="propagate" />
401
402
1.4.4.3.5 Policies
403
404
Policies are assigned to CMIS objects by including a control named “policy” with an index of
<policyindex>. A policy list is made up of a series of these “policy” controls.
405
<policyIndex> does not imply any order.
406
1.4.4.3.5.1 Policy:
407
Control name: “policy[<policyIndex>]”
408
Control value:
Policy id
409
410
411
412
413
414
415
416
Example:
<input name="policy[0]" type="hidden" value="1111-aaaa-2222" />
<input name="policy[1]" type="hidden" value="3333-bbbb-4444" />
<input name="policy[2]" type="hidden" value="5555-cccc-6666" />
417
1.4.4.3.6 Change Token
418
419
A CMIS change token is included by using a form control named “changeToken”. If the value of the
control is set to the empty string, then the repository MUST treat the change token as not set.
420
421
Control name: “changeToken”
422
Control value:
Change token
423
424
425
426
427
428
Example:
<input name="changeToken" type="hidden" value="8923653942" />
429
430
431
432
1.4.4.3.7 Versioning
433
434
When a document is checked in, a control named “versioningState” is used to set the versioning state
and a control named “checkinComment” is used to include comments.
435
1.4.4.3.7.1 Versioning State:
436
Control name: “versioningState”
437
Control value:
Versioning state enum ("none", "major", "minor", "checkedout")
438
439
440
441
442
Example:
<input name="versioningState" type="hidden" value="major" />
443
444
1.4.4.3.7.2 Checkin Comment
445
446
Control name: “checkinComment”
447
Control value:
Checkin comment
448
449
450
451
452
453
Example:
<input name="checkinComment" type="text" value="My comment" />
454
455
456
1.4.4.3.8 Query
457
458
A CMIS query can be constructed using a control named “statement” and set of controls to specify the
query options.
459
1.4.4.3.8.1 Statement:
460
Control name: “statement”
461
Control value:
462
1.4.4.3.8.2 Search all versions:
463
Control name: “searchAllVersions”
464
Control value:
465
1.4.4.3.8.3 Include relationships:
466
Control name: “includeRelationships”
467
Control value:
468
1.4.4.3.8.4 Rendition filter:
469
Control name: “renditionFilter”
470
Control value:
471
1.4.4.3.8.5 Include allowable actions:
472
Control name: “includeAllowableActions”
473
Control value:
474
1.4.4.3.8.6 Max items:
475
Control name: “maxItems”
476
Control value:
477
1.4.4.3.8.7 Skip count:
478
Control name: “skipCount”
479
Control value:
CMIS query statement
boolean (“true”, “false”)
includeRelationships enum ("none", "source" ,"target", "both")
rendition filter
boolean (“true”, “false”)
non-negative integer
non-negative integer
480
481
482
483
484
485
486
487
488
489
490
491
Example:
<input
<input
<input
<input
<input
<input
<input
name="statement" type="text" value="SELECT *
name="searchAllVersions"
type="hidden"
name="includeRelationships"
type="hidden"
name="renditionFilter"
type="hidden"
name="includeAllowableActions" type="hidden"
name="maxItems"
type="hidden"
name="skipCount"
type="hidden"
492
1.4.4.3.9 Content
493
A file select control SHOULD be used to attach content.
494
495
Control name: “content”
496
Control value:
497
498
499
500
501
none
<tr>
<td>File:</td>
<td><input name="content" type="file"></td>
FROM cmis:document" />
value="false" />
value="none" />
value="cmis:none" />
value="false" />
value="100" />
value="0" />
502
503
504
505
</tr>
506
507
1.4.4.4 Access to Form Response Content
508
509
510
511
512
513
514
JSON response content is subject to the same security constraints as any other kind of JavaScript which
means that a browser will not allow JavaScript in a page to access JSON objects included in an HTML
Form response if that response came from a different domain than the rest of the page content. For
example, suppose a browser displayed an HTML Form from Web Server foo.example.com to create a
document in a CMIS repository on server bar.example.com. When the user submits the form, there is no
way for the page to access the JSON object representing the new document created as a response to the
submitted form.
515
516
517
518
519
To make it possible for a browser client to access the JSON content answered from the CMIS repository,
we introduce an optional token called “cmistransaction”. It is a client generated value that is intended to be
used exactly once by the client to retrieve information about the results of a previous CMIS HTML Form
post.
520
521
522
To make this work, the CMIS repository MUST keep the core result details (the status code, object id and
error message) of a completed request and make those details available to the client in a later request.
523
524
525
526
In order to correlate the result of a CMIS request with the later call to retrieve the result of that request,
the client needs to generate a unique string and include this in the submitted HTML form in a form control
with the name “cmistransaction”. The mechanism to generate the value for this form control is a client
527
528
529
530
decision and the only requirement on this mechanism is that it should be generated in a way that makes it
unique enough that the client can retrieve the intended result, within a relatively short period of time
(within about one hour). For example, one approach would generate the value by concatenating the
number of milliseconds since 1970/01/01, UTC, with a random number and the name of the cmis object
531
532
533
534
535
536
Example:
<input name="cmistransaction" type="hidden" value="1296216073275-4312331document" />type="hidden" value="0" />
537
538
539
540
After the operation has been performed, the client can retrieve the result by sending a HTTP GET
requested to the repository URL (see section 1.3.1) with the selector set to “lastResult” and a parameter
“cmistransaction” which is set to the same string previously sent with the form.
541
542
The result details MUST be answered as a JSON object containing these elements.
543
544
integer code
545
An integer containing the HTTP status code for the operation.
546
string objectId
547
548
A string containing the id of the object, if the operation was successful. If the operation was not
successful, the value of this string is undefined.
549
string exception
550
551
A string containing the exception, if the operation was unsuccessful. If the operation was successful,
the value of this string is undefined.
552
string message
553
554
A string containing the error message, if the operation was unsuccessful. If the operation was
successful, the value of this string is undefined.
555
556
557
558
559
560
561
562
563
564
The result details SHOULD
only be available to the same client (as defined by the client’s IP address) that called the operation.
not be kept longer than an hour, since they are supposed to be retrieved immediately after the
operation by the client.
only be retrievable once. That is, a second attempt SHOULD return an invalidArgument error (code =
0).
If the value of the parameter “cmistransaction” is invalid, the “code” field of this JSON object MUST be set
to 0.
565
566
567
568
569
If the “cmistransaction” control is not specified in the form, the repository does not need to keep the result
details because there is no way for the client to retrieve them.
570
Example:
571
572
573
When the client submits the HTML form, it can include a form control with the name “cmistransction” like
this…
574
575
576
577
578
<input name="cmistransaction" type="hidden" value="1296216073275-4312331document" />type="hidden" value="0" />
579
580
581
582
583
584
585
Soon thereafter, the client could retrieve the results of the form post by making a request like this
http://localhost:8080/opencmis/browser/A1?cmisselector=lastResult&clientToken=
showNewDocumentId&cmistransaction=1296216073275-4312331-document
586
587
588
589
590
591
and then, the repository would answer a JSON object that contains the result details, like this …
{
code :
201,
592
593
594
595
596
597
objectId : "21983210980-2132-23 objectId",
exception : null,
message : null
}
598
Then the client could retrieve the details for the object using its objectId, as described in section 1.3.3.
599
1.4.4.4.1 Client Implementation Hints
600
601
602
Most applications don’t want to show the JSON object representations to the end-user after (s)he clicks
the form submit button. After all, business users using web browsers don’t want to look at raw JSON
content.
603
604
605
606
To avoid showing JSON to the user, the POST response can instead be directed to a hidden iframe. The
iframe’s onLoad event can be used as an operation status notification. When it is triggered the operation
is complete on the repository side and it is safe then to retrieve the results.
607
608
1.4.4.4.2 Server Implementation Hints
609
610
611
The use of transaction id’s can make CMIS stateful since the server has to remember details of a
previous service request. However, the state can in fact be kept entirely on the client, to eliminate the
need for the server to be stateful at all.
612
1.4.4.4.2.1 State on Server
613
614
Result details are non-permanent data and don’t need to be persisted. A simple in-memory store would
be sufficient.
615
616
617
618
When a repository receives a “lastResult” request it should check the IP address of the client and the
expiration time of the result details before it replies. This ensures that the data is not being retrieved by a
malicious client, and that the requested data is relevant.
619
1.4.4.4.2.2 State on Client
620
The state can be managed on the client side using browser cookies, which keeps the repository stateless.
621
622
623
624
When a “cmistransaction” control is sent with the form data, the repository can attach a cookie to its
POST response. The cookie name is derived from the “cmistransaction” value and the cookie value would
contain the result details.
625
626
627
628
629
When the repository receives a “lastResult” request, it also receives the cookies from the browser. So, if
the repository can find a cookie that matches the “cmistransaction” parameter value it can send back the
cookie value and delete the cookie. If there is no corresponding cookie, it can reply with an error
message.
630
631
632
633
634
635
636
Since the browser takes care of the cookie expiration and cookies can only be sent from the originating
client, there are no new additional security and lifecycle issues for the repository to handle.
637
1.4.5 Browser Binding Examples
638
639
All of the examples used in this document were created using the Apache Chemistry project.
640
1.4.5.1 Getting Repository Info
641
642
643
Repository information is retrieved using an HTTP GET of the service document URL. The response is a
JSON object containing properties each of which describes a single CMIS repository as a nested JSON
object.
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
GET /cmis/repositories HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxxx
{
"A1":{
"repositoryUrl":"http:\/\/localhost:8080\/chemistry-opencmis-bindingbrowser-0.3.0-incubating-SNAPSHOT\/browser\/A1",
"productName":"OpenCMIS InMemory-Server",
"repositoryName":"InMemory Repository",
"capabilities":{
"capabilityChanges":"properties",
"capabilityPWCUpdatable":true,
"capabilityMultifiling":true,
"capabilityAllVersionsSearchable":false,
"capabilityUnfiling":true,
"capabilityJoin":"none",
"capabilityGetDescendants":true,
"capabilityVersionSpecificFiling":false,
"capabilityGetFolderTree":true,
"capabilityACL":"none",
"capabilityRenditions":"none",
"capabilityQuery":"metadataonly",
"capabilityContentStreamUpdatability":"pwconly",
"capabilityPWCSearchable":false
},
"rootFolderId":"100",
"rootFolderUrl":"http:\/\/localhost:8080\/chemistry-opencmis-bindingbrowser-0.3.0-incubating-SNAPSHOT\/browser\/A1\/root",
"latestChangeLogToken":null,
"thinClientURI":null,
"changesIncomplete":true,
"repositoryId":"A1",
"productVersion":"0.1",
"cmisVersionSupported":"1.0",
"aclCapabilities":null,
"principalIdAnonymous":"anonymous",
"repositoryDescription":"InMemory Test Repository",
"vendorName":"OpenCMIS",
"principalIdAnyone":"anyone"
}
}
693
1.4.5.2 Getting Folder Children
694
695
696
The content of a CMIS folder is obtained using an HTTP GET of an object URL for the folder. The
response is a JSON object which contains properties such as hasMoreItems, numItems, as well as an
array of JSON objects each of which describes a child object, such as a cmis:folder or a cmis:document.
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
In this example the objectId is used as the selector.
GET /A1/root?objectId=101 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxxx
{
"numItems":3,
"objects":[
{
"object":{
"properties":{
"cmis:lastModificationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Last Modification Date Property",
"value":1298396347156,
"queryName":"cmis:lastModificationDate",
"localName":"cmis:lastModificationDate",
"id":"cmis:lastModificationDate"
},
"cmis:contentStreamFileName":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Content Stream File Name Property",
"value":"data.txt",
"queryName":"cmis:contentStreamFileName",
"localName":"cmis:contentStreamFileName",
"id":"cmis:contentStreamFileName"
},
"PickListProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample Pick List Property",
"value":"blue",
"queryName":"PickListProp",
"localName":"PickListProp",
"id":"PickListProp"
},
"cmis:baseTypeId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Base Type Id Property",
"value":"cmis:document",
"queryName":"cmis:baseTypeId",
"localName":"cmis:baseTypeId",
"id":"cmis:baseTypeId"
},
"cmis:isImmutable":{
"cardinality":"single",
"type":"boolean",
"displayName":"CMIS Is Immutable Property",
"value":false,
"queryName":"cmis:isImmutable",
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
"localName":"cmis:isImmutable",
"id":"cmis:isImmutable"
},
"cmis:objectId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Id Property",
"value":"114",
"queryName":"cmis:objectId",
"localName":"cmis:objectId",
"id":"cmis:objectId"
},
"cmis:createdBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Created By Property",
"value":"florian",
"queryName":"cmis:createdBy",
"localName":"cmis:createdBy",
"id":"cmis:createdBy"
},
"cmis:lastModifiedBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Last Modified By Property",
"value":"florian",
"queryName":"cmis:lastModifiedBy",
"localName":"cmis:lastModifiedBy",
"id":"cmis:lastModifiedBy"
},
"cmis:changeToken":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Change Token Property",
"value":"1298396347156",
"queryName":"cmis:changeToken",
"localName":"cmis:changeToken",
"id":"cmis:changeToken"
},
"cmis:creationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Creation Date Property",
"value":1298396347156,
"queryName":"cmis:creationDate",
"localName":"cmis:creationDate",
"id":"cmis:creationDate"
},
"StringProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample String Property",
"value":"My Doc StringProperty 6",
"queryName":"StringProp",
"localName":"StringProp",
"id":"StringProp"
},
"cmis:contentStreamMimeType":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Content Stream Mime Type Property",
"value":"text\/plain",
"queryName":"cmis:contentStreamMimeType",
"localName":"cmis:contentStreamMimeType",
"id":"cmis:contentStreamMimeType"
},
"cmis:name":{
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
"cardinality":"single",
"type":"string",
"displayName":"CMIS Name Property",
"value":"My_Document-1-0",
"queryName":"cmis:name",
"localName":"cmis:name",
"id":"cmis:name"
},
"cmis:objectTypeId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Type Id Property",
"value":"ComplexType",
"queryName":"cmis:objectTypeId",
"localName":"cmis:objectTypeId",
"id":"cmis:objectTypeId"
},
"cmis:contentStreamLength":{
"cardinality":"single",
"type":"integer",
"displayName":"CMIS Content Stream Length Property",
"value":32768,
"queryName":"cmis:contentStreamLength",
"localName":"cmis:contentStreamLength",
"id":"cmis:contentStreamLength"
}
}
}
},
{
"object":{
"properties":{
"cmis:lastModificationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Last Modification Date Property",
"value":1298396347156,
"queryName":"cmis:lastModificationDate",
"localName":"cmis:lastModificationDate",
"id":"cmis:lastModificationDate"
},
"cmis:contentStreamFileName":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Content Stream File Name Property",
"value":"data.txt",
"queryName":"cmis:contentStreamFileName",
"localName":"cmis:contentStreamFileName",
"id":"cmis:contentStreamFileName"
},
"PickListProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample Pick List Property",
"value":"blue",
"queryName":"PickListProp",
"localName":"PickListProp",
"id":"PickListProp"
},
"cmis:baseTypeId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Base Type Id Property",
"value":"cmis:document",
"queryName":"cmis:baseTypeId",
"localName":"cmis:baseTypeId",
"id":"cmis:baseTypeId"
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
},
"cmis:isImmutable":{
"cardinality":"single",
"type":"boolean",
"displayName":"CMIS Is Immutable Property",
"value":false,
"queryName":"cmis:isImmutable",
"localName":"cmis:isImmutable",
"id":"cmis:isImmutable"
},
"cmis:objectId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Id Property",
"value":"115",
"queryName":"cmis:objectId",
"localName":"cmis:objectId",
"id":"cmis:objectId"
},
"cmis:createdBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Created By Property",
"value":"jens",
"queryName":"cmis:createdBy",
"localName":"cmis:createdBy",
"id":"cmis:createdBy"
},
"cmis:lastModifiedBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Last Modified By Property",
"value":"jens",
"queryName":"cmis:lastModifiedBy",
"localName":"cmis:lastModifiedBy",
"id":"cmis:lastModifiedBy"
},
"cmis:changeToken":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Change Token Property",
"value":"1298396347156",
"queryName":"cmis:changeToken",
"localName":"cmis:changeToken",
"id":"cmis:changeToken"
},
"cmis:creationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Creation Date Property",
"value":1298396347156,
"queryName":"cmis:creationDate",
"localName":"cmis:creationDate",
"id":"cmis:creationDate"
},
"StringProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample String Property",
"value":"My Doc StringProperty 7",
"queryName":"StringProp",
"localName":"StringProp",
"id":"StringProp"
},
"cmis:contentStreamMimeType":{
"cardinality":"single",
"type":"string",
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
"displayName":"CMIS Content Stream Mime Type Property",
"value":"text\/plain",
"queryName":"cmis:contentStreamMimeType",
"localName":"cmis:contentStreamMimeType",
"id":"cmis:contentStreamMimeType"
},
"cmis:name":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Name Property",
"value":"My_Document-1-1",
"queryName":"cmis:name",
"localName":"cmis:name",
"id":"cmis:name"
},
"cmis:objectTypeId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Type Id Property",
"value":"ComplexType",
"queryName":"cmis:objectTypeId",
"localName":"cmis:objectTypeId",
"id":"cmis:objectTypeId"
},
"cmis:contentStreamLength":{
"cardinality":"single",
"type":"integer",
"displayName":"CMIS Content Stream Length Property",
"value":32768,
"queryName":"cmis:contentStreamLength",
"localName":"cmis:contentStreamLength",
"id":"cmis:contentStreamLength"
}
}
}
},
{
"object":{
"properties":{
"cmis:lastModificationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Last Modification Date Property",
"value":1298396347171,
"queryName":"cmis:lastModificationDate",
"localName":"cmis:lastModificationDate",
"id":"cmis:lastModificationDate"
},
"cmis:contentStreamFileName":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Content Stream File Name Property",
"value":"data.txt",
"queryName":"cmis:contentStreamFileName",
"localName":"cmis:contentStreamFileName",
"id":"cmis:contentStreamFileName"
},
"PickListProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample Pick List Property",
"value":"blue",
"queryName":"PickListProp",
"localName":"PickListProp",
"id":"PickListProp"
},
"cmis:baseTypeId":{
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
"cardinality":"single",
"type":"id",
"displayName":"CMIS Base Type Id Property",
"value":"cmis:document",
"queryName":"cmis:baseTypeId",
"localName":"cmis:baseTypeId",
"id":"cmis:baseTypeId"
},
"cmis:isImmutable":{
"cardinality":"single",
"type":"boolean",
"displayName":"CMIS Is Immutable Property",
"value":false,
"queryName":"cmis:isImmutable",
"localName":"cmis:isImmutable",
"id":"cmis:isImmutable"
},
"cmis:objectId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Id Property",
"value":"116",
"queryName":"cmis:objectId",
"localName":"cmis:objectId",
"id":"cmis:objectId"
},
"cmis:createdBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Created By Property",
"value":"greg",
"queryName":"cmis:createdBy",
"localName":"cmis:createdBy",
"id":"cmis:createdBy"
},
"cmis:lastModifiedBy":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Last Modified By Property",
"value":"greg",
"queryName":"cmis:lastModifiedBy",
"localName":"cmis:lastModifiedBy",
"id":"cmis:lastModifiedBy"
},
"cmis:changeToken":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Change Token Property",
"value":"1298396347171",
"queryName":"cmis:changeToken",
"localName":"cmis:changeToken",
"id":"cmis:changeToken"
},
"cmis:creationDate":{
"cardinality":"single",
"type":"datetime",
"displayName":"CMIS Creation Date Property",
"value":1298396347171,
"queryName":"cmis:creationDate",
"localName":"cmis:creationDate",
"id":"cmis:creationDate"
},
"StringProp":{
"cardinality":"single",
"type":"string",
"displayName":"Sample String Property",
"value":"My Doc StringProperty 8",
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
"queryName":"StringProp",
"localName":"StringProp",
"id":"StringProp"
},
"cmis:contentStreamMimeType":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Content Stream Mime Type Property",
"value":"text\/plain",
"queryName":"cmis:contentStreamMimeType",
"localName":"cmis:contentStreamMimeType",
"id":"cmis:contentStreamMimeType"
},
"cmis:name":{
"cardinality":"single",
"type":"string",
"displayName":"CMIS Name Property",
"value":"My_Document-1-2",
"queryName":"cmis:name",
"localName":"cmis:name",
"id":"cmis:name"
},
"cmis:objectTypeId":{
"cardinality":"single",
"type":"id",
"displayName":"CMIS Object Type Id Property",
"value":"ComplexType",
"queryName":"cmis:objectTypeId",
"localName":"cmis:objectTypeId",
"id":"cmis:objectTypeId"
},
"cmis:contentStreamLength":{
"cardinality":"single",
"type":"integer",
"displayName":"CMIS Content Stream Length Property",
"value":32768,
"queryName":"cmis:contentStreamLength",
"localName":"cmis:contentStreamLength",
"id":"cmis:contentStreamLength"
}
}
}
}
],
"hasMoreItems":false
}
1138
1139
1.4.5.3 Client Token Example
1140
1141
1142
As described in Section 1.2.6, a client token can be passed into a CMIS read service request to simplify
the handling of the returned JSON object. Here is an example of how that can be used in a
getRepositorories request.
1143
1144
1145
1146
1147
1148
1149
1150
Suppose an HTTP GET of
http://www.example.com/cmis/getRepositories
answered a JSON response like this …
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
{"A1":
{
"repositoryDescription":"InMemory Test Repository",
"repositoryId":"A1",
"repositoryName":"InMemory Repository"
}
}
Note that the contents of the response are abbreviated for brevity.
Adding the clientToken parameter to the request like this
"http://www.example.com/cmis/getRepositories?clientToken=showRepositoryInfo"
would result in this response ...
showRepositoryInfo (
{"A1":
{
"repositoryDescription":"InMemory Test Repository",
"repositoryId":"A1",
"repositoryName":"InMemory Repository"
}
}
)
On the client side, the result is a call to the JavaScript function, showRepositoryInfo, with the JSON
object passed as a parameter.
1185
1186
Putting it all together, the following illustration and sample code shows how a JSON object is fetched
when an HTML page is loaded, and how the JSON object can be handled by a JavaScript function.
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
<html>
<title>Repository Information</title>
<script type="text/javascript">
function showRepositoryInfo(repositoryInfo) {
for(repId in repositoryInfo) {
var ri = repositoryInfo [repId];
document.write("<h1>Repository Information</h1>");
document.write("<ul>");
document.write("<li>ID..."+ri.repositoryID+"</li>");
document.write("<li>Name..."+ri.repositoryName+"</li>");
document.write("<li>Description..."+ri.repositoryDescription);
document.write("</li>");
document.write("</ul>");
}
}
</script>
<script type="text/javascript"
src="http://www.example.com/cmis/getRepositories?clientToken=showRepositoryInf
o"></script>
</html
1214
1215
1.4.5.4 Creating a Document
1216
1217
1218
A CMIS document can be created using HTTP POST of an HTML form to an <object> URL when creating
a document in a folder or to a <repository> URL when instead creating an unfiled document (if allowed by
the repository).
1219
1220
In this example, a document by posting to a folder path entered
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
Let’s look at an HTML page containing a simple form.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>OpenCMIS Browser Binding createDocument Demo</title>
<style type="text/css">
body {
font-family: Arial, sans-serif;
font-size: 11pt;
}
.box {
border-width: 1px;
border-style: solid;
width: 100%;
padding: 3px;
}
td {
padding: 5px;
}
</style>
<script type="text/javascript">
var repositoryUrl;
var rootFolderUrl;
var lastTransaction;
function loadRepositoryInfos(infos) {
for(repId in infos) {
var ri = infos[repId];
// the InMemory repository has only one repository
repositoryUrl = ri.repositoryUrl;
rootFolderUrl = ri.rootFolderUrl;
}
}
function createDocument() {
var createForm = document.getElementById('createForm');
var docname = createForm["propertyValue[0]"].value;
document.getElementById('info').innerHTML = "Creating " + docname + "
...";
createForm.action = rootFolderUrl + createForm.folder.value;
lastTransaction = (new Date()).getTime() + "-" +
Math.floor(Math.random()*10000000) + "-" + docname;
createForm.transaction.value = lastTransaction;
return true;
}
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
function createDocumentCallback() {
if(lastTransaction) {
document.getElementById('info').innerHTML = 'Transaction: ' +
lastTransaction
var script1 = document.createElement("script");
script1.setAttribute("src", repositoryUrl +
"?selector=lastResult&clientToken=showNewDocumentId&transaction="+lastTransact
ion);
script1.setAttribute("type","text/javascript");
document.body.appendChild(script1);
}
}
function showNewDocumentId(result) {
if(result.objectId) {
alert("New document id: " + result.objectId + " (code: " + result.code
+ ")");
}
else {
alert("Error: " + result.error + " (code: " + result.code + ")");
}
}
</script>
</head>
<body>
<h1>OpenCMIS Browser Binding - Create Demo</h1>
<h2>Create Document</h2>
<form id="createForm" action="" method="POST" target="result"
enctype="multipart/form-data" onsubmit="return createDocument()">
<input name="cmisaction" type="hidden" value="createDocument" />
<input name="transaction" type="hidden" value="" />
<table>
<tr>
<td>Folder:</td>
<td><input name="folder" type="text" size="100" maxlength="1000"
value="/"></td>
</tr>
<tr>
<td>Name:</td>
<td><input id="docname" name="propertyValue[0]" type="text" size="100"
maxlength="100" value="document"></td>
<input name="propertyId[0]" type="hidden" value="cmis:name" />
</tr>
<tr>
<td>Object Type:</td>
<td><input name="propertyValue[1]" type="text" size="100" maxlength="100"
value="cmis:document"></td>
<input name="propertyId[1]" type="hidden" value="cmis:objectTypeId" />
</tr>
<tr>
<td>File name:</td>
<td><input name="filename" type="text" size="30" maxlength="30" value="">
(if left blank the orignal file name is used)</td>
</tr>
<tr>
<td>Content type:</td>
<td><input name="contentType" type="text" size="30" maxlength="30"
value=""> (if left blank the content type is determined by the browser)</td>
</tr>
<tr>
<td>File:</td>
<td><input name="content" type="file"></td>
</tr>
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
<tr>
<td></td>
<td><input type="submit" value="Create" /></td>
</tr>
</table>
</form>
<div id="info"></div>
<iframe name="result" style="border:2px;width:600px;height:400px;"
onload="createDocumentCallback()"></iframe>
<script type="text/javascript"
src="browser?clientToken=loadRepositoryInfos"></script>
</body>
</html>
The example illustrates a few interesting points.
1359
1360
The form takes advantage of the client token introduced in section 1.4.2 to obtain the root URL of
the repository. This root URL is used to compose the full path to which to post the form.
1361
1362
1363
The properties of the document are encoded in the form using pairs of form controls, one member
of the pair being a hidden control containing the CMIS property name and the other member
containing the property’s value.
1364
1365
The CMIS operation to be performed (createDocument) is encoded using a hidden control for
“cmisaction”.
1366
1367
1368
The content stream for the document is obtained by using a file type HTML form property which
causes the web browser rendering the form to present a dialog to the end user to select a local
file to POST with the form.
1369
1370
1371
1372
1373
1374
The following illustration shows what the simple HTML form looks like when, and how the form elements
and actions are defined in the form.
1375
1376
1377
1378
1379
When the user clicks the “Create” button, the JavaScript function createDocument runs. In this
function, the target URL is computed using the folder name entered by the user appended to the root
repository URL fetched in the loadRepositoryInfo function that runs when the page is loaded.
1380
1.4.5.5 An Open Social Gadget Example
1381
1382
Because the Browser Binding only uses elements understood by modern web browsers, it is possible to
use it to create web 2.0 style application components such as, for example, Open Social Gadgets.
1383
1384
1385
1386
1387
Here is a complete Open Social Gadget that displays repository information. All that was required to
create this example was the use of the JSONP pattern described in section 1.2.6, some JavaScript to
process the results and then a gadget ‘wrapper’, essentially a little bit of XML that can be understood by
the gadget container.
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="CMIS Example" scrolling="true">
<Require feature="opensocial-0.7" />
<Require feature="dynamic-height" />
</ModulePrefs>
<Content type="html">
<![CDATA[
<style type="text/css">
.leftcol
{
color: #E3AF1B;
text-align: left;
font-weight: bold;
background-color: #552681;
}
.rightcol
{
color: #552681;
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
text-align: left;
font-weight: bold;
background-color: #E3AF1B;
}
</style>
<script type='text/javascript'>
gadgets.window.adjustHeight( '600px' );
var
var
var
var
var
var
var
var
var
var
repositoryUrl;
rootFolderUrl;
repositoryName;
productName;
latestChangeLogToken;
thinClientURI;
changesIncomplete;
productVersion;
cmisVersionSupported;
repositoryDescription;
function loadRepositoryInfo(info) {
for(repId in info) {
var ri = info[repId];
repositoryUrl = ri.repositoryUrl;
rootFolderUrl = ri.rootFolderUrl;
repositoryId = ri.repositoryId;
repositoryName = ri.repositoryName;
productName = ri.productName;
latestChangeLogToken = (ri.latestChangeLogToken == null ? "null" :
ri.latestChangeLogToken);
thinClientURI = (ri.thinClientURI == null ? "null" :
ri.thinClientURI);
changesIncomplete = (ri.changesIncomplete == null ? "null" :
ri.changesIncomplete);
productVersion = ri.productVersion;
cmisVersionSupported = ri.cmisVersionSupported;
repositoryDescription = ri.repositoryDescription;
document.getElementById('r1').innerHTML = repositoryUrl;
document.getElementById('r2').innerHTML = rootFolderUrl;
document.getElementById('r3').innerHTML = repositoryId;
document.getElementById('r4').innerHTML = repositoryName;
document.getElementById('r5').innerHTML = productName;
document.getElementById('r6').innerHTML = latestChangeLogToken;
document.getElementById('r7').innerHTML = thinClientURI;
document.getElementById('r8').innerHTML = changesIncomplete;
document.getElementById('r9').innerHTML = productVersion;
document.getElementById('r10').innerHTML = cmisVersionSupported;
document.getElementById('r11').innerHTML = repositoryDescription;
}
}
</script>
<center>
<img src="http://localhost:8080/images/Cmis_logolittle.png">
<br/>
<h3>Repository Info</H3>
<br/>
</center>
<TABLE BORDER=1>
<TR><TD class="leftcol">Repository ID</TD><TD class="rightcol"><b
id='r3'></b></TD></TR>
<TR><TD class="leftcol">Repository Name</TD><TD class="rightcol"><b
id='r4'></b></TD></TR>
<TR><TD class="leftcol">Repository Description</TD><TD class="rightcol"><b
id='r11'></b></TD></TR>
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
<TR><TD class="leftcol">Repository URL</TD><TD class="rightcol"><b
id='r1'></b></TD></TR>
<TR><TD class="leftcol">Repository Root Folder URL</TD><TD class="rightcol"><b
id='r2'></b></TD></TR>
<TR><TD class="leftcol">Product Name</TD><TD class="rightcol"><b
id='r5'></b></TD></TR>
<TR><TD class="leftcol">Latest Change Log Token</TD><TD class="rightcol"><b
id='r6'></b></TD></TR>
<TR><TD class="leftcol">Thin Client URI</TD><TD class="rightcol"><b
id='r7'></b></TD></TR>
<TR><TD class="leftcol">Changes Incomplete</TD><TD class="rightcol"><b
id='r8'></b></TD></TR>
<TR><TD class="leftcol">Product Version</TD><TD class="rightcol"><b
id='r9'></b></TD></TR>
<TR><TD class="leftcol">CMIS Version</TD><TD class="rightcol"><b
id='r10'></b></TD></TR>
</TABLE>
<script type="text/javascript" src="http://localhost:8080/chemistry-opencmisbinding-browser-0.3.0-incubatingSNAPSHOT/browser?clientToken=loadRepositoryInfo"></script>
]]>
</Content>
</Module>
1507
1508
1509
1.4.5.6 Query Example
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
A CMIS query can be run using either GET or POST. Here is an example of a query by POSTing a
simple HTML form with the cmisaction control set to ‘query’ and the query string set in the control named
‘statement’.
<form id="queryForm" action="" method="POST">
<input name="cmisaction" type="hidden" value="query" />
<table>
<tr><td>Query:</td><td><input name="statement" type="text" size="100"
maxlength="1000" value="SELECT * FROM cmis:document"></td></tr>
<tr><td>Max Items:</td><td><input name="maxItems" type="text" size="4"
maxlength="8" value="100"></td></tr>
<tr><td>Skip Count:</td><td><input name="skipCount" type="text" size="4"
maxlength="8" value="0"></td></tr>
<tr><td></td><td><input type="submit" value="Go" /></td></tr>
</table>
</form>
1527
1528
1529
1530
1531
1532
1533
1534
The response to the form would look like this…
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxxx
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
{
"numItems":2,
"objects":[
{
"properties":{
"cmis:lastModificationDate":{
"displayName":"CMIS Last Modification Date Property",
"value":[
1298424879953
],
"queryName":"cmis:lastModificationDate",
"localName":"cmis:lastModificationDate",
"id":"cmis:lastModificationDate"
},
"cmis:contentStreamFileName":{
"displayName":"CMIS Content Stream File Name Property",
"value":[
"data.txt"
],
"queryName":"cmis:contentStreamFileName",
"localName":"cmis:contentStreamFileName",
"id":"cmis:contentStreamFileName"
},
"PickListProp":{
"displayName":"Sample Pick List Property",
"value":[
"blue"
],
"queryName":"PickListProp",
"localName":"PickListProp",
"id":"PickListProp"
},
"cmis:baseTypeId":{
"displayName":"CMIS Base Type Id Property",
"value":[
"cmis:document"
],
"queryName":"cmis:baseTypeId",
"localName":"cmis:baseTypeId",
"id":"cmis:baseTypeId"
},
"cmis:isImmutable":{
"displayName":"CMIS Is Immutable Property",
"value":[
false
],
"queryName":"cmis:isImmutable",
"localName":"cmis:isImmutable",
"id":"cmis:isImmutable"
},
"cmis:objectId":{
"displayName":"CMIS Object Id Property",
"value":[
"105"
],
"queryName":"cmis:objectId",
"localName":"cmis:objectId",
"id":"cmis:objectId"
},
"cmis:createdBy":{
"displayName":"CMIS Created By Property",
"value":[
"unknown"
],
"queryName":"cmis:createdBy",
"localName":"cmis:createdBy",
"id":"cmis:createdBy"
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
},
"cmis:lastModifiedBy":{
"displayName":"CMIS Last Modified By Property",
"value":[
"unknown"
],
"queryName":"cmis:lastModifiedBy",
"localName":"cmis:lastModifiedBy",
"id":"cmis:lastModifiedBy"
},
"cmis:changeToken":{
"displayName":"CMIS Change Token Property",
"value":[
"1298424879953"
],
"queryName":"cmis:changeToken",
"localName":"cmis:changeToken",
"id":"cmis:changeToken"
},
"cmis:creationDate":{
"displayName":"CMIS Creation Date Property",
"value":[
1298424879953
],
"queryName":"cmis:creationDate",
"localName":"cmis:creationDate",
"id":"cmis:creationDate"
},
"StringProp":{
"displayName":"Sample String Property",
"value":[
"My Doc StringProperty 0"
],
"queryName":"StringProp",
"localName":"StringProp",
"id":"StringProp"
},
"cmis:contentStreamMimeType":{
"displayName":"CMIS Content Stream Mime Type Property",
"value":[
"text\/plain"
],
"queryName":"cmis:contentStreamMimeType",
"localName":"cmis:contentStreamMimeType",
"id":"cmis:contentStreamMimeType"
},
"cmis:name":{
"displayName":"CMIS Name Property",
"value":[
"My_Document-2-0"
],
"queryName":"cmis:name",
"localName":"cmis:name",
"id":"cmis:name"
},
"cmis:objectTypeId":{
"displayName":"CMIS Object Type Id Property",
"value":[
"ComplexType"
],
"queryName":"cmis:objectTypeId",
"localName":"cmis:objectTypeId",
"id":"cmis:objectTypeId"
},
"cmis:contentStreamLength":{
"displayName":"CMIS Content Stream Length Property",
"value":[
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
32768
],
"queryName":"cmis:contentStreamLength",
"localName":"cmis:contentStreamLength",
"id":"cmis:contentStreamLength"
}
}
},
{
"properties":{
"cmis:lastModificationDate":{
"displayName":"CMIS Last Modification Date Property",
"value":[
1298424879968
],
"queryName":"cmis:lastModificationDate",
"localName":"cmis:lastModificationDate",
"id":"cmis:lastModificationDate"
},
"cmis:contentStreamFileName":{
"displayName":"CMIS Content Stream File Name Property",
"value":[
"data.txt"
],
"queryName":"cmis:contentStreamFileName",
"localName":"cmis:contentStreamFileName",
"id":"cmis:contentStreamFileName"
},
"PickListProp":{
"displayName":"Sample Pick List Property",
"value":[
"blue"
],
"queryName":"PickListProp",
"localName":"PickListProp",
"id":"PickListProp"
},
"cmis:baseTypeId":{
"displayName":"CMIS Base Type Id Property",
"value":[
"cmis:document"
],
"queryName":"cmis:baseTypeId",
"localName":"cmis:baseTypeId",
"id":"cmis:baseTypeId"
},
"cmis:isImmutable":{
"displayName":"CMIS Is Immutable Property",
"value":[
false
],
"queryName":"cmis:isImmutable",
"localName":"cmis:isImmutable",
"id":"cmis:isImmutable"
},
"cmis:objectId":{
"displayName":"CMIS Object Id Property",
"value":[
"122"
],
"queryName":"cmis:objectId",
"localName":"cmis:objectId",
"id":"cmis:objectId"
},
"cmis:createdBy":{
"displayName":"CMIS Created By Property",
"value":[
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
"unknown"
],
"queryName":"cmis:createdBy",
"localName":"cmis:createdBy",
"id":"cmis:createdBy"
},
"cmis:lastModifiedBy":{
"displayName":"CMIS Last Modified By Property",
"value":[
"unknown"
],
"queryName":"cmis:lastModifiedBy",
"localName":"cmis:lastModifiedBy",
"id":"cmis:lastModifiedBy"
},
"cmis:changeToken":{
"displayName":"CMIS Change Token Property",
"value":[
"1298424879968"
],
"queryName":"cmis:changeToken",
"localName":"cmis:changeToken",
"id":"cmis:changeToken"
},
"cmis:creationDate":{
"displayName":"CMIS Creation Date Property",
"value":[
1298424879968
],
"queryName":"cmis:creationDate",
"localName":"cmis:creationDate",
"id":"cmis:creationDate"
},
"StringProp":{
"displayName":"Sample String Property",
"value":[
"My Doc StringProperty 10"
],
"queryName":"StringProp",
"localName":"StringProp",
"id":"StringProp"
},
"cmis:contentStreamMimeType":{
"displayName":"CMIS Content Stream Mime Type Property",
"value":[
"text\/plain"
],
"queryName":"cmis:contentStreamMimeType",
"localName":"cmis:contentStreamMimeType",
"id":"cmis:contentStreamMimeType"
},
"cmis:name":{
"displayName":"CMIS Name Property",
"value":[
"My_Document-2-1"
],
"queryName":"cmis:name",
"localName":"cmis:name",
"id":"cmis:name"
},
"cmis:objectTypeId":{
"displayName":"CMIS Object Type Id Property",
"value":[
"ComplexType"
],
"queryName":"cmis:objectTypeId",
"localName":"cmis:objectTypeId",
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
"id":"cmis:objectTypeId"
},
"cmis:contentStreamLength":{
"displayName":"CMIS Content Stream Length Property",
"value":[
32768
],
"queryName":"cmis:contentStreamLength",
"localName":"cmis:contentStreamLength",
"id":"cmis:contentStreamLength"
}
}
}
],
"hasMoreItems":true
}
1830
Appendix A. Acknowledgements
1831
1832
The following individuals have participated in the creation of this specification and are gratefully
acknowledged:
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
Participants:
Jay Brown, IBM
Derek Carr, IBM
David Caruana, Alfresco Software
Eric Chan, Oracle Corporation
David Choy, EMC Corporation
Cornelia Davis, EMC Corporation
Florent Guillaume, Nuxeo
Jens Hübel, Open Text Corporation
Ryan McVeigh, Zia Consulting
Scott Malabarba, IBM
Gregory Melahn, IBM
Florian Müller, Alfresco
David Nuescheler, Day Software
Peeter Piegaze, Day Software
David Pittfield, Oracle Corporation
Norrie Quinn, EMC Corporation
1854
Appendix B. Schema Language (Orderly)
1855
1856
We wish to thank Lloyd Hilaiel for his work in defining the Orderly language, and express our gratitude for
allowing the use of Orderly in this specification.
1857
1858
1859
1860
1861
1862
The following is a description of the Orderly Language. In this description, we have liberally copied
sections from the original Orderly definition from http://Orderly-json.org/. In some cases, there may be
differences between the description here and the description from http://Orderly-json.org/. In any case,
the description of Orderly in this specification SHALL be used to describe the JSON elements of this
specification.
1863
1864
B.1 Overview
1865
1866
1867
Orderly is an ergonomic micro-language that can represent a subset of JSONSchema. Orderly is
designed to feel familiar to the average programmer and to be extremely easy to learn and remember.
This document provides a conversational overview of Orderly as well as a normative grammar.
1868
B.2 A subset of JSONSchema
1869
1870
JSONSchema attempts to provide a representation for three distinct types of information about JSON
structures:
1871
* Data structure (for documentation and validation purposes)
1872
* Storage attributes (information pertinent to tools that wish to persist JSON data)
1873
* Interaction Control (providing hints on how to render a UI where data can be manipulated).
1874
1875
1876
Orderly purposefuly ignores all features of JSONSchema which aren't useful for validation, including the
following attributes:
1877
* options (label/value)
1878
* title
1879
* description
1880
* transient
1881
* hidden
1882
* disallow
1883
* extends
1884
* identity
1885
1886
An exhaustive list of the differences between Orderly and JSONSchema is below.
1887
B.3 A Non-Normative Tutorial
1888
A collection of Non-normative examples of Orderly:
1889
B.3.1 Comments and Whitespace
1890
1891
Orderly supports comments, comments are initiated with either '#' or '//' and continue to the first
encountered newline ('\n').
1892
1893
1894
Orderly doesn't rely overmuch on whitespace, leaving the decision of how to format your schema up to
you.
1895
B.3.2 Property Names
1896
1897
Property names may be anything that is allowed inside JSON strings. Unlike JSON itself, however,
Orderly provides a shorthand that allows a subset of strings to be represented without quotes.
1898
1899
1900
1901
1902
1903
1904
1905
For instance these are all valid Orderly:
string foo;
string "foo";
string "this is a property name with spaces";
1906
1907
B.3.3 Common Properties
1908
1909
From the JSONSchema specification, four options exist which apply to all data types:
1910
1911
1912
1913
1914
1915
1916
1917
The optional property indicates a value which is not required in a conformant JSON instance. Optional
values are represented in Orderly with a trailing question mark:
string name?;
string "name"?;
1918
1919
1920
1921
1922
1923
1924
1925
The requires property says that if a value is present in the instance JSON, another named value MUST
also be present. In Orderly a requirement on another type is expressed by placing the property name
(optionally quoted) enclosed in angle brackets at the end of a type definition:
string town <state>;
1926
1927
1928
1929
1930
Multiple properties MAY be required, and SHOULD be separated with commas:
string town <state,zip>;
1931
1932
1933
1934
1935
1936
The enum property specifies a set of allowable values for a key in the JSON document.
string mood [ "happy", "sad", "meh" ];
integer secretOfLife [ 7, 42 ];
1937
1938
1939
1940
1941
1942
1943
1944
1945
In a JSONSchema document the default property specifies a default value for a property. One could
imagine that as an input object passes validation it will be automatically augmented with default values for
required properties missing in the instance object. The specification of default values in Orderly looks
something like assignment in most programming languages:
string mood [ "happy", "sad", "meh" ] = "happy"; # optimistically default to
"happy"
1946
1947
B.3.4 String Types
1948
1949
1950
1951
1952
1953
1954
1955
Strings are specified in Orderly using the string type specifier. Strings in JSONSchema support
"minLength" and "maxLength" properties, which are represented in Orderly using curly braces
immediately after the type:
string{4,12} login;
1956
1957
1958
1959
1960
1961
Omission of a specification of either minimum or maximum is allowed:
string{4,} login; # login requires at least 4 chars
string{,32} name; # name may not be longer than 32 chars
1962
1963
1964
1965
1966
1967
1968
Regular expressions are supported in JSONSchema for string values. In Orderly you may directly
provide a regular expression using '/' syntax to denote the beginning and end of the regular expression:
string mood /^((happy)|(sad)|(meh))$/;
1969
1970
B.3.5 Number and Integer types
1971
1972
1973
Numbers are specified in Orderly using the number type specifier. In JSONSchema numbers and integers
support ranges, in Orderly these ranges for numbers are specified in the same way we specify ranges for
strings:
1974
1975
1976
1977
1978
number{0.02, 0.98} numNum;
integer{0,10} rating
1979
1980
Syntactically, numbers in Orderly follow the same rules as numbers in JSON.
1981
1982
B.3.6 Boolean Types
1983
Boolean types are represented in Orderly using the boolean type specifier:
1984
1985
1986
boolean iShouldStay;
1987
1988
B.3.7 Object Types
1989
1990
1991
1992
Objects are represented in Orderly using the object type specifier:
object {
1993
1994
1995
1996
1997
string foo;
integer bar;
number baz;
};
1998
1999
2000
2001
2002
2003
2004
2005
2006
Object definitions may be "closed", meaning that properties that are not explicitly mentioned are not
allowed, or "open". A trailing star (*) indicates an "open" object defintion:
object {
string foo;
# whatever other properties you want, thanks to that star
}*;
2007
2008
B.3.8 Array Types
2009
2010
2011
2012
2013
2014
2015
2016
2017
Arrays are specified using the array type specifier. Schemas for arrays elements may be specified in
one of two ways. First, we can specify a single schema that governs all array members, with the
schema enclosed by square brackets:
array [
numbers{0.00, 1.00};
] weights; # an array of floating point weights between 0 and 1.
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
Alternately, "tuple typing" may be used to specify the allowable values for an array, in this case a list of
schemas that apply to each member of the array in sequence:
array {
integer;
string;
number;
} artificial;
2029
2030
2031
2032
2033
2034
2035
When tuple typing is used, the * operator may be used to allow additional elements at the end of an array.
For instance, to specify an array where the first element is an integer and the remaining are of arbitrary
number and type, one might use the following schema:
array { integer; }* intFollowedByWhatever;
2036
2037
2038
2039
2040
Finally, array types also support range semantics, for min/max number of elements:
array { integer; } {0,10} myArrayOfSmallInts;
2041
2042
B.3.9 Additional properties in arrays and objects
2043
2044
JSONSchema provides the additionalProperties attribute which allows a schema author to either:
2045
2046
2047
2048
* specify that a valid instance object/array may not have any properties not in the schema
* specify an additional schema that applies to any additional properties in the instance object/array that
are not explicitly mentioned in the schema
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
Orderly allows you to specify if additional properties SHOULD be allowed, but does not allow you to
specify a schema which governs these additional properties. A trailing * in Orderly indicates additional
properties are allowed, and occurs immediately after the definition of nested schemas (the closing curly
brace) for both objects:
object {
string name;
string title;
}* employee;
2060
2061
2062
2063
2064
2065
and for arrays
array { integer; string; }* myOpenTupleTypedArray
2066
2067
B.3.10 Null Types
2068
2069
2070
2071
2072
2073
2074
The null type in JSONSchema specifies a value that MUST be null. The null type specifier is Orderly's
equivalent:
null likeAir;
2075
2076
2077
2078
2079
2080
2081
2082
2083
As explained in the JSONSchema proposal, null is useful "mainly for purpose of being able use union
types to define nullability". For example:
union {
string [ "Sr.", "Jr.", "III" ];
null;
} suffix;
2084
2085
B.3.11 Any types
2086
2087
2088
2089
2090
2091
2092
"Any types" are represented in Orderly using the any type specifier:
any notes;
2093
B.3.12 Unions
2094
2095
2096
2097
2098
2099
2100
2101
2102
It is possible in JSONSchema to specify a property that may be of one of many different types. In Orderly
this functionality is represented using the union type specifier:
union {
string;
number;
} myUnion;
2103
2104
2105
A key syntactic feature to note is the supported (required?) ommission of property names where they
would be meaningless.
2106
B.3.13 Extensions or Extra Properties
2107
2108
2109
2110
Orderly is capable of concisely representing a subset of JSONSchema, however at times it might be
desirable to be able to represent properties in JSONSchema that are not supported natively in Orderly.
For this reason the backtick operators will allow you to encode a JSON object as part of an Orderly
schema.
2111
2112
2113
2114
2115
For example to attach a description to a schema entry one might generate something like:
string `{"description": "The name of the service"}`;
2116
2117
2118
2119
2120
2121
2122
2123
2124
The author has full control over formatting, as whitespace is ignored:
string `{
"title": "Service Name",
"description": "The name of the service",
"ui_hints": "Use the blink tag"
}`;
2125
2126
B.3.14 ID’s
2127
Schema elements can have an id, specified using the property “id”.
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
For example:
object {
id "http://docs.oasis-open.org/ns/cmis/browser/201103/ACLcapabilities";
string supportedPermissions [ "basic", "repository", "both" ];
string propagation [ "repositorydetermined", "objectonly", "propagate" ];
array { ref "http://docs.oasisopen.org/ns/cmis/browser/201103/permissionDefinition" } permissions;
ref "http://docs.oasis-open.org/ns/cmis/browser/201103/permissionMapping"
mapping?;
}*;
2144
B.3.15 Maps
2145
2146
2147
Associative arrays are neither defined in Orderly nor in JSONSchema. The CMIS Browser Binding
introduces associative arrays (“maps”) to describe a collection of unique keys and a collection of values.
2148
2149
Maps describe JSON objects without fixing the property names and the number of properties.
2150
2151
The keys become JSON object property names and have to be non-null strings. Keys can be restricted,
for example by defining a min and max length, regular expressions, an enum, etc.
2152
The values data type can be defined by any unnamed entry including null.
2153
2154
2155
Maps are specified using the map type specifier. Key and value types are defined within curly braces. The
key type first, followed by “=>”, followed by the value type:
2156
2157
2158
2159
2160
2161
2162
2163
For example:
map { string => boolean } isAllowed;
map { string{2,10} => union { string; integer; null; } } things;
map { string [ "happy", "sad", "meh" ] => integer } intMapping;
2164
2165
B.3.16 References
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
The reference type specifier “ref” is used to refer to another Orderly schema element using the “id”
described in Section B.3.14. For example:
object {
string name;
string title;
ref "http://json-schema.org/card" secretary;
array {
ref "http://json-schema.org/card";
} reports;
} employee;
2179
2180
B.3.17 More Complex Examples
2181
2182
2183
2184
2185
2186
A number with a range, enumerated possible values, and a default value:
integer{0,256} powerOfTwo[1,2,4,8,16,32,64,128,256] = 1;
2187
2188
2189
2190
An object with enumerated possible values and a default.
2191
2192
2193
2194
2195
2196
object {
string beast;
number normalTemperature;
} temps [ { "beast": "canine", "normalTemperature": 101.2 },
{ "beast": "human", "normalTemperature": 98.6 } ]
= { "beast": "canine", "normalTemperature": 101.2 };
2197
2198
B.3.18 Cautions
2199
2200
2201
2202
When you stare hard enough at the grammar of a non-trival language you usually learn quite a deal.
Sometimes what you learn can be surprising or downright confusing. Here's a tour of the darker parts
alleys of Orderly:
2203
2204
2205
2206
2207
2208
Brackets and braces -- visually a tad confusing:
integer{7,42} secretOfLife[7,42];
2209
2210
2211
2212
2213
and a little bit more confusing:
array { integer{7,42}[7,42]; } secretOfLife;
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
B.4 The Normative Grammar
Orderly_schema
unnamed_entry ';'
unnamed_entry
named_entries
named_entry ';' named_entries
named_entry
# nothing
unnamed_entries
unnamed_entry ';' unnamed_entries
unnamed_entry
# nothing
named_entry
definition_prefix property_name definition_suffix
string_prefix property_name string_suffix
unnamed_entry
definition_prefix definition_suffix
string_prefix string_suffix
definition_prefix
'id'
'integer' optional_range
'number' optional_range
'boolean'
'null'
'any'
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
# a tuple-typed array
'array' '{' unnamed_entries '}' optional_additional_marker optional_range
# a simple-typed array (notice the '*' marker is disallowed)
'array' '[' unnamed_entry ']' optional_range
'object' '{' named_entries '}' optional_additional_marker
'union' '{' unnamed_entries '}'
'map' '{' map_key '=>' unnamed_entries '}' optional_optional_marker
string_prefix
'string' optional_range
string_suffix
optional_perl_regex definition_suffix
definition_suffix
optional_enum_values optional_default_value optional_requires \
optional_optional_marker optional_extra_properties
# nothing
map_key
string_prefix string_suffix
csv_property_names
property_name "," csv_property_names
property_name
optional_extra_properties
'`' json_object '`'
# nothing
optional_requires
'<' csv_property_names '>'
# nothing
optional_optional_marker
'?'
# nothing
optional_additional_marker
'*'
# nothing
optional_enum_values
json_array
# nothing
optional_default_value
'=' json_value
# nothing
optional_range
'{' json_number ',' json_number '}'
'{' json_number ',' '}'
'{' ',' json_number '}'
'{' ',' '}'
# nothing
property_name
json_string
[A-Za-z_\-]+
# meaningless, yes.
# (alpha & underbar & dash)
optional_perl_regex # perl compatible regular expressions are supported
'/' ([^/]|\/) '/' # a Perl 5 compatible regular expression
#nothing
------------------------------------------------- [The JSON Grammar] ----------
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
---------------------------------------json_object
{}
{ members }
members
pair
pair , members
pair
json_string : json_value
json_array
[]
[ elements ]
elements
json_value
json_value , elements
json_value
json_string
json_number
json_object
json_array
'true'
'false'
'null'
---------------------------------------json_string
""
" chars "
chars
char
char chars
char
any-Unicode-characterexcept-quote-or-backslash-orcontrol-character
\" #double quote (")
\\
\/
\b
\f
\n
\r
\t
\u four-hex-digits
json_number
int
int frac
int exp
int frac exp
int
digit
digit1-9 digits
- digit
- digit1-9 digits
frac
. digits
exp
e digits
digits
digit
digit digits
e
e
e+
e-
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
E
E+
E-
© Copyright 2026 Paperzz