级别: 中级 潘 志华 (panzh@cn.ibm.com), 软件工程师, IBM 中国软件开发中心 何 辉剑 (hehuij@cn.ibm.com), 软件工程师, IBM
2007 年 8 月 23 日 作为新一代的文档协作平台,Lotus Quickr V8.0 提供了功能强大的文档管理功能,同时为用户提供了一套完备的文档管理 API 以供用户定制和扩展,即 Content Public API,其中包括 WebService API 和 REST API 两部分。本文将介绍文档 Content Public API 相关的数据模型、操作接口,并举例介绍 Content Public API 的使用方法。
本文将从以下几个方面来介绍 Quickr Content 的特性:
- Content Public API 在 Quickr 整套产品中的位置;
- Content Public API 的两大部分;
- Content Public API的数据模型;
- Content Public API 功能介绍;
- 客户端编程环境介绍;
- 编程模型,典型用户场景示例;
Content Public API 在 Quickr 整套产品中的位置
Content Public API 是 Quickr 整套产品对外提供的统一文档操作接口。Lotus Quickr 8.0 包含两套产品,Quickr for Domino 和 Quickr for Portal;尽管两者功能类似,但是实现却有很大不同。Quickr for Domino 后台是基于 Domino Server,其文档存储是基于 NSF 的文档结构。Quickr for Portal 后台是基于 IBM WebSphere Portal Server,其文档存储是基于 JSR-170(JCR:Java Content Repository)的文档模型。然而,尽管两者有着迥然不同的存储模型,但是两套产品对外有着共同的文档操作接口,就是 Content Public API。共同的文档操作接口为用户屏蔽了数据存储的异构性,实现了对异构数据的透明访问。除了 Quickr for Domino 和 Quickr for Portal 之外,FileNet 也将会集成到 Quickr 套件的后续版本中来,同样 FileNet 也将遵循 Content Public API 的定义,对外提供统一的文档操作接口。
作为 Lotus Quickr 的一大特性,Lotus Quickr 为客户提供了一系列功能强大的连接器(Connectors),这些连接器可以以插件的形式被安装到常用的桌面应用软件中,实现基于这些软件对 Quickr 服务器的中文档数据的访问。Quickr 8.0 中提供了如下的连接器:Explorer 连接器,Sametime 连接器,Notes 连接器,Office 连接器;用户可以在 Quickr 首页中找到并下载连接器的安装套件。值得一提的是,这些连接器是基于 Quickr 的 Content Public API 来实现的,用户通过使用连接器就可以体会 Public API 提供的强大功能。除此之外,IBM 也鼓励商业伙伴或者客户基于 Content Public API 来开发更多的,与自己应用相集成的 Connector。在 Quickr 8.0 中,Content Public API 包括 WebService API 和 REST API 两部分,后续版本将提供更多的 API。
图 1. Content Public API 在 Quickr 中的位置
Content Public API 的两大部分
Lotus Quickr 8.0 提供了两部分的 Content Public API:WebService API 和 REST API。两套 API 是相互独立的两部分,两套 API 都是基于目前流行的开放标准。
WebService 基于 W3 定义的 WSDL(WebService Definition Language)和 SOAP(Simple Object Access Protocol)协议。Quickr WebService 对外提供一个 WSDL 文档。WSDL 是一个自描述的 XML 文档,它包含了对 Quickr WebService 模型、接口、操作、消息的定义和描述。基于 WSDL,客户可以自己产生不同语言(VB, C#, C++, Java 等)的客户端来使用 Quickr WebService。Quickr 8.0 WebService 的 WSDL 文档中定义了三个服务(Port Types): ContentService,DocumentService,LibraryService。
相对于 WebService,REST 是一个更加轻量级的架构。相比面向活动的 SOAP,资源是 REST 关注的中心。REST 适合于面向资源的服务,服务提供方维护一组资源,并公开一组基本操作来执行以下任务:检索资源、修改资源、创建新资源、删除资源。Quickr 中的 REST API 是完全遵循开放的 IETF 标准(ATOM)。ATOM 是用于发布条目(单个主题或者项)和提要(主题或项的集合)的文档格式标准。ATOM 文档的传输采用的开发的协议 APP(Atom Publish Protocol)。Quickr REST Service 提供针对 Quickr 中的文档库、文档、文件夹、视图、草稿、评论等资源的 Feed 发布、获取、添加、修改、删除等操作。
Content Public API 的数据模型
WebService 数据模型
尽管 Quickr 的两套产品 Quickr for Portal 和 Quickr for Domino 后台分别基于不同的数据存储格式,但归根到底 Quickr Content Public API 是以 Quickr for Portal 的 JCR 结构为基础建立起来的。下面是 Content Public API 数据模型在 Quickr for Portal 中的数据模型关系。
图 2. Quickr for Portal 文档存储结构
- JSR170(JCR,Java Content Repository)被用来作为与所有内容对象交互的主要 API。
- IBM Content Model 定义了内容管理应用程序共有的元素(elements)、元数据(metadata)、集成模式(aggression patterns),Content Model 中的条目被分为两类 base type 和 metadata type。
- IBM Collaborative Content Model 则扩展了 IBM Content Model 来表示 Quickr 中文档管理相关的行为。Collaborative Model 中定义的规则,并没有限制或修改 Content Model 中的行为。
文档库(ClbLibrary)是 Content API 数据模型的基础。在 Quickr for Portal 中,文档库是一个树形结构。对应到 JCR 存储结构,一个文档库就是 JCR 树中的一棵子树。一个文档库包含三个固定容器:文档模板容器(ClbDocumentTemplateContainer),属性表容器(ClbPropertySheetTypeContainer),文档类型容器(ClbDocumentTypeContainer)。这些容器分别用来存储文档库中文件可能会使用到的文档模板、属性表、文档类型。容器中的元素为文档库一级共享的元素,同时文档库也可以共享父文档库容器中的元素。
文档库下面,用户就可以按照自己的需求建立文件和文件夹。在这里,文档有草稿的概念,草稿(ClbDraft)和文档(ClbDocument)是一对一的关系,一个文档有且仅有一个草稿。当文档被检出时候,对应的文档被锁住,产生草稿。当文档被检入时,草稿中的修改被合并到文档中,草稿被删除。
图 3. Quickr for Portal 文档库结构
REST Feed 文档格式
由于 REST 是面向资源的服务。Quickr 中的所有文档库、文档、草稿、文件夹、视图、评论都将对应一个唯一的 URL 来唯一标示。所有的资源的相关操作,都是通过这个唯一标识的 URL 来进行的。同时对于每个资源也存在另外一个 URL,它的作用是用来将该资源以 Feed 的形式发布出来以供 Feeds Reader 订阅。
表 1. REST Feed 文档格式
| 资源类型 | 实体 URL | Feed URL |
|---|
| 文档库 | http://主机名/dm/atom/library/文档库ID/entry | http://主机名/dm/atom/library/文档库ID/feed |
|---|
| 文档 | http://主机名/dm/atom/library/文档库ID/document/文档ID/entry | http://主机名/dm/atom/library/文档库ID/document/文档ID/feed |
|---|
| 草稿 | http://主机名/dm/atom/library/文档库ID/draft/草稿ID/entry | http://主机名/dm/atom/library/文档库ID/draft/草稿ID/feed |
|---|
| 文件夹 | http://主机名/dm/atom/library/文档库ID/folder/文件夹ID/entry | http://主机名/dm/atom/library/文档库ID/folder/文件夹ID/feed |
|---|
| 视图 | http://主机名/dm/atom/library/文档库ID/view/视图ID/entry | http://主机名/dm/atom/library/文档库ID/view/视图ID/feed |
|---|
| 评论 | http://主机名/dm/atom/library/文档库ID/comment/评论ID/entry | http://主机名/dm/atom/library/文档库ID/comment/评论ID/feed |
|---|
而 Quickr Server 上的所有文档库的 Feed URL 可以通过 http://主机名/dm/atom/introspection 获得。清单 1 中展示了一个 Lotus Quickr 文档被发布的 ATOM 文档格式。
清单 1. Lotus Quickr 文档被发布成 ATOM 文档格式
<service>
<workspace>
<atom:title type="text">何辉剑本地资料库</atom:title>
−<collection
<!-该文档库Feed URL,a3182d0044b752f5b3c0bb46988534a9为该文档ID-->
href="http://quickr.tap.ibm.com/dm/atom/library/a3182d0044b752f5b3c0bb46988534a9/feed">
<atom:title type="text">UAT Document Library</atom:title>
<accept>application/*,image/*,*/*</accept>
</collection>
−</workspace>
<workspace>
<atom:title type="text">何辉剑图片库</atom:title>
−<collection href="http://quickr.tap.ibm.com/dm/atom/library/
a3182d0044b752f5b3c0bb46988534a9/feed">
<atom:title type="text">UAT Document Library</atom:title>
<accept>application/*,image/*,*/*</accept>
</collection>
−</workspace>
</service>
|
Content Public API 功能介绍
从功能来讲,Quickr WebService API 和 Quickr REST API 两部分功能有所交叉,但侧重点不同。下表列出了两套 API 针对数据对象分别可以进行哪些 CRUD(Create、Retrieve、Update、Delete)操作。
表 2. Content Public API 功能对比
| Model Type | REST | WebService |
|---|
| ClbComment | CRUD | NONE |
|---|
| ClbDocument | CRUD | CRUD |
|---|
| ClbDocumentType | NONE | R |
|---|
| ClbDraft | CRUD | CRUD |
|---|
| ClbFolder | CRUD | CRUD |
|---|
| ClbLibrary | NONE | NONE |
|---|
| ClbPropertySheet | NONE | CRUD |
|---|
| ClbPropertySheetType | NONE | R |
|---|
| ClbViewTemplate | NONE | R |
|---|
通过 Content API 可以获得文档库的根节点,以及访问用户具有权限的所有文档库的列表。在 Quickr 中,是基于角色来进行用户管理的,其中预定义了四种基本的角色:管理者、编辑者、参与者、阅读者;除此之外,用户也可以根据自己的应用需求自定义角色。如果用户对某文档库拥有读(Read)以上的权限,那么就可以通过 API 能获得该文档库。关于用户的登陆,目前 Quickr 8.0 for Domino 已经支持匿名访问,而 Quickr 8.0 for Portal 还不支持匿名访问,将会在后续版本支持。
在 Quickr 的图形界面上有空间(Place)的概念,用户可以根据需求来创建团队空间。一个空间下面有一个或者多个文档库。然而在 API 的角度,空间是透明的。API 可以获得文档库,却无法知道该文档库属于那个空间。
APP 协议是一个轻量级的 Web 资源发布和编辑协议。由于 APP 协议本身更关注于文档的同步,所以 REST API 对文档附件的操作更有优势。由于性能的原因,WebService API 不支持对文档附件的上传和下载操作。目前对文档附件的操作只能通过 REST API 实现,由于底层 ClbComment 也是作为附件来存储的,所以对 Comment 的操作也只能通过 REST API 实现。
相比文档附件的操作,WebService 对文档相关属性的操作更加完备。对于 REST API 而言,属性对象 ClbDocumentType、ClbPropertySheetType、ClbViewTemplate 是透明的。对属性对象的操作只能通过 WebService API 来实现。
客户端编程环境介绍:
WebService 客户端编程环境
WebService 是一个开放的架构,其中主要的协议是 WSDL 和 SOAP。基于 WSDL,客户可以自己产生任何支持 WebService 的语言的客户端,并通过 SOAP 协议来调用 Quickr WebService。下面将介绍如何生成 Java 客户端,以及如何使用 Java 客户端来访问 WebService 接口。
Quickr WebService 的 WSDL 服务描述文件包含了模型、接口、操作、消息的定义和描述。Quickr WebService 的 WSDL 可以简单的通过以下 URL 访问 Quickr Server 即可获得:
http://<server>:<port>/dm/services/ContentService?wsdl
|
Quickr 8.0 WebService 的 WSDL 版本号是 8.0.0,客户端访问时必须输入版本号,目前 Quickr WebService 只支持当前版本客户端的访问。WSDL 定义了三个服务(Port Types):ContentService、DocumentService、LibraryService,以下分别是三个服务的服务访问点。
http://<server>:<port>/dm/services/ContentService
http://<server>:<port>/dm/services/DocumentService
http://<server>:<port>/dm/services/LibraryService
|
有了 WSDL 描述文件,用户可以使用 WSDL2JAVA 工具生成用来访问 Quickr WebService 的 Java 客户端 Stub。WSDL2JAVA 工具可以在 Quickr 安装目录下找到:
[Quickr Root]\AppServer\bin\WSDL2Java.bat
Quickr for Portal 8.0 不支持匿名用户的访问。因此要通过 API 访问 Quickr WebService,就首先要通过 PAC(Portal Access Control)的认证。因此对于基于 WSDL 生成的客户端 Stub,还需要的设置来实现基于 HTTP Base Authentication 的访问方式。
如果 server 端配置了 SSL(Security Socket Layer),那么需要配置 WebService 客户端以实现基于 HTTPs 的访问,具体配置方法请参阅相关文档。
REST 客户端环境建立
由于 REST 是一种松耦合的 Web 框架。简单的说 REST 就是通过 HTTP 协议来提供 XML 数据。而 Quickr 中传输的 XML 格式是完全基于 ATOM 格式的。因此使用 Apache Abdera 来构造客户端变成环境就成为了最佳选择。
Apache Abdera 是实现对 ATOM 格式解析,发布(APP, Atom Publishing Protocol)的 Java 类库,IBM 最早参与并提供了代码。采用了 Abdera 后,客户端不需要自己去解析 ATOM XML,这就大大减少了客户端的代码。当然我们同样可以使用其它的 HTTP client 来实现,如 Apache common client 等。下面以使用 Abdera 来获取一个文档的名字为例。说明使用 Abdera 带来的好处。
清单 2. 一个文档的实体 ATOM XML 文件片断
<?xml version="1.0" encoding="UTF-8" ?>
- <entry xml:lang="en" xml:base="https://quickr.tap.ibm.com/dm/atom/library/
cab5760045c0dc128e38be64bc21f362/" xmlns="http://www.w3.org/2005/Atom"
xmlns:td="urn:ibm.com/td">
<id>urn:lsid:ibm.com:td:7b56a380461dd06c9c179cf98407c03f</id>
<link href="https://quickr.tap.ibm.com/dm/atom/library/cab5760045c0dc128e38be64bc21f362/
document/7b56a380461dd06c9c179cf98407c03f/entry" rel="self" />
<link href="https://quickr.tap.ibm.com/lotus/mypoc?uri=dm:
7b56a380461dd06c9c179cf98407c03f&verb=view" rel="alternate" />
<link href="https://quickr.tap.ibm.com/dm/atom/library/cab5760045c0dc128e38be64bc21f362/
document/7b56a380461dd06c9c179cf98407c03f/entry" rel="edit" />
<link href="https://quickr.tap.ibm.com/dm/atom/library/cab5760045c0dc128e38be64bc21f362/
document/7b56a380461dd06c9c179cf98407c03f/media" rel="edit-media" />
<link href="https://quickr.tap.ibm.com/dm/atom/library/cab5760045c0dc128e38be64bc21f362/
document/7b56a380461dd06c9c179cf98407c03f/media" rel="enclosure" type="application/doc"
title="何辉剑的Abdera学习笔记.doc" hreflang="en" length="716621" />
<category term="document" scheme="tag:ibm.com,2006:td/type" label="document" />
………
</entry>
|
清单 3. 使用 Abdera 获得文档名称
ClientResponse response = client.get(“https://quickr.tap.ibm.com/dm/atom/library/
cab5760045c0dc128e38be64bc21f362/document/7b56a380461dd06c9c179cf98407c03f/entry”);
Entry entry=(Entry)response.getDocument().getRoot();
String title=entry.getTitle();
|
如果使用 Apache common client 来实现,则需要通过代码来解析上面的 ATOM XML 文件。获取 title="何辉剑的Abdera学习笔记.doc" 中的值。显然,通过使用 Abdera Client,可以将开发人员从繁琐的 ATOM XML 文档解析中解放出来。
编程模型,典型用户场景示例
本节将介绍 Quickr Content API 的使用方法,并接合几个典型的用户场景给出示例代码。
文档的创建和修改
文档的创建和修改是最基本的功能,下面是使用 Content API 创建一个文档的最基本的步骤。
- 获取 library:
LibraryService.getBusinessComponents()
- 创建 folder:
DocumentService.createFolder()
- 创建 draft:
DocumentService.createDraft()
- 检入 draft:
DocumentService.checkinDocument()
清单 4. 文档创建和修改
//获得所有文档库列表;
libraryService.getBusinessComponents(null,null,null);
ClbLibrariesResponse response = libraryService.getBusinessComponents(
null, null, new ClbCategoryType[] { ClbCategoryType.DocumentManager });
//选择到要操作的文档库;
ClbLibrary lib = response.getLibraries()[0];
//在文档库下创建文件夹;;
ClbFolder folder = new ClbFolder();
String folderPath = lib.getPath()+"/"+"myfolder";
folder.setPath(folderPath);
folder.setTitle("my title");
//设置文件夹其他属性, WSDL 描述了哪些属性可以被设置的.
ClbFolderResponse folderResponse = documentService.createFolder(folder);
//在文件夹下创建文档,首先是创建草稿;
String docPath = folderPath+"/"+"abc.doc";
ClbDraft draft = new ClbDraft();
//设置文件夹其他属性, WSDL 描述了哪些属性可以被设置的.
ClbDraftResponse docResponse = documentService.createDraft(null, docPath, draft);
//检入草稿;
ClbDocument doc = new ClbDocument();
doc.setPath(docPath);
ClbCheckinResponse checkInresponse = documentService.checkinDocument(doc);
|
文档的审批
文档的审批是 Quickr 中的一个新功能。如果要想实现文档的审批,需要对文档的 DocumentType 进行设置,这个功能只能在界面上进行,文档的审批可以并行或者串行进行。
- 从 GUI 界面上创建打开了文档审批功能的 DocumentType
- 创建 draft:
DocumentService.createDraft()
- 提交 draft:
DocumentService.subbmitDraft()
- 审批 draft:
DocumentService.approveDraft()
- 拒绝 draft:
DocumentService.rejectDraft()
清单 5. 文档的创建和审批
//创建一个新的本纪文档类型 DocumentType,并打开文档审批。
//获得所有本地文档类型。
ClbDocumentTypesResponse typeResponse = documentService.
getDocumentTypes(getLibId(), null, null ,ClbDocTypeOption.LibraryScope);
ClbDocumentType[] types = typeResponse.getDocumentTypes();
//选择打开文档审批的文档类型。
ClbDocumentType type = types[0];
//创建新草稿,选择设置了文档审批的文档类型。
String docPath = "..."+"/"+"abc.xls";
ClbDraft draft = new ClbDraft();
draft.setDocumentType(type);
//设置文件夹其他属性, WSDL 描述了哪些属性可以被设置的.
ClbDraftResponse draftResponse = documentService.createDraft(null, docPath, draft);
draft = draftResponse.getDraft();
//提交草稿
ClbResponse response = documentService.submitDraft(draft.getId(),null);
//审批用户获得等待被审批的草稿
ClbDraftsResponse draftsResponse = wasDocumentService.
getApproveDrafts("folderURL",null);
ClbDraft[] drafts = draftsResponse.getDrafts();
//批准草稿
wasDocumentService.approveDraft(drafts[0].getId(),null);
//拒绝草稿
wasDocumentService.rejectDraft(drafts[1].getId(),null);
|
文档媒体(media)的操作
正如上文所述,由于性能方面的考虑,Quickr WebService API 并没有提供相应的接口来实现附件的上传和下载。因此对于附件的上传和下载就是 REST API 的特点,在进行上传附件操作的时候,可以通过 Quickr 提供四个参数用来控制文档上传后的各种状态。如通过设置 Lock=true 来用当前用户锁定该文档,通过设置 replace=true 来强制替换同上传文档同名的文档,通过设置 submit=true 来提交该文档到审批流程,通过 draft=true,生成草稿,另外还可以通过设置参数 doctype=某文档类型 ID 来指定该文档的文档类型。这些参数在对文档进行修改时同样有效。下面以创建并提交一个文档到审批流程为例:
清单 6. 上传文档到文档库并提交审批
InputStream is = this.getClass().getClassLoader().getResourceAsStream(“手机.doc”);
RequestOptions options = new RequestOptions();
options.setHeader("Slug", “某某手机资料文档”);
options.setContentType(“application/doc”);
InputStreamRequestEntity entity = new InputStreamRequestEntity(is);
String documentTypeID= "_quickr_contentRoot_msword_doctype_100000";//该文档类型设置了文档审批流程
response = client.post(“https://quickr.tap.ibm.com/dm/atom/
library/cab5760045c0dc128e38be64bc21f362/feed”+ "?doctype=" + documentTypeID+”&
submit=true”, entity, options);
|
对文档添加删除注释
由于在 Quickr 中评论是以附件的方式来存储的。因此对评论的操作也是 REST API 的特点之一。下面代码实现提交 HTML 格式评论到一个文档。
清单 7. 将 HTML 的内容作为文档的评论
URL file = this.getClass().getClassLoader().getResource(“mycomment.html”);
URI uri = new URI(file.getProtocol(), file.getHost(), file.getPath(), null);
long length = new File(uri).length();
RequestOptions options = new RequestOptions();
options.setHeader("Slug", “我的评论”);
options.setContentType(“TEXT/HTML”);
InputStreamRequestEntity entity = new InputStreamRequestEntity(is);
response =client.post(“https://quickr.tap.ibm.com/dm/atom/
library/cab5760045c0dc128e38be64bc21f362/
document/7b56a380461dd06c9c179cf98407c03f/entry”, entity, options);
|
总结
本文介绍了 Quickr 8.0 的 Public Content API。目前只有 WebService 和 REST 两部分,后续版本将不断扩充两部分的功能,而且将会有更多的 Java API 推出。Public Content API 为用户开发与自己应用集成的程序提供了方便,WebService 和 REST 两部分特点不同,功能互补。另外由于 Quickr REST API 是基于 ATOM 开发标准,这样的轻量级的 Web 架构为 Mashup 提供了重要的保障。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Quickr WebService WSDL | ContentService.wsdl | 203 KB | HTTP |
|---|
参考资料 学习
讨论
作者简介  | 
|  | 潘志华,在 IBM 中国软件开发实验室 Lotus 开发中心工作,目前从事 IBM Lotus Quickr 的 API 测试工作。对软件测试和开发、协同软件有着丰富的经验。 |
 | 
|  | 何辉剑,现在 IBM 中国软件开发实验室 Lotus 开发中心工作,目前从事 Lotus Quickr 的开发工作。对 Web 2.0 相关技术和协同软件有丰富的经验。 |
对本文的评价
|