Content Management Guide

CHAPTER 3

Managing Documents

This chapter describes how to manage documents using the Content Management (CM) API. It has these sections:

NOTE:   Most of the document management tasks described in this chapter can also be accomplished using the CMS Administration Console.

For more information    For more information, see Creating Content. and Maintaining Content.

 
Top of page

About documents

A document in the CM subsystem may represent a simple, finite piece of content such as an image, or it may be a complex entity that comprises other documents. A document can be any data that you want to use directly or indirectly in your exteNd Director application.

The CM subsystem uses metadata fields to describe a document. There are standard fields for every document, such as name, title, author, and abstract. You can also associate content-related fields with a document type. This extension metadata can hold additional searchable information specific to that document type.

A document object can be associated with an EbiDocContent object that holds the text or binary data, but a document doesn't need to have a content object. The metadata for the document may store all the information you need. For a short text document, you could store the entire text in the abstract field. If the document doesn't have content, specify null for the MIME type and content.

The supplied content, if any, becomes the first version of the document. If you want to publish the content, you can call publishDocumentContentVersion() anytime or rely on your scheduled task to publish it. Documents without content cannot have versions (including a published version), but you could use another field (such as status) to label a document as publicly available.

 
Top of section

Accessing the CM API

The EbiContentMgmtDelegate interface provides access to most of the document-related methods in the CM subsystem.

For more information    For information, see About the CM API.

 
Top of page

Adding documents

To add a document, you create an EbiAddDocumentParams object and set various parameters. The next table explains the default values for the required parameters: name, document type, folder, and extension metadata, if any—as well as other parameters for which the default value has a particular meaning. Any other metadata fields that aren't explicitly set are null:

Parameter

Description and default values

Name

A name for the document, used when specifying a path for the document in the folder structure. The default name is the UUID assigned to the document when it is added.

Document type ID

The ID of the document type for this document. The default is the system's Default document type.

Folder ID

The folder that contains this document. The default is the system's root folder.

Extension metadata

If the document belongs to a document type that has at least one associated extension metadata field, you must call the setExtensionMetaData() method to provide values for the fields.

For more information    For information, see Specifying field values for a document.

Publish date

A timestamp specifying when the document's current version should be published. The default value of null means publish as soon as possible.

Expiration date

A timestamp specifying when the document should be removed from the published area. The default value of null means never expire.

Access control list

An ACL specifying access rights to the document.

The ACL is null by default. In this case, the document inherits the ACL of its folder. If the folder doesn't have an ACL, there are no restrictions for the document.

 
Top of section

Adding a document

This code example presents a method called addDocument() that illustrates how to add a document of type Movie Review. This method sets all required document parameters—document type, name, title, author, and parent folder—as well as some optional parameters.

The new document does not contain extension metadata fields, nor does it have a parent document. The addDocument() method sets the content of the new movie review document explicitly and stores it in the byte array content.

The addDocument() method needs to access a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments.

Note that the addDocument() method does not set the ACL for the new document. This means that the ACL is null and the document inherits the ACL of its folder:

  public void addDocument(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get the doctype
          EbiDocType type = cmgr.getDocumentTypeByName(context, "Movie Review");
  
          // Get the folder
          EbiDocFolder folder = (EbiDocFolder)cmgr.lookupDirectoryEntry(
              context, "MyApp/MovieReviews/Current", EbiDocFolder.EL_DOC_FOLDER);
  
          // Get the content
          String movieContent = "This movie has exceeded all expectations!....";
          byte content[] = movieContent.getBytes();
  
          EbiAddDocumentParams docParams = cmgr.createAddDocumentParams();
          docParams.setName("Star Trek Movie Review");
          docParams.setDocTypeID(type.getDocTypeID());
          docParams.setFolderID(folder.getID());
          docParams.setAuthor("Night Ghost");
          docParams.setTitle("Star Trek Movie Review");
          docParams.setSubtitle("Generations");
          docParams.setAbstract("This reviewer loves the movie!........");
          docParams.setMimeType("text/xml");
          docParams.setContent(content);
          docParams.setComment("Initial revision.");
  
          // params.setAcl(...); specify an ACL, otherwise inherit ACL of parent folder
  
          EbiDocument doc = cmgr.addDocument(context, docParams);
          System.out.println("Added new movie review: " + doc);
  
          // Publish the new document
          cmgr.publishDocumentContentVersion(context, doc.getID(), 1, true, true);
      }

 
Top of section

Adding multiple documents

This code example presents a method called addMultipleDocuments() that converts a set of files into new documents of type Movie Review and adds them to the CM subsystem.

This method sets all required document parameters—document type, name, title, author, and parent folder—as well as some optional parameters.

Note that the addMultipleDocuments() method executes the following shared logic outside the for loop for efficient processing:

The new documents do not contain extension metadata fields, nor do they have parent documents. The addMultipleDocuments() method reads in the content of each new movie review from its file of origin and stores the data in the byte array content.

As for security, the addMultipleDocuments() method does not set the ACL for the new documents. This means that the ACL is null and the documents inherit the ACL of their folder.

The addMultipleDocuments() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), and the directory where the files of interest are stored. All of these entities are passed in as arguments:

  public void addMultipleDocuments(
          EbiContentMgmtDelegate cmgr, EbiContext context, String dirName)
          throws
              EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException,
              FileNotFoundException, IOException
      {
          // Get the doctype
          EbiDocType type = cmgr.getDocumentTypeByName(context, "Movie Review");
  
          // Get the folder
          EbiDocFolder folder = (EbiDocFolder)cmgr.lookupDirectoryEntry(
              context, "MyApp/MovieReviews/Current", EbiDocFolder.EL_DOC_FOLDER);
  
          // Instantiate a document addition parameters object
          EbiAddDocumentParams docParams = cmgr.createAddDocumentParams();
  
          // Set all the String parameters to be reused
          String author = "NightGhost";
          String mimeType = "text/xml";
          String comment = "Initial revision.";
  
          File dir = new File(dirName);
          File[] files = null;
          if (dir.exists() && dir.isDirectory())
              files = dir.listFiles();
          else
              throw new EboApplicationException(null, "Invalid directory name '" + dirName 
  	 	 	 	 + "'.");
  
          // Turn each file in the specified directory into a new movie review document
          for (int i = 0; i < files.length; i++)
          {
              if (files[i].isDirectory())
                  continue;
              FileInputStream fis = new FileInputStream(files[i]);
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              byte[] value = new byte[4096];
              while (true)
              {
                  int bytes = fis.read(value);
                  if (bytes < 1)
                      break;
                  baos.write(value, 0, bytes);
              }
              byte[] content = baos.toByteArray();
              baos.close();
  
              String name = files[i].getName();
  
              docParams.setName(name);
              docParams.setDocTypeID(type.getDocTypeID());
              docParams.setFolderID(folder.getID());
              docParams.setAuthor(author);
              docParams.setTitle(name);
              docParams.setMimeType(mimeType);
              docParams.setContent(content);
              docParams.setComment(comment);
              docParams.setPublishImmediately(true);
  
  
              // params.setAcl(...); specify an ACL, otherwise inherit ACL of parent folder
  
              EbiDocument doc = cmgr.addDocument(context, docParams);
  
          }
      }

 
Top of page

Specifying field values for a document

When you add a document, you must create a set of field values that match the fields defined for the document's type. Each field can have one or more values, and null values are allowed. The fields and their values are called extension metadata, in contrast to the standard metadata defined for an EbiDocument object (such as title, author, abstract, and status).

You manage the extension metadata via two objects:

Object

Description

EbiDocExtnMeta

A holder for all the extension metadata for all the fields

EbiDocExtnMetaInfo

Associates a field with a set of values

After you create an EbiDocExtnMetaInfo object for a specific field, you set the values for the field as an array, even if there is only one value. The type of the array must correspond to the data type of the field.

After you've created an EbiDocExtnMetaInfo object for each field and added it to the EbiDocExtnMeta object, call setExtensionMetaData() for EbiAddDocumentParams to associate it with the document you are adding.

 
Top of section

Getting fields for the document type

To find out what fields to specify for a document, you can get a collection of EbiDocField objects for the document type. This example presents a method called getDocTypeFields() that gets all the document type fields to which the user has READ access.

The getDocTypeFields() method needs to access a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments:

  public void getDocTypeFields(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocType docType = cmgr.getDocumentTypeByName(context, "Movie Review");
          if (docType != null)
          {
              Collection fields = cmgr.getFilteredDocumentFields(context, docType.getDocTypeID());
              System.out.println("Fields: " + fields);
          }
      }

 
Top of section

Getting a field object by name

You can also get individual fields by name. This example presents a method called getField() that gets the field named Director.

The getField() method needs to access a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments:

  public void getField(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocField fldDirector = cmgr.getDocumentFieldByName(context, "Director");
          System.out.println("Director field: " + fldDirector);
      }

 
Top of section

Setting a field value

This example presents a method called setFieldValues() that performs the following tasks:

The values for each field are passed as String arrays.

Note that the setFieldValues() method does not set the ACL for the new document. This means that the ACL is null and the document inherits the ACL of its folder.

The setFieldValues() method needs to access a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments:

  public void setFieldValues(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get the doctype
          EbiDocType type = cmgr.getDocumentTypeByName(context, "Movie Review");
          // Get the folder
          EbiDocFolder folder = (EbiDocFolder)cmgr.lookupDirectoryEntry(
              context, "MyApp/MovieReviews/Current", EbiDocFolder.EL_DOC_FOLDER);
          // Instantiate a document addition parameters object
          EbiAddDocumentParams docParams = cmgr.createAddDocumentParams();
  
          // Create the extension metadata holder object
          EbiDocExtnMeta meta = cmgr.createExtnMeta();
  
          // Specify the extn metadata field values for 'Director'
          EbiDocField fldDirector = cmgr.getDocumentFieldByName(context, "Director");
          EbiDocExtnMetaInfo miDirector = cmgr.createExtnMetaInfo(fldDirector);
          String[] directors = { "Andy Wachowski", "Larry Wachowski" };
          miDirector.setFieldValues(directors);
          meta.setExtnMetaInfo(miDirector);
  
          // Specify the exnt metadata field values for 'Genre'
          EbiDocField fldGenre = cmgr.getDocumentFieldByName(context, "Genre");
          EbiDocExtnMetaInfo miGenre = cmgr.createExtnMetaInfo(fldGenre);
          String[] genres = { "Action", "Thriller", "Sci-Fi" };
          miGenre.setFieldValues(genres);
          meta.setExtnMetaInfo(miGenre);
  
          // Get the content
          String movieContent = "This movie has exceeded all expectations!....";
          byte content[] = movieContent.getBytes();
  
          // Set the extension metadata into the doc params object
          docParams.setExtensionMetaData(meta);
  
          docParams.setName("The Matrix (1999)");
          docParams.setDocTypeID(type.getDocTypeID());
          docParams.setFolderID(folder.getID());
          docParams.setAuthor("Night Ghost");
          docParams.setTitle("The Matrix (1999)");
          docParams.setMimeType("text/xml");
          docParams.setContent(content);
          docParams.setComment("Initial revision.");
  
          // params.setAcl(...); specify an ACL, otherwise inherit ACL of parent folder
  
          EbiDocument doc = cmgr.addDocument(context, docParams);
  
          // Publish the new document
          cmgr.publishDocumentContentVersion(context, doc.getID(), 1, true, true);
      }

 
Top of section

Getting all fields

This example presents a method called getExtnMeta() that gets all the extension metadata fields for a specified document. The method uses the EbiDocExtnMeta object as a holder for the document's fields. This object provides methods for getting information about the fields, such as names and values.

The getExtnMeta() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), and the document of interest—all of which are passed in as arguments:

  public void getExtnMeta(EbiContentMgmtDelegate cmgr, EbiContext context, String docID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get the extension metadata holder for the document
          EbiDocExtnMeta extnMetaData = cmgr.getDocumentExtnMeta(context, docID);
          System.out.println("Extension metadata: " + extnMetaData);
  
          // Enumerate the field names
          Iterator fieldNames = extnMetaData.getFieldNames().iterator();
          while (fieldNames.hasNext())
              System.out.println("Field: " + (String)fieldNames.next());
  
          // For each extension meta info
          for (int i = 0; i < extnMetaData.size(); i++)
          {
              EbiDocExtnMetaInfo mi = extnMetaData.getExtnMetaInfoByIndex(i);
              System.out.println("MetaInfo " + i + ": " + mi);
  
              String fieldName = mi.getFieldName();
              System.out.println("Field name: " + fieldName);
  
              Collection fieldValues = mi.getFieldValues(false);
              System.out.println("Values: " + fieldValues);
          }
      }

 
Top of section

Getting field values for a single field

This example presents a method called getExtnMeta() that gets an EbiDocExtnMetaInfo object for a single field.

The getExtnMeta() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), and the document and field of interest—all of which are passed in as arguments:

  public void getExtnMeta(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String docID, String fieldID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocExtnMetaInfo info = cmgr.getDocumentExtnMetaInfo(
              context, docID, fieldID);
          System.out.println("Meta Info: " + info);
      }

From the EbiDocExtnMetaInfo object you can get a Collection of the values for the field (the values of the array that set the field). A boolean argument lets you specify whether the data type of the returned values is String or the actual data type of the field.

This statement gets the values of the EbiDocExtnMetaInfo object as Strings:

  Collection valueStrings = info.getFieldValues(true);

Methods for managing documents

This table lists methods that let you manage documents, edit the metadata, and get documents:

Method

Returns

Description

createAddDocumentParams()

EbiAdd-DocumentParams

Creates an empty object to hold the data needed to add a document, including metadata, extension metadata, content, and ACL. You use the EbiAddDocumentParams object with the addDocument() method.

addDocument()

EbiDocument

Adds a document to the content repository. Content for the document is optional.

copyDocument()

EbiDocument

Copies a document to a folder or to a parent document.

getDocument()

EbiDocument

Gets a document object for a specified document ID.

moveDocument()

EbiDocument

Moves a document to a folder or to a parent document.

updateDocument()

void

Updates the information about a document in the content repository using changes made to EbiDocument.

removeDocument()

boolean

Removes a document and all its versions from the system.

addDocumentCategory-Reference()

void

Adds a document to a category. A document can belong to many categories.

removeDocumentCategory-Reference()

boolean

Removes a document from a category.

getDocumentExtnMeta()

EbiDocExtnMeta

Gets a holder for the extension metadata objects associated with each field of the document. Its methods let you get the values for individual fields.

getDocumentExtnMeta-Info()

EbiDocExtnMetaInfo

Gets the extension metadata object for a field of the document.

getDocumentsByType() and getFilteredDocuments-ByType()

Collection of EbiDocument

Gets a collection of the documents of a particular document type. The filtered version omits documents to which the current user has no READ access. The unfiltered version gets all documents for the type, regardless of access rights.

getLatestDocumentContent-Version()

EbiDocVersion

Gets the most recent version of a document.

getDocumentContent-Version()

EbiDocVersion

Gets a version of a document.

getDocumentContent-Versions()

Collection of EbiDocContent

Gets all the versions of a document.

publishDocumentContent-Version()

void

Publishes a version of a document.

getContent()

EbiDocContent

Gets the published content for a document. If the document is not published, returns null.

unpublishDocumentContent()

boolean

Removes a document's content from the published area.

The content for all document versions remains intact.

 
Top of page

Specifying layout sets for documents

Typically, the layout styles associated with the document type are adequate for displaying your document (as described in Managing layout styles). When you have hundreds of documents (news stories, press releases, editorials, reviews), you don't want to design custom XSL for each one. One design or a few alternative designs are enough; you can associate one or more layout styles with a document type.

 
Top of section

When to use a layout set

When you want to lock in a particular layout for an individual document, you can specify a layout set for that document. A layout set uses a specific layout style, selected from the ones that are valid for the document's type. The layout set uses one or more of the layout document descriptors associated with that style. In the set you can use whatever version of the layout document is currently published or you can select a specific version. The set needs to includes layout document descriptors for whatever clients will view the content. The XSL in the layout documents associated with the descriptors render the document.

What a layout set is good for   A layout set is meant for locking in a presentation so that the document always looks the same. As layout styles for a document type evolve with new versions, the presentation of an individual document will change. Use a layout set when it is important to preserve the original presentation.

What a layout set is less appropriate for   The layout set is less appropriate for giving a document a unique look. It may be more appropriate to add a new document type. However, you can also add a custom style to the document type in order to make a special layout available for the document. If you don't want to be constrained to styles for the document type, you could design your application to locate style documents another way—for example, via a custom field. However, you would want to make sure your custom system has the flexibility for getting different XSL for different clients.

 
Top of section

Methods for managing layout sets

These methods of EbiContentMgmtDelegate manage layout sets:

Method

Returns

Description

createDocLayoutSet()

EbiDocLayoutSet

Creates an empty layout set. It is associated with a document when you call addDocument().

getDocumentLayoutSet()

EbiDocLayoutSet

Gets the layout set for a document.

removeDocumentLayoutSet()

boolean

Removes the layout set from the document.

updateDocumentLayoutSet()

void

Updates the layout set with new layout style and layout style descriptor information.

To associate a layout set with a new document, call the setLayoutSet() method of EbiAddDocumentParams.

To change the XSL documents in the layout set of an existing document, call getDocumentLayoutSet(), call methods of EbiDocLayoutSet to make changes, and then call updateDocumentLayoutSet().

NOTE:   Currently, you cannot add a layout set to a document if it didn't have one when it was added.

 
Top of page

Creating links between documents

You can specify relationships between documents by specifying that one document is a child of another.

This section includes these topics:

 
Top of section

Two types of document relationships

The content repository supports two types of document relationships—hierarchical and compound

Document relationship

Description

Hierarchical

Where each document in the hierarchy stores the ID of its parent document. A document has only one parent. The value –1 identifies the top document in a chain of links. The chain can be an indefinite number of levels deep.

Hierarchical linking is designed for a threaded discussion and similar structures.

Compound

Where a link object identifies the originator of the link (parent) and the target of the link (child). A parent can have many child documents, and a child can have many parents.

Compound linking is designed for building composite documents, where many pieces of content are brought together in a single presentation page. For example, child documents might include sections of a report, a list of cross-references that is appended to a document, or images to be displayed in a page.

You can use linked documents in many ways. A parent document might serve as a container of child documents, where each subsection of the document is produced by a different author. Documents could be linked in a chain to identify a message thread. Links could point to nontext documents that are stored separately, such as images or sound files.

CAUTION:    When specifying either hierarchical or compound links, you are not prevented from creating circular links, where a parent document is also a child of its child document. If you do this, proceed with caution: circularity may confuse both programmer and end user. It is up to you to understand the link structure of your repository when you process the content.

 
Top of section

Hierarchical linking

Hierarchical linking lets you create a threaded discussion. The following diagram shows two views of a threaded discussion. Each reply has one parent, and each message can be the parent of several replies. The top message in each chain has no parent.

When a user submits a reply, the application uses the ID of the original message as the parent of the new reply document:

replyDoc

Methods for hierarchical linking

These methods of EbiContentMgmtDelegate are useful in managing hierarchical links:

Method

Returns

Description

addDocument()

EbiDocument

When adding a document, you can make it a child document by specifying a parent ID. If the parent ID is –1, the document has no parent.

getChildDocuments() and getFilteredChild-Documents()

Collection of EbiDocument

Gets child documents that have a parent ID of the specified document. The filtered version omits documents to which the current user has no READ access. The unfiltered version gets all child documents, regardless of access rights.

In addition, when you have an EbiDocument object, you can get and change the parent document ID, via getParentDocID() and setParentDocID(). After changing the ID, call updateDocument() to put the changes in the repository.

 
Top of section

Adding a child document

This example presents a method called addChildDocument() that creates a child document as a reply in a message thread. Inside a while loop, the method navigates the thread to the top message, and then uses its title to construct the name and subtitle of the reply.

The addChildDocument() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent document, a message subject, and a reply—all of which are passed in as arguments:

  public void addChildDocument(
          EbiContentMgmtDelegate cmgr, EbiContext context, String folderID,
          String parentID, String subject, String reply)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiAddDocumentParams params = cmgr.createAddDocumentParams();
          params.setName("Reply to " + threadTitle);
          EbiDocType doctype = cmgr.getDocumentTypeByName(context, "Discussion");
          if (doctype != null)
              params.setDocTypeID(doctype.getDocTypeID());
          params.setFolderID(folderID);
          params.setAuthor(context.getUserID());
          params.setTitle(subject);
          params.setSubtitle(threadTitle);
          params.setMimeType("text/plain");
          params.setContent(reply.getBytes());
          params.setParentID(parentID);
          cmgr.addDocument(context, params);
      }

 
Top of section

Compound linking

Compound linking lets you create a network of interrelated documents. You might use it to create a composite document out of many contributed pieces, such as sections (written by different authors), images, cross-references, and other information.

For more information    For more information, see Composite documents.

The following diagram shows a network of documents that are used by two different parent documents; some of the material is shared by both:

docNetwork

Access to documents you want to link   To create a link, you must check out both the parent and child documents, add the link, and then check in both documents.

XML for composite documents   It is easy to program the display of a composite document when the content type is XML. Your portlet inserts each child document as a node in the DOM with an appropriate element name. An XSL style sheet specifies how those elements are displayed. You don't have to insert the child documents into existing content in any particular order. The order is determined by the style sheet. By selecting different style sheets, you can change the way the different elements are displayed and whether they are included at all.

For more information    For information about style sheets for document types, see Managing layout styles. To specify styles for individual documents, see Specifying layout sets for documents.

For example, suppose you have a Movie Review document type and the paragraphs of the review are its content. Child documents for the review could include an image from the movie and biographies of the cast. In the displayed HTML, the biographies could be displayed on the same page or they could be links to another HTML page. You could have different style sheets that determine which way to display the biographies and whether the image is on the left or the right.

Methods for compound linking

NOTE:   When adding, removing, and changing links, you must check out the parent and child documents.

These methods of EbiContentMgmtDelegate are useful in managing compound links:

Method

Returns

Description

addDocumentLink()

EbiDocLink

Adds a link between two documents. For the child version ID argument, you can specify a specific version or –1 to use the published version.

getDocumentLink()

EbiDocLink

Gets a link object, given the parent and child IDs.

removeDocumentLink()

boolean

Removes a link.

updateDocumentLink()

void

Allows you to change the version of the child document the link uses.

getLinkChildDocuments() and getFilteredLinkChild-Documents()

Collection of EbiDocument

Gets the link objects for the child documents that are linked to the specified parent document. The filtered version omits documents to which the current user has no READ access. The unfiltered version gets all documents regardless of access rights.

getLinkParentDocuments() and getFilteredLinkParent-Documents()

Collection of EbiDocument

Gets the document objects for the parent documents to which the specified child document is linked. The filtered version omits documents to which the current user has no READ access. The unfiltered version gets all documents regardless of access rights.

 
Top of section

Linking a child document

This example presents a method called addDocLink() that adds a link between a parent document and a child document.

The addDocLink() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent and child documents, and the child document version—all of which are passed in as arguments.

  public void addDocLink(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String linkParentDocID, String linkChildDocID, int linkChildVersionID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocLink lnk = cmgr.addDocumentLink(
              context, linkParentDocID, linkChildDocID, linkChildVersionID);
      }

 
Top of section

Updating a link with a new document version

This example presents a method called updateDocumentContentAndLink() that creates and publishes a new version of a child document, then updates the link from the parent to point to the new version.

If a new version of the child document is published later, this link continues to point to the old version. A link between parent and child must exist. If not, you need to use addDocumentLink() instead of updateDocumentLink().

The updateDocumentContentAndLink() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent and child documents, document content, and a MIME type—all of which are passed in as arguments:

  public void updateDocumentContentAndLink(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String linkParentDocID, String linkChildDocID,
          byte[] linkChildDocContent, String linkChildDocMimeType)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Create a new version of the link child document
          int newVersionID = cmgr.checkinDocument(
              context,                   // Context
              linkChildDocID,            // Docid of link child
              linkChildDocMimeType,      // Mime type
              linkChildDocContent,       // New content
              "new version",             // Check-in comment
              false);                    // Whether to keep doc checked out
  
          // Publish it
          cmgr.publishDocumentContentVersion(
              context, linkChildDocID, newVersionID, true, true);
  
          // Now update the link to point to the new version
          cmgr.updateDocumentLink(
              context,                   // Context
              linkParentDocID,           // Link parent docid
              linkChildDocID,            // Link child docid
              newVersionID);             // New version id
      }
  

 
Top of section

Getting linked parent documents

This example presents a method called getLinkParentDocuments() that gets the parent documents that are linked to a specified child.

By calling getFilteredLinkParentDocuments(), the code retrieves only documents to which the user has READ access.

The getLinkParentDocuments() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the child document of interest—all of which are passed in as arguments:

  public void getLinkParentDocuments(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String linkChildDocID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          Collection linkParentDocs = cmgr.getFilteredLinkParentDocuments(context, linkChildDocID);
          System.out.println("Parent docs: " + linkParentDocs);
      }

 
Top of section

Getting linked child documents

This example presents a method called getLinkChildDocuments() that gets the child documents that are linked to a specified parent.

By calling getFilteredLinkChildDocuments(), the code retrieves only documents to which the user has READ access.

The getLinkChildDocuments() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the parent document of interest—all of which are passed in as arguments.

  public void getLinkChildDocuments(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String linkParentDocID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          Collection linkChildDocs = cmgr.getFilteredLinkChildDocuments(context, linkParentDocID);
          System.out.println("Child docs: " + linkChildDocs);
      }

 
Top of page

Modifying and publishing documents

The CM subsystem includes functionality that supports checkout, checkin, versioning, and publishing.

Much of the information in the CM subsystem is data about documents. However, when you start using the checkout and checkin methods, you also get multiple versions of document content. Each time a document is checked in, a new version is created. When a document is published, there is also a released version of the content, which comes from the set of versions. You can continue creating new versions, while the publicly available version remains stable.

The diagram that follows shows the relationship between an EbiDocument object, which holds the document metadata, and its version objects. The content for each version is stored in an EbiDocVersion object. When you select a version for publishing, that version's content is copied to an EbiDocContent object.

objRelationship

NOTE:   It is important to remember that only the content has multiple versions. There is only one version of the document's metadata.

You might program portlets for source control and publishing to accomplish tasks like these:

Task

Information

Add a new document to the system

If the document is added with accompanying content, the system creates a first version.

Check out a document

When a user checks out the document, your portlet copies the content to an appropriate editing environment.

Check in a document

When the user checks in the document, the system creates a new version.

Publish documents

You might have a scheduled task that checks publish dates and calls publishDocumentContentVersion() when a document's publish date is passed.

Unpublish documents

You might have a scheduled task that removes a published version when the expiration date has passed. The task might move the document to an archive folder, purge it from the system, or set its publish date so another version can be published later.

Review the checkin comments for a document's versions.

 
Top of section

Tracking document status

To find out if a document is published, you call the EbiDocument method getPublishStatus(). If it returns null, then the document has no published content.

A publish date does not automatically reflect the time the document was published. It just indicates when it should be published; for example, a publish date of null means publish immediately. However, your publishing portlet can set the publish date if you want to track the date a document became available.

The document's status field is available for your own document tracking. You can establish your own application-specific set of status values and update the document's status field to reflect its progress through your document processing procedures. For example, you could specify submitted, reviewed, approved, rejected, published, unpublished, archived, and purged as status values for your application.

Setting document status   This example presents a method called setDocumentStatusToRejected() that sets a document's status to rejected—perhaps to indicate that the document has been rejected by a content administrator and requires further changes before it can be published. Note that after setting status, you must call the updateDocument() method for the change to take effect.

The setDocumentStatusToRejected() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the document of interest—all of which are passed in as arguments:

  public void setDocumentStatusToRejected(
          EbiContentMgmtDelegate cmgr, EbiContext context, String docID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocument doc = cmgr.getDocument(context, docID);
          doc.setStatus("rejected");
          cmgr.updateDocument(context, doc);
      }

 
Top of section

Methods for source control and publishing

These methods of EbiContentMgmtDelegate are available for source control and publishing:

Method

Returns

Description

checkoutDocument()

boolean

Checks out a document to the current user (specified in the context argument). This method locks the document. To get the content for editing, use other methods—such as getDocumentContentVersion().

checkinDocument()

int

Checks in a new version of the document with data for the content. Only the user who checked out the document can check it in. The user is implicit in the context argument.

uncheckoutDocument()

boolean

Releases the lock set by the current user.

unlockDocument()

boolean

An administrative method that allows you to release a document lock that was set by any user.

rollbackDocument-Content()

void

Rolls document content from the latest version back to the specified one.

publishDocument-ContentVersion()

void

Publishes a specific version of the specified document.

getContent()

EbiDocContent

Gets the published content object for a document. You can choose whether it includes the actual data. If it does, get the byte array of data by calling getData() of EbiDocContent.

getDocumentContent-Version()

EbiDocVersion

Gets a version of a document. You can choose whether it includes the actual data. If it does, get the byte array of data by calling getData() of EbiDocVersion.

unpublishDocument-Content()

boolean

Removes the published content for a document.

 
Top of page

Displaying documents

Portlets in your online application get a document's metadata and content, retrieve linked content, and use the associated layout styles to display the document to the user.

 
Top of section

HTML content

If the content type of a document is HTML and it has no linked documents, the portlet might simply get and set the content, as shown below:

  EbiContentMgmtDelegate cm = null;
  try {
    cm = 
     com.sssw.cm.client.EboFactory.getDefaultContentMgmtDelegate();
  } catch (EboFactoryException ebfe) {
    throw new EboUnrecoverableSystemException(ebfe, 
    "Unable to get ContentManager");
  }
  try {
    EbiDocument doc = (EbiDocument)
     cm.lookupDirectoryEntry(context, "MyFolder/TDBDoc1",
     EbiDocument.EL_DOCUMENT);
     EbiDocContent content = cm.getContent(context, doc.getID(), true);
     if (content != null)
     {
       PrintWriter writer = response.getWriter();
       byte [] html = content.getData();
       String shtml = new String(html);
       writer.print(shtml);
     }
  
  } catch (EboItemExistenceException eiee)
  {
    throw new EboUnrecoverableSystemException(eiee, 
     "Unable to get Content");
  } catch (EboSecurityException ese)
  {
    throw new EboUnrecoverableSystemException(ese, "Security exception");
  }

 
Top of section

XML content

If the content of a document is an XML String and it has no linked documents, the portlet could get the content and the document layout (also as an XML String) and use the layout XSL to transform the XML.

This concept is illustrated in the displayContent() example method shown below. In this example, methods in com.sssw.fw.util.EboXmlHelper convert a String to a DOM and apply an XSL transformation to a DOM. The displayContent() method accesses a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the document of interest—all of which are passed as arguments:

  public void displayContent(
          EbiContentMgmtDelegate cmgr, EbiPortalContext context, String docID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocument doc = (EbiDocument)cmgr.lookupDirectoryEntry(
              context, "MyFolder/TDBDoc1", EbiDocument.EL_DOCUMENT);
          EbiDocContent doccnt = cmgr.getContent(context, doc.getID(), true);
          if (doccnt != null)
          {
              byte[] xml = doccnt.getData();
              EbiDocVersionDescriptor layoutver = cmgr.getDocumentLayout(
                  context, docID, EbiContentMgmtDelegate.COMPARE_ALL, true);
              EbiDocVersion layoutcnt = cmgr.getDocumentContentVersion(
                  context, layoutver.getDocumentID(), layoutver.getDocumentVersionID(), true);
              byte[] xsl = layoutcnt.getData();
              String sxml = new String(xml);
              String sxsl = new String(xsl);
  
              String content = EboXmlHelper.processXML(
                  EboXmlHelper.getDOM(sxml), EboXmlHelper.getDOM(sxsl));
              // Set type according to results of xsl transformation
              response.setContentType(EbiPortletConstants.MIME_TYPE_HTML);
              // Use a PrintWriter to render
              writer.print(content);
          }
      }

 
Top of section

Composite documents

A composite document could be constructed in many different ways. It is up to your portlet to gather the pieces and put them together in an appropriate way. Typically, you would build an XML DOM for the composite document and add elements for each piece. For a simpler composite document where the pieces are HTML fragments, you might concatenate them into a larger HTML fragment.

To illustrate the process of building an XML DOM, suppose you are displaying a movie review, a document of type Movie Review. The content of the movie review document is the text paragraphs of the review. The document's metadata provides the title, author, and other information specific to the Movie Review type, such as genre, director, year of release, and cast. Child documents refer to an image of the movie and cast biographies. To display all the data, the portlet builds an XML DOM of the pieces and provides an XSL style sheet for display specifications.

You will want to plan an XML structure for defining the XSL and building the DOM in the portlet's code. You may want to formalize that structure in a DTD. The XML structure might look like this (shown without closing tags):

  <REVIEW>
     <TITLE>
     <AUTHOR>
     <GENRE>
     <DIRECTOR>
     <CAST>
        <CASTMEMBER>
           <CASTPICTURE>
           <BIO>
        </CASTMEMBER>
        <CASTMEMBER>
           <CASTPICTURE>
           <BIO>
        </CASTMEMBER>
     </CAST>
     <CONTENT>
  </REVIEW>
  

The coding steps might be:

  1. Get the EbiDocument object.

  2. Get the metadata you want displayed (such as title, author, director, and genre) and add elements for each one. Element names might be TITLE, AUTHOR, and so on. The data values could be attributes or text nodes of the elements.

  3. Get the cast metadata and add a CAST element, with child CASTMEMBER elements for each one.

  4. Get the content data. Add a CONTENT element for the review paragraphs (the document content) and add the content data as a text node of the element.

  5. Call getLinkChildDocuments() to get the linked child documents.

  6. For each linked document, get the MIME type and other information to determine the document's purpose:

  7. When the XML DOM is complete, call methods of the context object to set the MIME type and the content.



Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.  more ...