The Repository API
After reading this guide, you will
- Understand the concept
- Repository item data structure
- Know how to configure the Repository Manager
- Know how to implementing the Repository API
1 Concept
A repository is a service or data source, which provides repository items and is registered with the Repository Manager (RepositoryManager
). The Repository Manger manages all available repositories and routes queries to all registered repositories. Any plugin may make requests to the Repository Manager for repository items, and specify one or more kinds of items it wishes to have returned, such as website
or localanchor
(where localanchor
could be a headline provided by a document repository implementation). Usually a CMS back-end would provide data such as links to sites, images, videos, files that should be available during the editing process. The repository data are repository items that contain JSON data with at least the following attributes: id
, name
, url
, type
. All other attributes are optional and depend on the item’s type
. A repository may provide repository items of a freely definable type
. We suggest type
to be a mimetype, e.g.: image/png
, text/html
, video/H264
, application/pdf
…. However, this is not required.
1.1 Origins
Aloha Editor’s Repository API is based on the CMIS specification.
Notable differences are:
ObjecTypes
is based on CMIS’ Document Object-Type definitionquery()
queryString
: In the CMIS spec comes with its own query language; we limit ourselves to a full text search.renditionFilter
: Instead oftermlist
an array oftype
is expected. If the empty array ornull
is passed, all renditions are returned. See the CMIS specification aboutrenditionFilter
.
2 Repository item data structure
The API and data layout is inspired by CMIS.
2.1 Repository Item types
The object concept from CMIS is inconsistent and too complicated for Aloha Editor’s needs. So we opted for a much simpler model, which is easier to use for developers (but still allows one to implement CMIS if desirable).
2.1.1 type
, baseType
and mimeType
Each repository item must have at least the type
attribute defined, but may optionally also have a mimeType
attribute defined. See below for more details.
Besides type
being required, baseType
is also required. baseType
must be either document
or folder
. That indeed means that you can “subclass” document
and folder
to fullfill your domain-specific or site-specific needs. Note that you can not set baseType
to anything else than document
or folder
— from an OOP point of view, this implies that you can only do single level inheritance, not multiple levels of inheritance.
folder
is used only for browsing your repository, and it probably makes less sense to define your own, more specific type for type = folder
repository items. An example could be that each user in your system has his own folder with content, so you could then define a ownFolder
, so this one could be styled differently in the repository browser.
However, for type = document
repository items, it makes a lot of sense: documents
are the actual content your users are looking for; it’s the whole reason the Repository API exists. Many different types of content likely exist: videos, audio, text, rich text, vector graphics, photographs, and so on. You could define type
to be equal to the mimetype
. But you could also come up with your own types to discern between repository items that have the same mimeType
, such as internalImage
for images that are part of your site/CMS, flickrImage
for external images hosted by Flickr, and externalImage
for other externally hosted images.
2.1.2 Document
id
REQUIREDrepositoryId
REQUIREDname
REQUIREDbaseType
REQUIRED(document|folder)
type
REQUIRED — This is the type you can freely define.parentId
OPTIONALrenditions
OPTIONALlocalName
OPTIONALcreatedBy
OPTIONALcreationDate
OPTIONALlastModifiedBy
OPTIONALlastModificationDate
OPTIONALlength
OPTIONALmimeType
OPTIONALfileName
OPTIONALurl
OPTIONAL
2.1.3 Folder
id
REQUIREDrepositoryId
REQUIREDname
REQUIREDbaseType
REQUIRED(document|folder)
type
REQUIREDparentId
REQUIREDlocalName
OPTIONALcreatedBy
OPTIONALcreationDate
OPTIONALlastModifiedBy
OPTIONALlastModificationDate
OPTIONAL
2.2 Repository Item Renditions
For some type = document
repository items, it makes sense to have multiple representations. For example, for rich text documents, you could have .rtf
, .docx
, .odf
and pdf
renditions (or representations or renderings or derivatives or variations or … inaccurately, but often used: versions). Another example: a vector graphics file in both svg
and pdf
format.
The most archetypical example is probably the case of images: you typically have the “original” image, of which many derivatives are generated: a medium version, a small version and a thumbnail. These call all be renditions!
A more complete example: a page document in a repository may be rendered in 3 different languages. Each of these 3 variations of that page can be served by the repository as a rendition of any of the other 2 translations that correspond with it. Each of these pages may be a stand-alone document in the repository as well. In fact, different renditions for a single document type will likely be different files which the repository will serve back in response to a request for a specific rendition of a given object.
No matter what your renditions (and there is no limit on their number) turn out to be, you can assign it your own naming scheme, so that you can make it fit your needs. The name of a rendition is called its kind
.
2.2.1 Rendition
documentId
ID REQUIRED identifies the rendition document (ThebaseType
must bedocument
)url
URL REQUIRED identifies the rendition stream.mimeType
String REQUIRED The MIME type of the rendition stream.filename
String REQUIRED The filename of the rendition streamlength
Integer OPTIONAL The length of the rendition stream in bytes.name
String OPTIONAL Human readable information about the rendition.kind
String REQUIRED A categorization associated with the rendition. This is freely definable. An example could be:square
– an image square 75×75thumbnail
– a thumbnail version of the objectsmall
– 240 on longest sidemedium
- 500 on longest sidelarge
– 1024 on longest side (only exists for very large original images)docx
– Microsoft docx Version of the contentlang_de
– same content in German languagelang_fr
– same content in French languagepdf
– pdf version of the content
height
Integer OPTIONAL Typically used for imagetype
renditions (expressed as pixels). SHOULD be present ifkind
equalsthumbnail
.width
Integer OPTIONAL Typically used for imagetype
renditions (expressed as pixels). SHOULD be present ifkind
equalsthumbnail
.
2.2.2 Example: Flickr Image Repository Item
- id – gailenejane/5008283282
- name – Quiet moment
- baseType – document
- type – image
- url http://www.flickr.com/photos/gailenejane/5008283282/
The JSON response could look like:
{ id: 'gailenejane/5008283282’, repositoryId: 'flickr', name: 'Quiet moment’, type: ‘image/jpeg’, url: 'http://www.flickr.com/photos/gailenejane/5008283282/‘, renditions: [{ url: 'http://farm5.static.flickr.com/4128/5008283282_f3162bc6b7_s.jpg’, mimeType: ‘image/jpeg’, filename: '4128/5008283282_f3162bc6b7_s.jpg’, kind: ’thumbnail’, height: 75, width: 75 }] }
3 Repository API
3.1 query
The implementation should perform a full text search on all attributes and properties of the repository items.
query()
receives two parameters: p
, which contains all the parameters the query should take into account (if it supports them), and callback
, which should be called whenever the results of the query are available.
3.1.1 Parameters
Parameters are passed as properties of p
.
Required parameters:
queryString
[String]
Optional parameters:
filter
[array] OPTIONAL Attributes that will be returned.orderBy
[array] OPTIONAL e.g.[{lastModificationDate: 'DESC', name: 'ASC'}]
maxItems
[Integer] OPTIONALinFolderId
[RepositoryItem] OPTIONAL This is a predicate function that tests whether or not a candidate object is a child-object of the folder object identified by the giveninFolderId
.inTreeId
[RepositoryItem] OPTIONAL This is a predicate function that tests whether or not a candidate object is a descendant-object of the folder object identified by the giveninTreeId
.skipCount
[Integer] OPTIONAL This is tricky in a merged multi repository scenario.renditionFilter
[array] OPTIONAL An array of zero or moretype
s andkind
s; if empty, then all renditions are returned.
3.1.2 Return values
Required return values:
objects
[Object][] Array of Aloha objects as result of a full text search.hasMoreItems
Boolean
Optional return values:
numItems
[Integer] OPTIONAL
3.2 getChildren
3.2.1 Input attributes
- folderId [RepositoryItem] OPTIONAL If null the root folderId should be used
- maxItems [Integer] OPTIONAL
- skipCount [Integer] OPTIONAL This is tricky in a merged multi repository scenario
- filter [array] OPTIONAL Attributes that will be returned
- renditionFilter [array] OPTIONAL
- Instead of termlist an array of ’’’kind’’’ or ’’’mimetype’’’ is expected. If ’’’null’’’ or ’’’array.length == 0’’’ all renditions are returned. See http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310
3.2.2 Output attributes
- [array] Objects Aloha objects as result of a full text search
- Boolean hasMoreItems
- Integer numItems OPTIONAL
3.3 getObjectById
3.4 markObject
3.5 makeClean
3.6 example
/** * Create the Aloha Repositories object. */ define( [ 'aloha', 'jquery' ], function ( Aloha, jQuery ) { 'use strict'; new ( Aloha.AbstractRepository.extend( { _constructor: function () { this._super( 'myRepository' ); }, /** * initialize the repository */ init: function () { }, /** * Searches a repository for repository items matching queryString if none found returns null. * The returned repository items must be an array of Aloha.Repository.Object * * @param {object} params object with properties * @param {function} callback this method must be called with all resulting repository items */ query: function ( p, callback ) { callback.call( this, [ { id: 1, name: 'My item', url: 'http://mydomain.com/myItem.html', type: 'text/html' } ]); }, /** * Returns all children of a given motherId. * * @param {object} params object with properties * @property {array} objectTypeFilter OPTIONAL Object types that will be returned. * @property {array} filter OPTIONAL Attributes that will be returned. * @property {string} inFolderId OPTIONAL his is a predicate function that tests whether or not a candidate object is a child-object of the folder object identified by the given inFolderId (objectId). * @property {array} orderBy OPTIONAL ex. [{lastModificationDate:’DESC’}, {name:’ASC’}] * @property {Integer} maxItems OPTIONAL number items to return as result * @property {Integer} skipCount OPTIONAL This is tricky in a merged multi repository scenario * @property {array} renditionFilter OPTIONAL Instead of termlist an array of kind or mimetype is expected. If null or array.length == 0 all renditions are returned. See http://docs.oasis-open.org/cmis/CMIS/v1.0/cd04/cmis-spec-v1.0.html#_Ref237323310 for renditionFilter * @param {function} callback this method must be called with all resulting repository items */ getChildren: function ( p, callback ) { callback.call( this, [ { id: 1, name: 'My item', url: 'http://mydomain.com/myItem.html', type: 'text/html' } ]); }, /** * Get the repositoryItem with given id * Callback: {Aloha.Repository.Object} item with given id * @param itemId {String} id of the repository item to fetch * @param callback {function} callback function */ getObjectById: function ( itemId, callback ) { callback.call( this, [ { id: 1, name: 'My item', url: 'http://mydomain.com/myItem.html', type: 'text/html' } ]); }, /** * Mark or modify an object as needed by that repository for handling, processing or identification. * Objects can be any DOM object as A, SPAN, ABBR, etc.. * (see http://dev.w3.org/html5/spec/elements.html#embedding-custom-non-visible-data) * @param obj jQuery object to make clean * @return void */ markObject: function (obj, repositoryItem) { obj.attr('data-myRepository-temporary-data').text( repositoryItem.name ); }, /** * Make the given jQuery object (representing an object marked as object of this type) * clean. All attributes needed for handling should be removed. * @param {jQuery} obj jQuery object to make clean * @return void */ makeClean: function ( obj ) { obj.removeAttr('data-myRepository-temporary-data'); }; }))(); });
4 Reccomandation of repository item attributes
The API and data layout is inspired by CMIS.
4.1 ObjectTypes
The object concept from CMIS is inconsistent and to complicated for Aloha Editors needs. So we changed to a much simpler model, which allows to implement CMIS, but is easier to use for developers. CMIS objects
There are 2 BaseTypes: document and folder. All other objectTypes may extend either document or folder. Extended Objects may not be extended any more.
4.2 Document
- id MUST
- repositoryId MUST
- name MUST
- baseType MUST (document|folder)
- type MUST
- parentId OPTIONAL
- renditions OPTIONAL
- localName OPTIONAL
- createdBy OPTIONAL
- creationDate OPTIONAL
- lastModifiedBy OPTIONAL
- lastModificationDate OPTIONAL
- length OPTIONAL
- mimeType OPTIONAL
- fileName OPTIONAL
- url OPTIONAL
4.3 Folder
- id MUST
- repositoryId MUST
- name MUST
- baseType MUST (document|folder)
- type MUST
- parentId MUST
- localName OPTIONAL
- createdBy OPTIONAL
- creationDate OPTIONAL
- lastModifiedBy OPTIONAL
- lastModificationDate OPTIONAL
- children OPTIONAL (array of child folders objects)
4.4 Rendition
- documentId ID identfies the rendition document (baseObjectType == document)
- url URL identifies the rendition stream.
- mimeType String The MIME type of the rendition stream.
- filename String The filename of the rendition stream
- length Integer (optional)The length of the rendition stream in bytes.
- name String (optional) Human readable information about the rendition.
- kind String A categorization String associated with the rendition.
- square – an image square 75×75
- thumbnail – a thumbnail version of the object
- small - 240 on longest side
- medium- 500 on longest side
- large – 1024 on longest side (only exists for very large original images)
- docx – Microsoft docx Version of the content
- lang_de – same content in german language
- lang_fr – same content in frensh language
- pdf – pdf version of the content
- height Integer (optional) Typically used for ‘image’ renditions (expressed as pixels). SHOULD be present if kind = cmis:thumbnail.
- width Integer (optional) Typically used for ‘image’ renditions (expressed as pixels). SHOULD be present if kind = cmis:thumbnail.
4.4.1 What are renditions, and why are they so useful?
A repository may implement renditions for any object that has “document” as its baseObjectType. A rendition is simply an alternative representation (rendering) of a given object. Any document may have any number of renditions. For example: A page document in a repositroy may be rendered in 3 different languages. Each of these 3 variations of that page can be served by the repository as a rendition of any of the other 2 translations that correspond with it. Each of these pages may be a stand-alone document in the repository as well. In fact, different renditions for a single document type will likely be different files which the repository will server back in response to a request for a specific rendition of a given object.
5 Configuring the Repository Manager
You may define a timeout (in milliseconds) when the Repository Manager should stop waiting for any repository implementation’s response.
var Aloha = { settings : { repositories: { timeout: 10000 // default 5000 (5 sec) } } };
If you want to figure out the optimal value for your timeout, you should test the server-side script for your repository to find its typical response times under heavy load. After determining the maximum time it takes to load a result you might want to add a buffer (e.g. 2–5 seconds) to allow for adapting to even higher server load.