Skip to main content

skip to main content

developerWorks  >  Lotus  >

IBM Lotus Quickr library linker: Content interoperations between Lotus Quickr libraries based on Dojo and Lotus Quickr REST services

developerWorks
Document options

Document options requiring JavaScript are not displayed

Discuss

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Hui Jian (Jeff) Je (hehuij@cn.ibm.com), Software Engineer, IBM
Qin (Alice) Jun (qinjun@cn.ibm.com), Software Engineer, IBM
Yan (Kevin) Tao (taoyan@cn.ibm.com), Software Engineer, IBM
Chen Yan (cheny@cn.ibm.com), Advisory Software Engineer, IBM
Bruce Roberts (robertsb@us.ibm.com), Architect, IBM

29 Apr 2008

Learn how to operate your Lotus Quickr library content with Lotus Quickr REST services based on Dojo. In this example described in this article, content from different Lotus Quickr libraries interacts with simple Lotus Quickr REST services in the library linker tool, which is based on the latest Dojo 1.0 framework.

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.

Prerequisites

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.



Back to top


About Lotus Quickr Library Linker

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!

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
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.



Back to top


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.



Back to top


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);



Back to top


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:

  1. url. The feed’s URL to denote content in the Lotus Quickr server.
  2. user. User name to access the content.
  3. pw. Password to access the content.
  4. callback. Callback method to refresh the UI when the user gets a successful response.
  5. 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; 
      }
    });
}



Back to top


Refresh the grid table

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.



Back to top


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:

  1. Get the entry/feed URL of the selected contents.
  2. 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.
  3. Organize the POST entry Atom XML according to step 2.
  4. 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.

Save a document

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!");
		}
	});
}

Save a folder

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!");
		}
	});
}



Back to top


Conclusion

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.




Back to top


Download

NameSizeDownload method
QuickrLibraryLinker.zip56.2KBHTTP
Information about download methods


Resources

Learn

Get products and technologies

Discuss


About the authors

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.


Chen Yan is an Advisory Software Engineer at IBM working with the Lotus Quickr team in the China Software Development Lab in Beijing, You can reach him at cheny@cn.ibm.com.


Bruce Roberts is an Architect of IBM Lotus Quickr. You can reach Bruce at robertsb@us.ibm.com.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


12345
Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top