Uno de los últimos hypes relacionados con los servicios de contenidos
documentales es el estándar CMIS. Pero qué es el CMIS? CMIS es una
especificación estándar para servicios de interoperabilidad de gestión
de contenidos cuyo momento actual es en cierto modo paralelo al previo
a la estandarización del lenguaje SQL. Las bases relacionales se
crearon a principios de los 70’s, pero los primeros esfuerzos sobre un
lenguaje estándar SQL no empezaron hasta mucho después. Una vez
aunados esos esfuerzos, los desarrolladores crearon aplicaciones que
podían atacar multiples back-ends relacionales. Pues el CMIS tiene el
potencial de hacer lo mismo para las aplicaciones de contenidos
(digamos gestores documentales) entendidas como un backend,
proporcionando un manera estándar de interactuar con el repositorio de
contenidos, independiendiente de la implementación del repositorio o
el lenguaje de programación del front-end. De esta manera, en vez de
filas y columnas, estaremos interactuando con contenidos
pseudo-estructurados, típicamente ficheros que se alojan en
estructuras jerárquicas de directorios. Es decir, se trata de una capa
que nos va a presentar un repositorio documental, proporcionando un
modelo datos (estándar) relacional para objetos de tipo documento, o
carpeta, a la cual vamos a acceder a través de querys SQL.
Numerosas empresas se han puesto en marcha en definir el
estándar y aunar esfuerzos como son los casos de IBM (Filenet), ECM
(Documentum), Oracle (UCM) o Microsoft (Sharepoint), y en el contexto
del software libre Alfresco, Nuxeo o KnowledgeTree. De este modo,
las últimas versiones de Alfresco y Nuxeo implementan CMIS 1.0.
En paralelo han aparecido un buen número de clientes CMIS,
componentes para CMSs como Joomla,
Drupal,
y también APIs de diferentes lenguajes de programación como Python o Ruby. Con el API de
Python para CMIS de Jeff Potts, se puede demostrar lo anterior
atacando al repositorio
público de CMIS de Nuxeo. Ya que esta semana nos estamos
certificando en Nuxeo, vamos a hacer el ejemplo en Nuxeo (En la
documentación de la librería y en los artículos, Jeff Potts lo hace
contra el repositorio de Alfresco).
Lo primero es instalar el módulo de cmislib (con easy_install
por ejemplo, sudo easy_install cmislib) y abrir después la consola de
python:
>>> from pprint import * >>> from cmislib.model import CmisClient, Repository >>> client = CmisClient('http://cmis.demo.nuxeo.org/nuxeo/site/cmis/repository', 'Administrator', 'Administrator') >>> repo = client.getDefaultRepository() >>> repo.getRepositoryId() u'default' >>> info = repo.getRepositoryInfo() >>> for k,v in info.items(): ... print "%s:%s" % (k,v) ... cmisVersionSupported:1.0 repositoryDescription:Repository default changesOnType:cmis:document changesIncomplete:false productVersion:5.3.2-SNAPSHOT rootFolderId:4fb1b8a1-6dfd-4da4-95b0-4ef41c27b920 latestChangeLogToken:None repositoryId:default repositoryName:default vendorName:Nuxeo productName:Nuxeo Repository
>>> someFolder = repo.getObjectByPath('default-domain/workspaces/demo-workspace') >>> someFolder.getTitle() u'demo-workspace' >>> someFolder.getProperties() >>> pprint(someFolder.getProperties()) {u'cmis:baseTypeId': 'cmis:folder', u'cmis:createdBy': u'Administrator', u'cmis:creationDate': datetime.datetime(2010, 1, 11, 12, 51, 23), u'cmis:lastModificationDate': datetime.datetime(2010, 1, 11, 12, 51, 23), u'cmis:lastModifiedBy': u'Administrator', u'cmis:name': u'demo-workspace', u'cmis:objectId': '5af586f4-6221-4ad5-8bc6-7c34d247bc2b', u'cmis:objectTypeId': 'Workspace', u'cmis:parentId': 'd3b45d33-9415-4796-bc90-74c9800b823e', u'cmis:path': u'/default-domain/workspaces/demo-workspace', u'dc:contributors': u'Administrator', u'dc:description': None, u'dc:subjects': None, u'dc:title': u'Demo Workspace', u'icon': u'/icons/workspace.gif', u'publish:sections': None, u'webc:moderationType': u'aposteriori', u'webc:name': u'Demo Workspace', u'webc:theme': u'sites', u'webc:themePage': u'workspace', u'webc:url': u'demo-workspace'} >>> someFolder = repo.getObjectByPath('default-domain/workspaces/demo-workspace') >>> newFolder = someFolder.createFolder('test-zylk') >>> pprint(newFolder.properties) {u'cmis:baseTypeId': 'cmis:folder', u'cmis:createdBy': u'Administrator', u'cmis:creationDate': datetime.datetime(2010, 4, 13, 14, 7, 32), u'cmis:lastModificationDate': datetime.datetime(2010, 4, 13, 14, 7, 32), u'cmis:lastModifiedBy': u'Administrator', u'cmis:name': u'test-zylk', u'cmis:objectId': 'ff8a7129-a962-4b3a-84f3-d205e36c758e', u'cmis:objectTypeId': 'cmis:folder', u'cmis:parentId': '5af586f4-6221-4ad5-8bc6-7c34d247bc2b', u'cmis:path': u'/default-domain/workspaces/demo-workspace/test-zylk', u'dc:contributors': u'Administrator', u'dc:subjects': None, u'dc:title': u'test-zylk', u'icon': u'/icons/folder.gif'}
>>> results = repo.query("SELECT * FROM cmis:folder WHERE dc:title='test-zylk'") >>> for result in results: ... print result.name ... test-zylk >>> someFile = open('LICENSE.txt', 'r') >>> someDoc = someFolder.createDocument('Zylk Document', contentFile=someFile) >>> children = someFolder.getChildren() >>> for child in children: ... print child.name ... test-zylk Zylk Document pictures
Todavía los servidores documentales no implementan todas la
funcionalidades en CMIS, y las API’s empiezan a tener buena parte de
las funcionalidades CRUD, lo cual de por si ya es un buen
comienzo.
Este artículo está basado en:
- http://www.ibm.com/developerworks/library/x-cmis1/index.html
- http://cmislib.googlecode.com/svn/trunk/src/doc/build/examples.html
Otros enlaces:
- http://ecmarchitect.com/archives/2009/12/18/1113