Content Management Guide  

Chapter 2   Content Management API

This chapter describes the Director Content Management subsystem from a programmer's viewpoint. It covers:

TIP   This chapter describes a Director API that allows you to build your own content management application. Director also provides the Portal Management Console (PMC), which you can use to create, maintain, administer, and secure all content for your Director application.

 
Top of page

Using the Content Management API

You can use the Content Management API to build a system tailored to your business process. By writing components, you can build a complete interface that includes such functionality as:

The Content Management API provides complete programmatic access to the document repository.

Several components that access the document repository come with Director. You can use the discussion board and document viewer in your Director application. Their source code can serve as a starting point for your own components.

 
Top of section

Getting a content manager object

Methods of the EbiContentMgmtDelegate interface provide access to the most of the objects in the Content Management subsystem.

For all the examples in this chapter, you must use this code somewhere in your component to get a reference to the content manager delegate:

  EbiContentMgmtDelegate defaultCmgr = 
  	 com.sssw.cm.client.EboFactory.getDefaultContentMgmtDelegate();
  if (cmgr != null) 
     ... // do content-related processing
  else
     System.out.println("Failed to get Content Manager");

Using delegates   Delegates are objects that provide a layer of abstraction for main Director manager objects (such as the Content Manager object). Using delegates removes the need for coding things like local and remote access to Director services.

From a best practices standpoint, you should always use delegates rather than accessing Director manager objects directly.

 
Top of section

Changing repository data

In the simplest case, the basic procedure for working with objects in the repository is:

  1. Use a get method of EbiContentMgmtDelegate to get an object from the repository.

  2. Use methods of that object to modify it.

  3. Use an update method of EbiContentMgmtDelegate to put the changed object back in the repository, or use the update method on the object itself if it is available.

Some objects are more complex. The rest of this chapter describes how to work with many of these objects, with code examples.

 
Top of page

Setting up the Content Management subsystem infrastructure

Before creating documents in the Content Management subsystem, you must set up the content infrastructure, which includes the criteria by which you organize the documents. The infrastructure includes fields, document types, layout styles, folders, and categories:

Item

Description

For more information

Fields

A field allows you to provide application-specific information about documents, also called extension metadata. Each document type can have zero or more fields. Each document may have one or more values per field, and null values are allowed.

Managing fields

Document types

The document type is the basic classification mechanism of the system. You would classify documents as a particular type when they have similar formatting and subject matter. A document type has a list of fields and a default layout style.

Managing document types

Layout styles

A document type can have a default layout style. Specific documents can have their own layout styles or sets of styles.

Managing layout styles

Folders

Folders allow you to group documents for administrative purposes. For example, you can assign confidential documents to a folder that has restricted access. Folders can be nested.

Managing folders and categories

Categories

You can use categories as another way of organizing documents. Typically, categories are the user's view of the content repository, organized by subject matter. Categories can be nested.

Managing folders and categories

 
Top of section

Managing fields

All documents have a basic set of metadata, such as title, author, abstract, published version, and so on. You can also define custom metadata fields to store application-specific data for each document type. Fields are appropriate for any piece of data for which all the documents have a value. For example, movie reviews have a director, cast, release date, and rating. Books have an author, publisher, publish date, and number of pages. Reviews of travel destinations have country, cost category, and quality rating.

Fields are also useful for finding documents. For each document type, a set of fields identify the pertinent, searchable information for the subject matter of that document type. Fields can be searched quickly via a database lookup, in contrast to searching the document content text.

For example, for a document type of MovieReview, you might create several fields as shown below:

Field name

Data type

Sample value

Genre

FT_STRING

Drama, Romance

Tagline

FT_STRING

In a perfect world...they never would have met

User Rating

FT_STRING

4.9/10 (1083 votes)

Runtime

FT_STRING

USA:133 / UK:132 / Finland:133 / Japan:132

Year of Release

FT_INT

2000

NOTE   In this example, Genre and Runtime could have multiple values.

Data types   EbiDocField defines several data types to be used for fields. This table categorizes the available types:

Type of data

Available data types defined in EbiDocField

Character data

FT_CHAR, FT_STRING

Numeric

FT_BIGDECIMAL
FT_DOUBLE, FT_FLOAT
FT_INT, FT_LONG, FT_SHORT

Boolean

FT_BOOLEAN

Date and time

FT_DATE, FT_TIME, FT_TIMESTAMP

Binary

FT_BYTE, FT_BYTEARRAY

Metadata for fields   You already know that fields store metadata about a document. You can also store data about the field itself. You can use this extension metadata to store a list of appropriate values, a prompt to use in forms, an image for the field, or other information appropriate to your application. The data is a byte array.

Fields and document types   When you create a document type, you specify the set of fields it uses. You can use a field with more than one document type.

Fields and values   For each document of a particular document type, all the associated fields must have at least one value, specified via an EbiDocExtnMetaInfo object. The value can be null. You assign the field values to the document as a set via an EbiDocExtnMeta object. EbiDocExtnMeta holds an EbiDocExtnMetaInfo object for each field associated with the document type. You call getFieldValues() to get an array of values for a field. The values can be returned as Strings, or they can have the field's data type.

These methods in EbiContentMgmtDelegate let you add and modify fields:

Method

Returns

Description

addDocumentField()

EbiDocField

Adds a field to the Content Management subsystem. You specify the name, data type, supporting data for the field, and an ACL (access control list). The last two arguments can be null.

getDocumentFieldByID()

EbiDocField

Gets a field by ID.

getDocumentFieldByName()

EbiDocField

Gets a field by name.

updateDocumentField()

void

After calling methods to modify an EbiDocField object, updates the content repository with the changes.

removeDocumentField()

void

Removes a field from the system.

getDocumentFields() and getFilteredDocumentFields()

Collection of EbiDocField

Gets a Collection of all the fields in the Content Management subsystem. The filtered version omits fields to which the current user has no READ access. The unfiltered version gets all fields, regardless of access rights.

    For information about using fields with document types, see Managing document types.

Examples

Adding a field   This example provides a method called addField() that adds an extension metadata field.

  public void addField(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          String fieldName = "Rating";
          String valueType = EbiDocField.FT_STRING;
          String extnMeta = "This is a Rating field...";
          cmgr.addDocumentField(
              context,                   // context
              fieldName,                 // field name
              valueType,                 // value data type
              extnMeta.getBytes(),       // extension metadata
              null);                     // ACL
      }

Adding a field in the processRequest() method   This example shows how to add a field in the processRequest() method of a component. It gets the name and data type the user entered in an HTML form and adds a field. A message about success or failure is stored in the context object to be displayed when getComponentData() generates content.

  public void processRequest( EbiPortalContext context,
     java.util.Map params )
  {
     String name = req.getParameter(FORM_NAME);
     String datatype = req.getParameter(FORM_DATATYPE);
     String valuelist = req.getParameter(FORM_LIST);
  
     EbiContentMgmtDelegate cmgr = ...; // get content manager
  
     try
     {
       cmgr.addDocumentField(context,name,datatype,valuelist,null);
       context.setValue(
           context.getComponentInfo().getComponentClassName(),
           KEY_STATUS,
           "Field " + name + " successfully added.");
     }
     catch (Exception e)
     {
       context.setValue(
           context.getComponentInfo().getComponentClassName(),
           KEY_STATUS,
           "Field " + name + " not added. " + e.toString() );
     }
  }

Listing fields using different filters   This example provides a method called listFields() that gets existing document fields by filtering the results in different ways.

The listFields() method needs to have access to a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments. The context object provides information about the user's security privileges. The listFields() method passes the context object to the getFilteredDocumentFields() method to return only those fields for which the user has READ access.

  public void listFields(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get all the existing fields (note: no security checking is done here)
          Collection allFields = cmgr.getDocumentFields(context);
          Iterator iterAllFields = allFields.iterator();
          while (iterAllFields.hasNext())
          {
              EbiDocField field = (EbiDocField)iterAllFields.next();
              System.out.println(field + "\n\n");
          }
  
          // Get all the fields that belong to doctype 'MovieReview'
          EbiDocType docType = cmgr.getDocumentTypeByName(context,"MovieReview");
          Collection docTypeFields = cmgr.getDocumentFields(context,docType.getDocTypeID());
  
          // Get all the fields to which the user has Read access
          Collection filteredFields = cmgr.getFilteredDocumentFields(context);
  
          // Get all the Read-accessible fields that belong to doctype 'MovieReview'
          Collection filteredDtFields = cmgr.getFilteredDocumentFields(context, docType.getDocTypeID());
      }

 
Top of section

Managing document types

A document type identifies a particular type of content. Typically, you create document types for groups of documents that have similar content. The documents share the same set of fields that describe that content and, for XML content, the same layout styles to display the content.

After you have created a document type, you can modify its name and description. To do so, get an EbiDocType object, call setDocTypeName() or setDescription(), then call updateDocumentType() to put the changed type back into the content repository.

You can also associate layout styles with the document type. For information, see Managing layout styles.

These methods in EbiContentMgmtDelegate let you add and modify document types:

Method

Returns

Description

addDocumentType()

EbiDocType

Adds a document type to the system. You specify a name, description, and the list of metadata fields associated with the type. The system gives the type a numeric ID.

getDocumentType()

EbiDocType

Gets a document type by name or ID.

updateDocumentType()

void

After calling methods to modify an EbiDocType object, updates the content repository with the changes.

removeDocumentType()

boolean

Removes a document type from the system. If documents of that type exist, you must delete them before you can delete the type.

getDocumentTypes() and getFilteredDocumentTypes()

Collection of EbiDocType

Gets a Collection of EbiDocType objects. The filtered version omits types to which the current user has no READ access. The unfiltered version gets all types, regardless of access rights.

These methods of EbiContentMgmtDelegate manage the association between document types and fields:

Method

Returns

Description

addFieldToDocumentType()

void

Adds a field to the document type. For existing documents, the values for the field are null.

removeFieldFrom-
DocumentType()

boolean

Removes the association between a field and a document type. Deletes the field values for documents of that type.

getDocumentFields() and getFilteredDocumentFields()

Collection of EbiDocField

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

getDocumentTypesWithField() and getFilteredDocument-
TypesWithField()

Collection of EbiDocType

Gets a Collection of all the document types that use a particular field.

Examples

Adding a document type with associated fields    This example provides a method called addDocType() that adds a document type called Movie Review and associates it with several existing fields. The addDocType() method needs to have access to a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments.

  public void addDocType(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get several fields by name
          EbiDocField fldDir = cmgr.getDocumentFieldByName(context, "Director");
          EbiDocField fldGenre = cmgr.getDocumentFieldByName(context, "Genre");
          EbiDocField fldYear = cmgr.getDocumentFieldByName(context, "Year");
          EbiDocField fldCast = cmgr.getDocumentFieldByName(context, "Cast");
          // Get the field IDs
          String[] fieldIDs = {
              fldDir.getFieldID(),
              fldGenre.getFieldID(),
              fldYear.getFieldID(),
              fldCast.getFieldID() };
  
          // Add the doctype
          EbiDocType dt = cmgr.addDocumentType(
              context,                            // context
              "Movie Review",                     // doctype name
              "Movie Review document type",       // description
              fieldIDs,                           // associated fields
              null);                              // ACL for the doctype
          System.out.println("The new doctype: " + dt);
      }

 
Top of section

Managing layout styles

Layouts are XSL specifications for rendering a document. The document might be XML or some other format that can be processed by XSL. The actual layout specification is stored as the content of a document in the repository. The Content Management subsystem has a document type called Document Layout already installed for layout documents. You can use it or add your own document types for layouts.

After you have added a layout document, you can check it out, modify it, and check it in. That means a particular layout document can have multiple versions. You can publish one of those versions.

You can group several layouts together under the umbrella of a layout style. The various layouts in the layout style can handle the rendering of the document for different clients (also called user agents), such as browsers, PDAs, and other display devices. The association of a layout document with a user agent is handled by a layout document descriptor.

A layout style is associated with a document type. When you display a document of that type, the system searches the layout document descriptors in the style to find the one for the user agent, as specified in the component's context object.

A layout style with multiple layout document descriptors can process content for various clients (also called user agents). When you want to display a document of the particular document type, you call getDocumentLayout() and the system will get the current user agent from the context object to select the appropriate layout.

Here is the group of objects that provide XSL processing for a content document:

NOTE   In addition to layout styles for document types, you can define a layout set for a specific document. A layout set is a custom combination of layout documents for a single content document. This specialized functionality is appropriate for special types of documents. When you are producing many documents of the same type, you will typically stick with layout styles for the document type. For more information, see Specifying layout sets for documents.

To set up layout styles for a document type:

  1. Add one or more layout styles for the content document type.

  2. Specify one of the styles as the default for that document type.

  3. Add one or more layout documents whose XSL is designed for the expected content. The versions can arrange the content differently or tailor the content for different clients.

  4. Add layout document descriptors that tie the layout documents to a client and a layout style.

These methods in EbiContentMgmtDelegate let you add and modify layout styles and their associated objects:

Method

Returns

Description

addDocumentLayoutStyle()

EbiDoc-
LayoutStyle

Adds a new Document Layout Style for the specified Document Type.

getDocumentLayoutStyle()

EbiDoc-
LayoutStyle

Gets the details of a particular layout style.

updateDocumentLayout-
Style()

void

Updates the information for a layout style in the Content Management subsystem.

removeDocumentLayout-
Style()

boolean

Removes a layout style from the system.

addLayoutDocument-
Descriptor()

EbiLayout-
DocDescriptor

Adds a layout document descriptor, associating a layout document with a layout style and user agent.

getLayoutDocument-
Descriptor()

EbiLayout-
DocDescriptor

Get a layout document descriptor object.

updateLayoutDocument-
Descriptor()

void

Updates a layout document descriptor with a new user agent.

removeLayoutDocument-
Descriptor()

boolean

Removes a layout document descriptor.

getLayoutDocument-Descriptors()

Collection of EbiLayout-
DocDescriptor

Gets the layout document descriptors associated with a layout style.

getDocumentLayout()

EbiDoc-
Version-
Descriptor

Gets the layout document appropriate for the current document and user agent. This is the actual XSL you use to process the content document.

getDefaultDocument-
LayoutStyle()

EbiDoc-
LayoutStyle

Gets the layout style that is the default for a document type.

getDocumentLayout-
Styles() and getFiltered-DocumentLayoutStyles()

Collection of EbiDoc-
LayoutStyle

Gets all the layout styles associated with a document type. The filtered version omits styles to which the current user has no READ access. The unfiltered version gets all styles for the type, regardless of access rights.

User agents

A user agent identifies itself in the HTTP header it sends to the server. Director stores the identifying string in the context object. The string used by a browser varies according to the browser version. Here are some examples:

  User Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
  User Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)
  User Agent: Mozilla/4.5 (Macintosh; U; PPC)
  User Agent: Mozilla/4.7 [en] (WinNT; I)
  User Agent: Mozilla/3.0 (compatible; Opera/3.0; Windows 95/NT) 3.1

You will need to use these strings in EbiLayoutDocumentDescriptor objects.

    For more information on user agents, see the HTTP 1.1 specification.

Examples

Adding a layout style    This example provides a method called addLayoutStyle() that adds a layout style for a document type called Movie Review. The addLayoutStyle() method needs to have access to a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments.

  public void addLayoutStyle(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Get the doctype for which the style is to be added
          EbiDocType dtMovieReviews = cmgr.getDocumentTypeByName(context, "Movie Review");
  
          // Add the new style
          EbiDocLayoutStyle style = cmgr.addDocumentLayoutStyle(
              context,                                             // context
              dtMovieReviews.getDocTypeID(),                       // doctype ID
              "MovieReviewStyle-PicOnLeft",                        // style name
              "Layout style for movie reviews, with pic on left",  // style descr
              true,                                                // is default style
              null);                                               // ACL for style
          System.out.println("The new style: " + style);
      }

Adding a layout document and layout document descriptor    This example provides a method called addLayoutDocAndDescriptor() that adds a layout document and a layout descriptor. The layout descriptor associates the layout document with the layout style from the previous example. The addLayoutDocAndDescriptor() method needs to have access to a content manager (EbiContentMgmtDelegate), context object (EbiContext), layout file name, and layout style, which are passed in as arguments.

  public void addLayoutDocAndDescriptor(
          EbiContentMgmtDelegate cmgr, EbiContext context, String layoutFileName, String layoutStyleID)
          throws
              EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException, FileNotFoundException, IOException
      {
          // Read in the XSL for the layout
          FileInputStream fis = new FileInputStream(layoutFileName);
          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();
  
          // Get the Document Layout doctype
          EbiDocType dtLayout = cmgr.getDocumentTypeByName(context, "Document Layout");
          // Get the Layouts folder
          EbiDocFolder layoutFolder = (EbiDocFolder)cmgr.lookupDirectoryEntry(
              context, "MyApp/Layouts", EbiDocFolder.EL_DOC_FOLDER);
  
          // Add the layout document
          EbiAddDocumentParams params = cmgr.createAddDocumentParams();
          params.setName("ReviewLayout-POL");
          params.setDocTypeID(dtLayout.getDocTypeID());
          params.setFolderID(layoutFolder.getID());
          params.setAuthor("JSmith");
          params.setTitle("ReviewLayout-POL");
          params.setSubtitle("This is the layout with picture on left");
          params.setMimeType("text/xsl");
          params.setContent(content);
          params.setComment("Initial revision.");
          // params.setAcl(...); specify an ACL, otherwise inherit ACL of parent folder
          EbiDocument layoutDoc = cmgr.addDocument(context, params);
          System.out.println("New layout doc: " + layoutDoc);
  
          // Publish the new layout document
          cmgr.publishDocumentContentVersion(context, layoutDoc.getID(), 1, true, true);
  
          // Figure out what user agent this layout is intended for...
          String userAgent = "User Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)";
  
          // Associate the new layout document with the specified layout style
          EbiLayoutDocDescriptor ldd = cmgr.addLayoutDocumentDescriptor(
  	 	     context,               // context
  	 	     layoutStyleID,         // layout style ID
  	 	     layoutDoc.getID(),     // layout document ID
  	 	     userAgent);            // user agent
      }

Changing a layout style    This presents a method called changeLayoutStyle() that gets the default style for a document type and changes it so that it is not the default. The changeLayoutStyle() method needs to have access to a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments.

  public void changeLayoutStyle(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          EbiDocType dtMovieReview = cmgr.getDocumentTypeByName(context, "MovieReview");
          EbiDocLayoutStyle style = cmgr.getDefaultDocumentLayoutStyle(context, dtMovieReview.getDocTypeID());
          style.setDefault(false);
          cmgr.updateDocumentLayoutStyle(context, style);
      }

 
Top of section

Managing folders and categories

Folders and categories are ways of organizing documents. A document belongs to one folder and can belong to many categories. Typically, you would use folders to group documents for administrative purposes, such as all documents for a project or documents that have access restrictions. You can use categories to organize documents as an end user might view them, typically by subject matter.

The system has a root folder and root category already created—called Root Folder and Root Category. The content manager provides the getRootFolder() and getRootCategory() methods to get EbiDocFolder and EbiDocCategory objects for them.

The default directory type for folders and categories is EbiDirectory.DIR_TYPE_DEFAULT. The root and system types apply to the root folder and root category. You can also define your own folder types. For information, see EbiDirectory in the API Reference.

These methods of EbiContentMgmtDelegate manage folders and categories:

Method

Returns

Description

addFolder()

EbiDocFolder

Creates a new folder.

copyFolder()

EbiDocFolder

Copies one folder into another.

getFolder()

EbiDocFolder

Gets a folder by name or ID.

moveFolder()

EbiDocFolder

Moves one folder into another.

updateFolder()

void

Updates a folder in the content repository after making changes to its properties via the EbiDocFolder object.

removeFolder()

boolean

Removes a folder. If the folder contains documents and subfolders, you can set the force argument to remove them too. The user must have WRITE permissions on all the subfolders and documents; otherwise, a security exception is thrown. If force is false, the folder can't be removed until the contents are deleted.

getRootFolder()

EbiDocFolder

Gets the top-level folder.

addCategory()

EbiDocCategory

Creates a new category.

copyCategory()

EbiDocCategory

Copies one category into another.

getCategory()

EbiDocCategory

Gets a category by name or ID.

moveCategory()

EbiDocCategory

Moves one category into another.

updateCategory()

void

Updates a category in the content repository after making changes to its properties via the EbiDocCategory object.

removeCategory()

boolean

Removes a category.

getRootCategory()

EbiDocCategory

Gets the top-level category.

addDocument-
CategoryReference()

void

Adds a document to a category.

removeDocument-
CategoryReference()

boolean

Removes a document from the category.

getDocumentCategory-
References() and getFilteredDocument-
CategoryReferences()

Collection of EbiDocCategory

Gets the categories to which the document belongs. The filtered version omits categories to which the current user has no READ access. The unfiltered version gets all categories for the document, regardless of access rights.

Example of adding a category

This example presents a method called addCategory() that gets the information required for creating a new category, then adds the new category as a subcategory of the specified parent. The addCategory() method needs to access a content manager (EbiContentMgmtDelegate) and context object (EbiContext), which are passed in as arguments.

  public void addCategory(EbiContentMgmtDelegate cmgr, EbiContext context)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // Locate the parent category
          EbiDocCategory categParent = (EbiDocCategory)cmgr.lookupDirectoryEntry(
              context, "MyApp/Shopping", EbiDocCategory.EL_DOC_CATEGORY);
          EbiDocCategory categChild = cmgr.addCategory(
              context,                            // context
              categParent,                        // parent category
              "Clothing",                         // new category name
              EbiDirectory.DIR_TYPE_DEFAULT,      // type of the new category
              "This is the clothing-related category", // description
              null);                              // ACL for the new category
          System.out.println("New category added: " + categChild);
      }

 
Top of page

Adding documents

A document in the Content Management 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 Director application. For ideas on the different types of information that can be documents, see Content and documents.

The Content Management 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.

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

Examples of adding documents

The following code examples show how to add single or multiple documents to the Content Management subsystem.

Adding a document   This 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);
      }

Adding multiple documents   This example presents a method called addMultipleDocuments() that converts a set of files into new documents of type Movie Review and adds them to the Content Management 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);
  
          }
      }

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:

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.

Examples

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

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

Setting a field value and associating the extension metadata with a new document   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);
      }

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

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.

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.

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.

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

Methods   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

Update 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().

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.

The content repository supports two types of document relationships:

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 component uses the ID of the original message as the parent of the new reply document:

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 ם, then 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.

Example of 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, then uses its title to construct the name and subtitle of the reply.

The addChildDocument() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), the parent document, message subject, and 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, 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.

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

Examples

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), a 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);
      }

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 the parent and child must exist. If not, use addDocumentLink() instead of updateDocumentLink().

The updateDocumentContentAndLink() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), the parent and child documents, document content, and 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
      }
  

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

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), 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 Content Management subsystem includes functionality that supports checkout, checkin, versioning, and publishing.

Much of the information in the Content Management 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.

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 components for source control and publishing to accomplish tasks like these:

 
Top of section

A document's status

To find out if a document is published, 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 component 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.

Example of 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), context object (EbiContext), and 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

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. Use other methods, such as getDocumentContentVersion(), to get the content for editing.

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

Finding documents

The Director Content Management subsystem is integrated with the Director Search subsystem to provide capabilities for conceptual and keyword searching of document content and metadata. The underlying technology is built around Application Builder, a toolkit from Autonomy, Inc. consisting of application programming interfaces (APIs) that provide access to conceptual query and index functionality of Autonomy's Dynamic Reasoning Engine (DRE).

The Content Management subsystem also provides its own built-in capability for SQL-based searching over document metadata.

 
Top of section

Autonomy-based conceptual searching

The Autonomy-based search technology gives you the ability to implement conceptual and keyword searching in your Director components. Traditional keyword searching returns all documents that contain occurrences of a search string. By contrast, conceptual searching matches concepts rather than simply finding literal text strings, thereby returning content that is related by meaning and ranked by relevance to the search criteria. As a result, conceptual search returns more relevant results and fewer false hits.

For more information about conceptual searching, see the chapter about the Search subsystem in the Search Guide.

eXtend Director comes with a data fetcher for the Director Content Management repository that propagates document content and metadata from the Content Management repository into the Director DRE where it is indexed. The related processes of propagating and indexing data is often called fetching. The Content Management subsystem communicates with the Director DRE through the Search API, as described in the chapter about the Search API in the Search Guide.

To implement Autonomy-based conceptual and keyword search in your Director applications, you use the Content Management API functionality that wrappers the relevant Search APIs:

The wrapper classes provide methods for constructing and running queries on content and metadata that reside in the Content Management repository and have been indexed by the Director DRE.

In addition, you can configure your environment to manage the processes of document fetching and querying, as described in the section on setting search options in the chapter on using the Search subsystem in the Search Guide.

CAUTION   The Content Management data fetcher that comes with Director allows you to conduct Autonomy-based searches exclusively on content and metadata stored in theDirector Content Management repository. To use Autonomy technology with Director to search data sources other than the Content Management repository, you must purchase additional data fetchers from Autonomy, Inc. and use Search API classes to implement data fetching and querying.

Key classes and interfaces for Autonomy-based searching

Key classes and interfaces for implementing Autonomy-based searching of content and metadata in the Content Management repository include:

Class or Interface

Description

Package

EbiContentMgmtDelegate

Delegate for accessing objects that implement the EbiContentManager interface, which allows you to run Autonomy-based queries on standard metadata, custom metadata, and content in the Content Management repository.

com.sssw.cm.api

EbiQuery

Interface that provides methods for constructing various types of Autonomy-based queries and setting query properties

com.sssw.search.api

EbiQueryResult

Interface that provides methods for processing the results of Autonomy-based queries.

com.sssw.cm.api

EboFactory

Factory class that provides methods for getting content manager delegates

com.sssw.cm.client

EboFactory

Server-side factory class that provides methods for instantiating objects that implement the EbiQuery interface for constructing Autonomy-based queries

com.sssw.cm.factory

Methods for basic Autonomy-based search functions

This section describes methods that you can use to perform basic functions.

Getting delegates

The method for getting the content manager delegate is getDefaultContentMgmtDelegate(), called on com.sssw.cm.client.EboFactory. This method returns a content manager delegate associated with the Default Director Content Management repository.

You can run Autonomy-based queries on this object to search document content, standard metadata, and custom metadata stored in the Default Content Management repository.

For more information about why to use delegates, see Programming practices.

Constructing queries

The EbiQuery interface for constructing Autonomy-based queries resides in the Search subsystem API. You must use the Search API method getQuery() method to instantiate an object that implements this interface, then call Search API methods on this query object to construct Autonomy-based queries and fine-tune search results. The key methods for constructing and configuring Autonomy-based queries are the following:

Method

Description

com.sssw.search.factory.EboFactory.
getQuery()

Instantiates a blank EbiQuery object that can be used to construct Autonomy-based queries.

com.sssw.search.API.EbiQuery.
setQueryType()

Specifies the type of query you want to run.

For more information, see the section on query types in the chapter that describes the Search API in the Search Guide.

com.sssw.search.API.EbiQuery.
setQueryText()

Specifies the query string.

com.sssw.search.API.EbiQuery.
setMaxNumResults()

Sets the maximum number of results to return.

com.sssw.search.API.EbiQuery.
setRelevanceCut()

Sets the minimum relevance criteria for query results.

For more information, see the chapter that describes the Search API in the Search Guide.

Running queries

You run Autonomy-based queries by calling the runQuery() method on the content manager delegate associated with the Default Director Content Management repository. You can also run queries via the Search subsystem by calling EbiQueryEngineDelegate.runQuery(), as described in the chapter on the Search API in the Search Guide.

Processing query results

You can call methods on EbiQueryResult to process your Autonomy-based query results. EbiQueryResult inherits methods from com.sssw.search.api.EbiQueryResult to allow you to get and set properties on your query results. It also inherits methods from com.sssw.cm.api.EbiDocument and com.sssw.cm.api.EbiDocConetent to allow you to retrieve content and metadata from your search results.

Programming practices

This section describes the best practices for using the Content Management API (in conjunction with the Search API) to implement conceptual searching in components for your Director applications.

Using delegates

The Content Management subsystem lets you use delegates to access the content manager. A delegate is a wrapper that hides the location of a service. The delegate model follows the J2EE Business Delegate pattern.

When you use a delegate, you do not need to know whether the service is using a local manager object or an EJB. The delegate initially attempts to instantiate a local manager. If this fails, it attempts to use an EJB instead. This approach allows developers to use the same code on clients and servers to instantiate services.

For more information about delegates, see the chapter on coding Java for Director applications in the Core Development Guide.

Logic flow

Here is the recommended logic flow for developing a search component. Add this logic to the setComponentData() method of your component:

  1. Configure your search environment, as described in the section on setting search options in the chapter on using the Search subsystem in the Search Guide.

    NOTE   The Content Management data fetcher supplied with Director automatically initiates the process of fetching data, based on how you set synchronization mode.

  2. Instantiate a blank query object.

  3. Set the query type.

  4. Specify the query expression.

  5. Set other parameters such as maximum number of results to return and relevance cut.

  6. Get an object that implements the EbiContentMgmtDelegate interface for running the query.

  7. Run the query.

  8. Process the results.

For more information about writing Director components, see the chapter on developing components in the Portal Guide.

Code example

Here is an example of a getComponentData() method that illustrates the recommended logic flow for running a conceptual query:

  ...
  public void getComponentData( EbiPortalContext context, java.util.Map params ) throws com.sssw.fw.exception.EboUnrecoverableSystemException 
  {
     //Declare a string buffer
     StringBuffer sb = new StringBuffer();
  
     //Set the query string
     String queryString = "The+effect+of+the+recession+on+consumer+spending";
  
     try
     {
        //Create a blank query object
        com.sssw.search.api.EbiQuery query = com.sssw.cm.factory.EboFactory.getQuery();
  
        //Set query type to text
        query.setQueryType(query.QUERY_TYPE_TEXT);
  
        //Specify the query string. This is a conceptual query
        query.setText(queryString);
  
        //Ask for a maximum of 50 results
        query.setMaxNumResults(50);
  
        //Ask for results that are at least 80% relevant
        query.setRelevanceCut(80);
  
        //Ask to return all available document properties in the results
        query.selectAll();
  
        //Get the content manager delegate
        EbiContentMgmtDelegate contentMgr = com.sssw.cm.client.EboFactory.getDefaultContentMgmtDelegate();
  
        //Run the query
        //The boolean argument in runQuery indicates whether results should be filtered
        Iterator iterResults = contentMgr.runQuery(context, query, true).iterator();
  
        //Process the results
        while (iterResults.hasNext())
        {
           com.sssw.cm.api.EbiQueryResult res = (com.sssw.cm.api.EbiQueryResult)iterResults.next();
           //Get document metadata
           String docTitle = res.getTitle();
           java.sql.Timestamp dateCreated = res.getDateCreated();
  
           //Get document content
           String docAbstract = res.getAbstract();
  
           //Add query result to the string buffer returned by the component
           sb.append("\n").append(docTitle).append(dateCreated).append(docAbstract).append("\n");
        }
     }
     catch (Exception _E)
     {
        System.out.println ("Query failed");
        _E.printStackTrace();
     }
     //Set content type
     context.setContentType(com.sssw.portal.api.EbiComponentConstants.MIME_TYPE_HTML_UTF8);
  
     //Place the content into the context
     context.setComponentContent( sb.toString() );
  }
  ...

Note that this component retrieves standard metadata—the document title and the date created—as well as content from the query results. To make sure this data is returned in the query results, you must configure the Director DRE to index standard metadata and content by setting the following search options in the Content Management subsystem configuration file:

The Content Management subsystem provides many other configurable options that you can set to customize your search environment. For more information, see the section on setting search options in the chapter on using the Search subsystem in the Search Guide.

Querying content and metadata

You can query content and metadata using a single query.

When you use the Content Management data fetcher supplied with Director, you specify what types of data to search—content, standard metadata, and/or custom metadata—as described in the section on setting search options in the chapter on using the Search subsystem in the Search Guide. Then you use the Content Management API to instantiate a query object and run the query using a method defined on an EbiContentMgmtDelegate object, as described in Programming practices.

Supported queries

Autonomy-based searching allows you to run the following types of queries in Director applications:

Type of query

Description

Boolean

Uses logical operators to refine search criteria.

Conceptual

Returns content that is related by meaning and ranked by relevance to the search criteria.

Field

Searches metadata in documents, or metadata and content in a single query.

Fuzzy

Tries to match terms even when they are misspelled.

Keyword

Looks for occurrences of a search string.

Name

Searches for proper names.

Proximity

Specifies that certain words in the query expression must occur close to each other.

Suggest similar documents

Tries to find documents similar to other documents that were found to be relevant to the search criteria.

Thesaurus

Analyzes not only the terms in the query expression, but also the associated terms—or synonyms— that you define in a separate Thesaurus Dynamic Reasoning Engine (DRE).

For more information about these Autonomy-based queries and how to implement them, see the section on query types in the chapter that describes the Search API in the Search Guide.

 
Top of section

SQL-based searching

In the Content Management subsystem you can find documents whose metadata or content contain specific values. There are three ways you can search:

To perform a query, you write code that calls:

  1. The EbiContentMgmtDelegate method createQuery(), specifying the type of query you want to perform

  2. Methods of the particular query object, specifying what data to return and what the WHERE clause and ORDER BY criteria are

  3. The EbiContentMgmtDelegate method findElements(), which executes the query and returns a Collection of EbiDocument or EbiDocContent objects

The EbiDocument and EbiDocContent objects contain only the fields that you specify via the SELECT methods. They are not complete representations of the object in the content repository. If you call a get method for a field that was not part of the query, the method will return null.

For example, you might search the document content for a phrase, but return only the document ID and size. Using the ID, you can display a list of document names and sizes; and the user can click a link to see the document content, which you can display by calling getContent().

Finding documents according to values of the metadata

You can search the standard and extension metadata for documents by creating an EbiDocQuery object:

  EbiDocQuery query = (EbiDocQuery) cmgr.createQuery(EbiDocQuery.DOC_QUERY);

The EbiDocQuery object has numerous methods for specifying the metadata fields you want to select and search.

To select the fields to be returned, call one of the inherited SELECT methods.

To specify the search criteria, call one of the WHERE methods of EbiDocQuery, which creates a EbiQueryExpression object. You can create several expression objects and call methods of EbiQueryExpression to concatenate them using AND or OR, as well as parentheses. (For more details, see Building the search criteria.)

To execute the search, you call findElements(), which returns a collection of EbiDocument objects. The EbiDocument objects contain the document ID plus the data for the fields you selected. Data for other fields is not available, and methods to get that data return null.

Building the search criteria

For each of the standard metadata fields, you can choose one of several WHERE methods to specify search criteria for that field. The methods can match a value against the data using a SQL, relational, or string operator. Each method includes a NOT parameter that can negate the clause. The full set of WHERE methods are listed in EbiDocQuery.

A summary of the operators defined in com.sssw.fw.api.EbiMetaDataQuery are:

Constant

Definition

SQL operators

OP_BETWEEN

SQL BETWEEN operator

OP_IN

SQL IN operator

OP_IS_NULL

SQL IS NULL operator (the value argument in the where method is not ignored)

Relational operators

ROP_EQUAL

Is equal to (=)

ROP_GEQ

Is greater than or equal to (>=)

ROP_GREATER

Is greater than (>)

ROP_LEQ

Is less than or equal to (<=)

ROP_LESS

Is less than (<)

String operators

SOP_ENDS_WITH

Whether the target string ends with the specified character sequence

SOP_EQUALS_IGNORE_CASE

Whether two strings are equivalent without considering case

SOP_LIKE

SQL LIKE operator

SOP_LIKE_IGNORE_CASE

SQL LIKE operator, where the case of the operands is ignored

SOP_STARTS_WITH

Whether the target string begins with the specified character sequence

Using Title for an example, you can call these three methods:

When you need WHERE expressions for several metadata fields, you connect them together using methods of EbiQueryExpression. Here are some patterns that assign the result to expression1:

To search an extension metadata field, you create one expression for the field IDs you want to search and another expression for the value to search for. For the field ID, you would usually use:

  whereFieldID(int value, int op, boolean not) 

For field values, you might use any of these:

  whereFieldValue(java.lang.Object fieldValue, int op, boolean not) 
  whereFieldValueBetween(java.lang.Object first, java.lang.Object last, boolean not) 
  whereFieldValueIn(java.lang.Object[] values, boolean not) 

After you create an expression for the field ID and another for the field value, you concatenate the two using the AND method and the parenthesize() method, which restricts the search to that field and values. You can search another field by setting up another pair of expressions in the same way and concatenating the result with the rest of the WHERE clause.

Example of searching metadata for documents

This example presents a method called executeDocMetaSearch() that finds documents of type Movie Review that meet these search criteria:

The EbiDocument objects in the returned collection contain all the properties that have been defined for the movie reviews in ascending order by creation date.

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

  public void executeDocMetaSearch(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          String mrDocTypeID, String yorFieldID)
          throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException
      {
          // The search condition: find all the Movie Review documents whose:
          // (Author is 'JSmith' or whose Title starts with 'A')
          // AND
          // whose YearOfRelease was between the year 1990 and the year 2000.
  
          EbiDocQuery docQuery = (EbiDocQuery)cmgr.createQuery(EbiDocQuery.DOC_QUERY);
          docQuery.selectAll();
  
          EbiQueryExpression expr = docQuery.whereDocTypeID(mrDocTypeID, EbiDocQuery.ROP_EQUAL, false);
          EbiQueryExpression expr2 = docQuery.whereAuthor("JSmith", EbiDocQuery.ROP_EQUAL, false);
          EbiQueryExpression expr3 = docQuery.whereTitle("A", EbiDocQuery.SOP_STARTS_WITH, false);
          EbiQueryExpression expr4 = docQuery.whereFieldID(yorFieldID, EbiDocQuery.ROP_EQUAL, false);
          EbiQueryExpression expr5 = docQuery.whereFieldValueBetween(
              EboMisc.getInteger(1990), EboMisc.getInteger(2000), false);
  
          // (Author is 'JSmith' or Title starts with 'A)
          expr2.orExpression(expr3);
          expr2.parenthesize();
  
          // YearOfRelease was between the year 1990 and the year 2000
          expr4.andExpression(expr5);
  
          // (Author is 'JSmith' or whose Title starts with 'A')
          // AND
          // YearOfRelease was between the year 1990 and the year 2000
          expr.andExpression(expr2);
          expr.andExpression(expr4);
  
          docQuery.setWhere(expr);
  
          // Sort results by creation date/time, in ascending order
          docQuery.orderByCreateDate(true);
  
          // Execute the search
          Collection results = cmgr.findElementsFiltered(context, docQuery);
      }

Finding folders and categories and their contents

Categories and folders form two separate hierarchies of nested directories, starting from a root category or folder. The main difference between the two is that a document belongs to one and only one folder, but may belong to zero or more categories. In this discussion, directory refers to both folders and categories.

In the Content Management subsystem, you can add directories to the root directory and to subdirectories to any level of nesting, described in Managing folders and categories. Once your directory hierarchy is established, you can get a listing of the contents of a directory and examine the properties of individual entries.

This section describes some ways to use the methods and classes that navigate the directory hierarchy. Both categories and folders implement the functionality for directory manipulation found in their superinterface EbiDirectory. Folders, categories, and documents also implement EbiDirectoryEntry and share methods for getting information about the contents of a directory.

These methods are useful in navigating categories and folders:

Example    This example builds an XML DOM tree of nested categories, starting with the root category. The root category is a category element within Categories; subcategories of the root and further nested levels are category elements also. The name and ID for each category are attributes.

The code creates the Categories container element and gets the root category of the tree you want to build. It then calls addNode() to find and add its subcategories. The variable dom is the DOM object and root is the root element of the DOM.

    For a working component that uses this technique, see component/documentmgmt/CategoryTreeBase.java.

  Element categories = dom.createElement("Categories");
  root.appendChild(categories);
  
  EbiDocCategory category = cmgr.getRootCategory(context);
  if (category == null)
     System.out.println("root category is null");
  else
  {
     Element rootCategory = dom.createElement("category");
     categories.appendChild(rootCategory);
     rootCategory.setAttribute("id", category.getID());
     rootCategory.setAttribute("name", category.getName());
     addNode(rootCategory, category, dom, context, 
        cmgr, "category");
  }

The addNode() method gets the subcategories of a particular category and adds them as child elements. It is called recursively to add additional levels of nested subcategories if they exist.

  public void addNode(org.w3c.dom.Element element, 
  EbiDirectoryEntry directoryEntry, org.w3c.dom.Document document, 
  EbiContext context, EbiContentMgmtDelegate cmgr, String elementName)
  {
     try 
     {
        Collection collection = cmgr.getFilteredDirectoryList(
           context, (EbiDirectory) directoryEntry, true, false);
        Enumeration list = Collections.enumeration(collection);
        if (list != null)
        {
           Element child;
           while (list.hasMoreElements())
           {
              EbiDirectoryEntry subdirEntry =
                 (EbiDirectoryEntry) list.nextElement();
              child = document.createElement(elementName);
              child.setAttribute("id", subdirEntry.getID());
              child.setAttribute("name", subdirEntry.getName());
              element.appendChild(child);
              addNode(child, subdirEntry, document,
                 context, cmgr, elementName);
           }
        }
     }
     catch (Exception e) 
     {
        e.printStackTrace();
     }
  }

 
Top of page

Displaying documents

Components 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 component might simply get and set the content, as shown below:

  EbiContentMgmtDelegate cm = null;
  try {
    cm = (EbiContentMgmtDelegate)
     com.sssw.fw.factory.EboFactory.getManager(
     EbiPortalConstants.PORTAL_CONTENT_MGR);
  } 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)
     {
       byte [] html = content.getData();
       String shtml = new String(html);
       context.setComponentContent(shtml);
       context.setContentType(EbiComponentConstants.MIME_TYPE_HTML);
     }
  
  } 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 component 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), context object (EbiContext), and 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));
              context.setComponentContent(content);
  
              // set type according to results of xsl transformation
              context.setContentType(EbiComponentConstants.MIME_TYPE_HTML);
          }
      }

 
Top of section

Composite documents

A composite document could be constructed in many different ways. It is up to your component 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 component 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 component's code. You may want to formalize that structure in a DTD. The XML structure might look like this (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.

 
Top of page

Security for the Content Management subsystem

You can specify access restrictions based on user ID or group membership on most objects in the Content Management subsystem. You can use access restrictions to:

For example, you can specify that a folder and its documents have read-only access or that a document type cannot be changed.

You specify access restrictions via an ACL. To provide support for ACLs, Director implements the java.security.acl.Acl interface.

For every content management action, Director checks whether the user specified in the EbiPortalContext object has permission to perform the specified action. If an object has an ACL, Director checks whether the user has been granted the specified permission. These situations can occur:

Situation

Access outcome

The object doesn't have an ACL

The action proceeds

The object has an ACL but the user is not included by name or by group

Access is denied; EboSecurityException

The user is in the ACL for the EbiContentAdmin with permission for the particular type of access (permissions for EbiContentAdmin override permissions on individual objects)

The action proceeds

The object has an ACL that includes the user (by ID or group) and the user has permission for the particular type of access

The action proceeds

The object has an ACL that includes the user (by ID or group) and the user has been denied the particular type of access

Access is denied; EboSecurityException

The Content Management subsystem determines whether the user has permission to access an element in three steps:

  1. Does the element have an ACL?

  2. Does the user have permission in the element's ACL?

  3. Is the user an administrator by having PROTECT access for EbiContentAdmin?

    NOTE   For information on administrators, see Roles for users of the Content Management subsystem.

 
Top of section

Securable objects and access right types

Objects that can have access restrictions implement the EbiSecurableElement interface. Each of the objects has a set of supported access right types. The supported types are defined as String constants in each object's interface.

The access right types include:

Type

Description

PROTECT

Allows the users and groups in the ACL to change permissions on the object.

READ

Allows the users and groups in the ACL to view the object or get the metadata for an object.

WRITE

Allows the users and groups in the ACL to make changes to the object, by updating the object programmatically or by checking in a new version of a document. A user who has been denied WRITE access cannot check out a document.

LIST

Allows the users and groups in the ACL to view a list of the objects that this object contains. This includes the documents and subfolders of a folder, the documents and subcategories of a category, and the documents associated with a document type.

PUBLISH

For documents, allows the users and groups in the ACL to change the published status of the document. They can publish it and remove it from the published area.

The table that follows lists the securable objects (not including some securable superinterfaces) and the access right types they support.

Object

Access right types

EbiContentAdmin

PROTECT, READ, WRITE

EbiDocType

PROTECT, READ, WRITE, LIST

EbiDocField

PROTECT, READ, WRITE

EbiDocCategory

PROTECT, READ, WRITE, LIST

EbiDocFolder

PROTECT, READ, WRITE, LIST

EbiDocument

PROTECT, READ, WRITE, PUBLISH

EbiDocLayoutStyle

PROTECT, READ, WRITE

EbiLayoutDocDescriptor

PROTECT, READ, WRITE

 
Top of section

Roles for users of the Content Management subsystem

A comprehensive security policy must set different permissions for different roles. Typical roles in the Content Management subsystem are:

Role

Description

Author

Has read and write access for documents; has read, write, and list access for folders and categories

Publisher

Has publish access for documents; has list access for folders and categories

Administrator

Has all rights, including protect, to all objects

Users are considered administrators when the ACL assigned to EbiContentAdmin gives them at least one of the permissions. If they have all permissions, you could think of them as super-administrator.

When setting up users and groups for Director, you will want to consider how your users fall into these roles and create appropriate groups. You can use those user IDs and groups to create ACLs that implement your security. You might create a master ACL that you can get and reuse throughout the Content Management subsystem.

 
Top of section

Setting the ACL for an object

ACLs for new objects   For securable objects, you can specify an ACL when you create the object. It is an argument of the object's add method.

Inheriting ACLs   For the following objects, if you don't specify an ACL when you create them, the settings of their container are copied to the new object:

New

Copy the ACL of their

Folders

Parent folder

Documents

Folder

Layout descriptors

Layout style

After the object is created, there is no further connection to the container's ACL. Changes to a container's ACL have no effect on the contained objects.

For other object types, if you don't specify an ACL, they have an empty ACL.

ACLs for existing objects   For securable objects, you can call the getAcl() and setAcl() methods to get and change the ACL associated with an object.

You can set permissions for an object's ACL by calling:

    For information about using the security methods of EbiSecurityManager, see the chapter on authorization in the User Management Guide.

 
Top of section

Methods for Content Management subsystem security

These methods of EbiContentMgmtDelegate let you set security for objects:

Method

Returns

Description

getAcl()

java.security.acl.-
Acl

Gets the ACL for a securable element: category, field, folder, layout style, layout document descriptor, document type, or document

setAcl()

void

Assigns an ACL to a securable element

isAuthorized()

boolean

Checks whether the user identified in the context object is authorized for the specified type of access for an object

getAdminElement()

EbiContentAdmin

Gets the administration object that holds the ACL that identifies the users and groups that have administrator access to content objects

Examples

This section provides examples that demonstrate a number of techniques for setting ACLs on objects and handling security exceptions.

For information on adding users and groups to ACLs, see the section on setting up ACL-based security in the User Management Guide.

Setting ACLs on objects   This example presents a method called demonstrateSecurity() that illustrates the following techniques:

The demonstrateSecurity() method needs to access a content manager (EbiContentMgmtDelegate), context object (EbiContext), and principal—all of which are passed in as arguments.

  public void demonstrateSecurity(
          EbiContentMgmtDelegate cmgr, EbiContext context,
          Principal principal)
          throws
              EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException, EboFactoryException, NotOwnerException
      {
          EboPermission readPerm = EboPermission.getPermission(
              context.getEbiSession(), EboPermission.READ);
          EboPermission writePerm = EboPermission.getPermission(
              context.getEbiSession(), EboPermission.WRITE);
  
          // Add READ access to the Content Admin element to the passed in principal
          EbiContentAdmin adminElement = cmgr.getAdminElement(context);
          Acl admAcl = cmgr.getAcl(context, adminElement);
          AclEntry aclEntry = com.sssw.fw.factory.EboFactory.getAclEntry();
          aclEntry.setPrincipal(principal);
          aclEntry.addPermission(readPerm);
          admAcl.addEntry(principal, aclEntry);
          cmgr.setAcl(context, adminElement, admAcl);
  
          // Add a folder with an ACL
          Acl acl = com.sssw.fw.factory.EboFactory.getAcl();
          aclEntry = com.sssw.fw.factory.EboFactory.getAclEntry();
          aclEntry.setPrincipal(principal);
          aclEntry.addPermission(readPerm);
          aclEntry.addPermission(writePerm);
          cmgr.addFolder(
              context,
              cmgr.getRootFolder(context),
              "Movie Reviews",
              EbiDocFolder.DIR_TYPE_DEFAULT,
              "Folder for movie reviews",
              acl);
  
          // Add a folder with no ACL -- it will inherit the ACL
          // from its parent folder (if there is an ACL set on the parent)
          EbiDocFolder frFolder = cmgr.addFolder(
              context,
              cmgr.getRootFolder(context),
              "Financial Reports",
              EbiDocFolder.DIR_TYPE_DEFAULT,
              "Folder for financial reports",
              null);
  
          // This code adds an ACL to an existing folder.
          cmgr.setAcl(context, frFolder, acl);
      }

Handling security exceptions   This example presents a method called demonstrateHandleExceptions() that illustrates how to handle a security exception (and other exceptions as well).

This code publishes version 2 of a document whose ID is assigned to the variable docid. The publishDocumentContentVersion() method will throw an EboSecurityException if the user is not allowed to publish the specified document. This example handles the exception by adding an error message to the context object. The component can then include the error message in its generated content so the user knows what went wrong.

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

  public void demonstrateHandleExceptions(
          EbiContentMgmtDelegate cmgr, EbiContext context, String docID)
      {
          try
          {
              cmgr.publishDocumentContentVersion(context, docID, 2, true, true);
          }
          catch (EboSecurityException se)
          {
              se.printStackTrace();
              String msg = "Security violation: " + se.toString();
              context.setValue("error", "User does not have access. " + msg);
          }
          catch (EboUnrecoverableSystemException use)
          {
              use.printStackTrace();
              String msg = "Unrecoverable exception: " + use.toString();
              context.setValue("error", msg);
          }
          catch (EboItemExistenceException iee)
          {
              iee.printStackTrace();
              String msg = "Item existence exception: " + iee.toString();
              context.setValue("error", msg);
          }
      }
  }

 
Top of page

Importing and exporting Content Management data

The Content Management API includes EbiImporter and EbiExporter, two powerful, flexible interfaces for importing and exporting data into and out of a Director Content Management system.

Potential uses of the functionality provided by EbiImporter and Ebi exporter include:

Importing and exporting data in the PMC   The Import and Export facilities of the PMC implement a subset of the functionality of EbiImporter and EbiExporter. Using these facilities, you can import and export Content Management data without writing any Java code.

For a description of the import and export facilities of the PMC, see Importing and exporting content.

 
Top of section

Methods for exporting Content Management data

These methods of EbiExporter allow you to export Content Management data:

Method

Returns

Description

selectAllFields()

void

Selects all fields for export

mustExportAllFields()

boolean

Tells whether all fields are to be exported

mustExportFields()

boolean

Tells whether any fields are to be exported

selectFields()

void

Selects a set of fields for export

selectField()

void

Selects a specific field for export

getSelectedFields()

EbiDocField[]

Returns a list of all selected fields

selectAllDoctypes()

void

Selects all document types for export

selectDoctype()

void

Selects a specific document type for export

mustExportAllDoctypes()

boolean

Tells whether all doctypes are to be exported

mustExportDoctypes()

boolean

Tells whether any document types are to be exported

selectDoctypes()

void

Selects a set of doctypes to be exported

getSelectedDoctypes()

EbiDocType[]

Returns a list of all selected document types

selectAllStyles()

void

Selects all layout styles for export

selectStyle()

void

Selects a specific layout style for export

mustExportAllStyles()

boolean

Tells whether all document layout styles are to be exported

mustExportStyles()

boolean

Tells whether any styles are to be exported

selectStyles()

void

Selects a set of document layout styles for export

getSelectedStyles()

EbiDocLayoutStyle[]

Returns a list of all selected layout styles

selectAllFolders()

void

Selects all folders for export

mustExportAllFolders()

boolean

Tells whether all folders are to be exported

selectFolder()

void

Selects a specific folder for export

mustExportFolders()

boolean

Tells whether any folders are to be exported

selectFolders()

void

Selects a set of folders for export

getSelectedFolders()

EbiDocFolder[]

Returns a list of all selected folders

selectAllCategories()

void

Selects all categories for export

selectCategory()

void

Selects a specific category for export

mustExportAllCategories()

boolean

Tells whether all categories are to be exported

mustExportCategories()

boolean

Tells whether any categories are to be exported

selectCategories()

void

Selects a set of categories to be exported

getSelectedCategories()

EbiDocCategory[]

Returns a list of all selected categories

selectAllDocuments()

void

Selects all documents for export

selectDocument()

void

Selects a specific document for export

mustExportAllDocuments()

boolean

Tells whether all documents are to be exported

mustExportDocuments()

boolean

Tells whether any documents are to be exported

selectDocuments()

void

Selects a set of documents for export

selectDocuments()

void

Selects documents for export by providing a query that is to be run in order to determine the scope of documents to be exported

getDocumentQuery()

com.sssw.fw.api.-
EbiQueryBase

Returns the document scope query, if any was set via the selectDocuments method

getSelectedDocuments()

EbiDocument[]

Returns a list of all selected documents

selectContentAdmin()

void

Selects the Content Admin element for export

mustExportContentAdmin()

boolean

Tells whether the Content Admin element is to be exported

selectAllLinks()

void

Selects all document links for export

mustExportAllLinks()

boolean

Tells whether all document links are to be exported

selectLinks()

void

Selects a set of document links for export

getSelectedLinks()

EbiDocLink[]

Returns a list of all selected document links

selectLinks()

void

Selects a set of document links for export

getLinkQuery()

com.sssw.fw.api.-
EbiQueryBase

Returns the document link query, if it was set by the selectLinks method

selectAllElements()

void

Selects all Content Management elements for export, including:

  • fields

  • document types

  • layout styles

  • folders

  • categories

  • documents

  • document links

  • the Content Admin element

mustExportAll()

boolean

Tells whether all Content Management elements are selected for export

selectElement()

void

Selects a specific Content Management element for export

setOutputStream()

void

Sets the output stream for writing the export data

getOutputStream()

OutputStream

Returns the output stream that has been specified

setUseElementIDs()

void

Sets the option for whether Content Management element UUIDs are to be used in the output XML

mustUseElementIDs()

boolean

Tells whether Content Management element UUIDs are to be used in the output XML

Examples

For code examples on exporting Content Management data, see the Javadoc topic on EbiExporter.

 
Top of section

Methods for importing Content Management data

These methods of EbiImporter allow you to import data into a Content Management system:

Method

Returns

Description

importDocuments()

Collection

Imports document content and other data from a set of XML files into the Content Management System

setZipInputStream()

void

Sets the input data source for the Importer to be an archive

getZipInputStream()

ZipInputStream

Returns the input zip input stream, if any was set.

setCheckOutDocs()

void

Specifies whether to check out all the imported documents to the user whose context is passed in to the execute() method.

setPublishDocs-
Immediately()

void

Specifies whether documents should be published immediately after being added by the Importer.

setCreateNonexistent-
Folders()

void

Sets the option to create any folders that do not exist but whose URLs are mentioned in the input import XML such as the document XML.

setCreateNonexistent-
Categories()

void

Sets the option to create any categories that do not exist but whose URLs are mentioned in the input import XML such as the document XML.

setFieldsOverwrite()

void

Sets the field overwrite options.

getFieldsOverwrite()

EbiElementOverwrite

Returns the field overwrite options

setDoctypesOverwrite()

void

Sets the doctype overwrite options.

getDoctypesOverwrite()

EbiElementOverwrite

Returns the doctype overwrite options.

setStylesOverwrite()

void

Sets the style overwrite options.

getStylesOverwrite()

EbiElementOverwrite

Returns the style overwrite options.

setFoldersOverwrite()

void

Sets the folder overwrite options.

getFoldersOverwrite()

EbiElementOverwrite

Returns the folder overwrite options.

setCategoriesOverwrite()

void

Sets the category overwrite options.

getCategoriesOverwrite()

EbiElementOverwrite

Returns the category overwrite options.

setDocumentsOverwrite()

void

Sets the document overwrite options.

getDocumentsOverwrite()

EbiElementOverwrite

Returns the document overwrite options.

setLinksOverwrite()

void

Sets the link overwrite options.

getLinksOverwrite()

EbiElementOverwrite

Returns the link overwrite options.

setTargetFolder()

void

Sets the target folder for the import operation.

getTargetFolder()

EbiDocFolder

Returns the target folder (defaults to the Root Folder).

mustCheckOutDocs()

boolean

Tells whether the Importer is to check out any documents it creates at execution time, to the user whose context is set into the Importer via the setContext method.

mustPublishDocs-
Immediately()

boolean

Tells whether any added documents must be published immediately.

mustCreateNonexistent-
Folders()

boolean

Tells whether the tool must create any non-existent folders.

mustCreateNonexistent-
Categories()

boolean

Tells whether the tool must create any non-existent categories.

Examples

For code examples on importing Content Management data, see the Javadoc topic on EbiImporter.


   

Content Management Guide  

Copyright © 2002, SilverStream Software, Inc. All rights reserved.