IBM® Lotus® Quickr™ content libraries can help you easily organize and share content for your projects, with your teams, or for yourself. You can set up libraries for your documents so that your teams can easily share and collaborate with check-in and check-out, version control, and other tools to help manage content. Complex and powerful workflow also simplifies working with content.
Individual content operations between different Lotus Quickr content libraries are not easy, though. In this example, content from different Lotus Quickr libraries interacts with simple Lotus Quickr REST services in the Library Linker tool. Library linker is based on the latest Dojo 1.0 framework. Contents are listed in two Dojo grid widgets, and you can work with two libraries on the same page.
You should have a good understanding of IBM Lotus Quickr REST services and some knowledge of Dojo toolkit and HTML development. See the developerWorks® article, "Introducing IBM Lotus Quickr REST services," for more information about Lotus Quickr REST services. See the Dojo Web site for more information about Dojo.
About Lotus Quickr Library Linker
Lotus Quickr manages your organization’s contents with a library approach. Users, though, inevitably need to work with contents in different libraries; for example, they might want to copy documents from one library to another. The current version of Lotus Quickr does not support this kind of use with a browser. Lotus Quickr Library Linker is designed to help us in this case.
Figure 1 shows the user interface (UI) of Lotus Quickr library linker.
Figure 1. Lotus Quickr library linker
The contents of two Lotus Quickr libraries are listed after the user clicks the Get Contents buttons. The contents contain both folders and documents in a library. The two libraries can be on the same server, or they can be on different servers. You can copy the selected contents in the source library to the target library by clicking the >> button or the << button. Detailed implementation steps for installing and using Lotus Quickr library linker follow.
Get content from two different libraries
In this case, we need to get the contents to refresh the table without refreshing the whole page. This requirement can be satisfied by calling an Ajax request. Currently there are too many implementations to support Ajax, such as Bindows, BackBase, Dojo, Open Rico, Tibet, and others. In this case, we choose Dojo as our Web framework because Dojo is an open source framework that is based on JavaScript™ and that provides many ready-made widgets.
Build the grid table for the UI display
A grid table, which is a widget in Dojo1.0, provides a convenient way to list all contents, to sort the contents according to the columns, and to collect the user’s selections. Add this grid table in your HTML page as shown in listing 1.
Listing 1. Code snippet to define the grid table in the HTML file
<div style="border:grey solid 1px;" id="gridLeft" dojoType="dojox.Grid" structure="layout" model="modelLeft" autoHeight="true"> </div> |
In listing 1, the variable structure is an object to display the table’s layout, such as the column’s name and style. Listing 2 shows the code that defines the variable structure.
Listing 2. Code snippet to define the variable structure
var view = {
cells: [[
{name: 'Select', width: 5, headerStyles: 'padding-bottom: 2px;',
formatter: format4Select, styles: 'padding: 3px; text-align: center;'},
{name: 'Category', width: 5, headerStyles: 'padding-bottom: 2px;',
formatter: format4Category, styles: 'padding: 3px; text-align: center;'},
{name: 'Title', width: 15, headerStyles: 'padding-bottom: 2px;',
styles: 'padding: 3px;font-weight:bold;'},
{name: 'Link', width: 100, headerStyles: 'padding-bottom: 2px;',
styles: 'text-align: left; padding: 3px;'}
]]};
// a grid structure is an array of views.
var layout = [ view ];
|
You use the variable model to maintain the data to be displayed. See listing 3.
Listing 3. Code snippet to define the variable model
var data = [[“0”, “folder”, “test1”, “”], [“0”, “document”, “test2”, “”]]; var modelLeft = new dojox.grid.data.table(null, data); |
Get the contents from the library
When the user clicks the button labeled Get Contents, the Lotus Quickr library feeds REST service is called through an Ajax mechanism to get all the contents from the library. The response takes the form of Atom. Lotus Quickr has an internal Atom parser based on the Dojo DOM and Atom formats. It can also be parsed with the JavaScript DOM. The calling method can look like the code shown in listing 4.
Listing 4. Getting contents from library with the Atom library
getDataFromServer: function(url,user,pw,callback)
{
var atomIO = new ibm_atom.io.atom.AtomIO();
//Here we wrapped the Atom parser as AtomIO with Javascript DOM.
atomIO.user = user;
atomIO.password = pw;
//get content from server
atomIO.getFeed(url, feedHandler, errorHandler);
data = new Array();
//The feedHandler function will be called on a successful response.
function feedHandler(feed, domNode)
{
if (feed != null)
{
var entries = feed.entries;
if (entries != null)
{
for (var i = 0; i < entries.length; i++)
{
var entry = entries[i];
var newArray = new Array();
newArray[0] = "0";
newArray[1] = entry.categories[0].term;
newArray[2] = entry.title.value;
newArray[3] = getCurrentLink(entry);
newArray[4] = entry.id;
data[i] = newArray;
}
}
//callback to refresh UI
if (callback)
{
eval(callback).call(null, this);
}
}
}
//The errorHandler function will be called on an unsuccessful response.
function errorHandler(error, ioArgs)
{
alert(error.message);
}
}
|
The following list introduces the code of listing 4:
- url. The feed’s URL to denote content in the Lotus Quickr server.
- user. User name to access the content.
- pw. Password to access the content.
- callback. Callback method to refresh the UI when the user gets a successful response.
- Ibm_atom.io.atom.AtomIO. Object provided in the IBM Atom Library package that provides a series of methods to support Atom requests and responses.
Dojo supports the Ajax request itself so that you can get Lotus Quickr library contents through the Dojo XmlHttpRequest Method directly as shown in listing 5.
Listing 5. Getting contents from the library through the Dojo XmlHttpRequest method
function getFeed(feedUrl, user, pw)
{
dojo.xhrGet( {
// The following URL must match that used to test the server.
url: feedUrl,
user: user,
password: pw,
handleAs: "xml",
preventCache: true, //do not user browser's cache
timeout: 5000, // Time in milliseconds
// The LOAD function will be called on a successful response.
load: function(response, ioArgs) {
alert("Success response is " + response);
return response;
},
// The ERROR function will be called in an error case.
error: function(response, ioArgs) {
console.error("HTTP status code: ", ioArgs.xhr.status);
return response;
}
});
}
|
After getting the contents by parsing the Atom XML response through the Atom Library or Dojo DOM, construct the content data in an array and refresh the grid table with this data. See listing 6.
Listing 6. Callback method used to refresh the UI
function callback(data)
{
gridLeft.model.clearData();
//data is an Array.
if(data != null)
{
gridLeft.model.setData(data);
gridLeft.refresh();
//clear the user's selections.
gridLeft.selection.clear();
}
}
|
With the same process, you can get the other library's contents and list them in the Grid table.
Save contents from source to target
Lotus Quickr provides a suite for REST services to work with documents in a Lotus Quickr library doing such functions creating, editing, and deleting documents. More information can be found in the developerWorks Lotus article, "Introducing IBM Lotus Quickr REST services."
In Lotus Quickr library linker, both of the libraries on the page can be seen as either a source or a target library. First the user selects content by clicking the checkboxes. Then, the user clicks the << button or the >> button to copy the contents from one library to another.
These contents can be folders or documents. The code flow should be as follows:
- Get the entry/feed URL of the selected contents.
- Perform a GET request with the URL in step 1 on the source library to get the metadata or attachment (if the content type is a document) of the content.
- Organize the POST entry Atom XML according to step 2.
- Perform a POST request on the target library to publish the new content.
There are two types of content: documents and folders. Here, we describe the detailed steps to handle these two content types.
In Lotus Quickr, the document entry contains the metadata of the document, and the URL pattern to get a document entry is as follows:
<protocol>://<host>:<port>/dm/atom/library/<library uuid>/document/
<document uuid>/entry
We can get the link to the document’s attachment from the document entry with rel="edit-media". The link should look like this:
<link href="http://lwptsthink10.cn.ibm.com/dm/atom/library/
03557c004823e048951db5c52d6a3bea/document/757104804838726f964ab7c52d6a3bea/media"
rel="edit-media" />
To save a document, you need to save not only the metadata that includes the name, document type, and so on but also the attachment. In Lotus Quickr, the attachment of a document is transformed as a binary stream; we can get the binary stream with the media URL, and then we can post it to the target library with the Lotus Quickr document POST service as shown in listing 7. Listing 8 shows the code used to get an attachment from a document.
Listing 7. Document POST service
POST /library/08ca5f0044ab2d6a858eed71ca20d4cf/folder /4e05cb0044f7e4f1937e932188721110/entry HTTP/1.1 Host: example.com Content-Type: application/msword Content-Length: …… Authorization: Basic …… Slug: My document.doc Binary of the document goes in the request body |
Listing 8. Getting attachment from a document
function getDocHandlerL2R(entry, domNodes)
{
var docTitle = entry.title.value;
var entryLinks = entry.links;
var docMedia = getMediaLink(entryLinks);
getDocumentAttachment(docTitle, docMedia, "Right");
}
function getDocumentAttachment(docTitle, docUrl, position) {
dojo.xhrGet({
url: docUrl,
handleAs: "text",
load: function(responseText)
{
console.log("Get Document Attachment Successfully!");
postDocumentAttachment(responseText, position, docTitle);
},
error: function(response)
{
console.log("Get Document Attachment Fail!");
}
});
}
function getMediaLink(links)
{
if(links === null || links.length === 0){
return null;
}
for(x in links){
if(links[x].rel && links[x].rel == "edit-media"){
return links[x].href;
}
}
return null;
}
|
In listing 8, we get the title of document and the URL of its attachment from the document entry, and the URL can be used to get the binary stream through dojo.xhrGet function. See listing 9 for the code that posts the attachment to the target library.
Listing 9. Posting the attachment to the target library
function postDocumentAttachment(data, position, docTitle)
{
dojo.rawXhrPost({
url: feedUrl = dojo.byId("libFeed" + position).value,
postData: data,
handleAs: "text",
contentType: "text/plain",
encoding: "utf-8",
headers: {"Slug": docTitle},
load: function(responseText)
{
console.log("Post Document Attachment Successfully!");
getContent(position);
},
error: function(response){
console.log("Post Document Attachment Error!");
}
});
}
|
To save a folder, you need to create a new folder in the target library and copy all the subdocuments and subfolders into it. Here, we describe how to create a new folder in the library. To save an entire folder and its contents, you need to traverse all the content of the source folder.
You can find the metadata of a folder in its folder entry. The URL pattern of a folder feed should look like this:
<protocol>://<host>:<port>/dm/atom/library/<library uuid>/folder/
<folder uuid>/entry
See listings 10 and 11 for code for the folder entry Atom XML and the code for saving a folder to a target library.
Listing 10. Code snippet for folder entry Atom XML
<entry xml:base=”http://example.com/dm/atom/library/5d06ab0044ed8129bd5ebd4caeec5df1/”
xmlns=”http://www.w3.org/2005/Atom”>
<id>urn:lsid:ibm.com:td:a054ab0044f7e2a9936d932188721110</id>
<link href=”folder/a054ab0044f7e2a9936d932188721110/entry” rel=”self”/>
<link href=”http://example.com/wps/mypoc?uri=
dm:a054ab0044f7e2a9936d932188721110&verb=view” rel=”alternate”/>
<link href=”folder/a054ab0044f7e2a9936d932188721110/entry” rel=”edit”/>
<category term=”folder” scheme=”tag:ibm.com,2006:td/type” label=”folder”/>
<author>
<uri>uid=jsmith,ou=example,o=organization</uri>
<name>John Smith</name>
<email>jsmith@example.com</email>
</author>
<title type=”text”>My Folder</title>
<published>2007-04-13T22:16:42.734Z</published>
<updated>2007-04-13T22:16:42.734Z</updated>
<!-- User modifiable creation date -->
<td:created>2007-05-13T19:03:25.500Z</td:created>
<!-- User modifiable modification date -->
<td:modified>2007-05-13T19:03:25.500Z</td:modified>
<!-- Last modified person -->
<td:modifier>
<td:uri> uid=jdoe,ou=example,o=organization</td:uri>
<td:name>John Doe</td:name>
<td:email>jdoe@example.com </td:email>
</td:modifier>
<summary type=”text”>My Folder description</summary>
<content type=”application/atom+xml”
src=”folder/a054ab0044f7e2a9936d932188721110/feed”/>
</entry>
|
Listing 11. Code snippet for saving folder to target library
function folderHandlerR2L(feed, domNodes)
{
var folderTitle = feed.title.value;
//create a new folder
createNewFolder(folderTitle, "Left");
}
//create a new folder
function createNewFolder(folderTitle, position)
{
//organize the new folder entry for creating operation
var folderEntry = folderEntryHeader.concat(folderTitle, folderEntryEnd);
//add the new folder to another library
postNewFolder(folderEntry, position);
}
//add the new folder to target library
function postNewFolder(entry, position)
{
dojo.rawXhrPost({
url: feedUrl = dojo.byId("libFeedTarget" + position).value,
//This URL is the feed url of the target library/folder.
postData: entry,
contentType: "application/atom+xml",
headers: {"Slug": "Folder Name"},
load: function(responseText){
console.log("create a new folder successfully!");
getContent(position);
},
error: function(){
console.log("Get Folder Feed Fail!");
}
});
}
|
In this document, we showed you how to operate your Lotus Quickr library content with Lotus Quickr REST services based on Dojo. As a content management and collaboration platform, Lotus Quickr REST services offer an easy way for your organization to extend Lotus Quickr capability and perform mashups with your existing system.
| Name | Size | Download method |
|---|---|---|
| QuickrLibraryLinker.zip | 56.2KB | HTTP |
Information about download methods
Learn
-
Read the developerWorks Lotus article, "Introducing IBM Lotus Quickr REST services."
-
Read the developerWorks Lotus article, "IBM Lotus Quickr: Enhance team productivity with social computing."
-
Refer to the Lotus Quickr Developer's Guide.
-
Refer to the developerWorks Lotus Quickr documentation page.
-
Refer to the Dojo Web site.
Get products and technologies
-
Download a free trial version of IBM Lotus Quickr 8.0.
Discuss
- Participate in the discussion forum.
-
Particpate in the developerWorks Lotus team blog.
Hui Jian He (Jeff) is a Software Engineer at IBM working with the Lotus Quickr team in the China Software Development Lab in Beijing, You can reach Jeff at hehuij@cn.ibm.com
Qin Jun (Alice) is a Software Engineer at IBM working with the Lotus Quickr team in the China Software Development Lab in Beijing, You can reach Alice at qinjun@cn.ibm.com
Tan Tao (Kevin) is a Software Engineer at IBM working with the Lotus Quickr team in the China Software Development Lab in Beijing, You can reach Kevin at taoyan@cn.ibm.com.
Comments (Undergoing maintenance)





