Content Management Guide
CHAPTER 3
This chapter describes how to manage documents using the Content Management (CM) API. It has these sections:
NOTE: Most of the document management tasks described in this chapter can also be accomplished using the CMS Administration Console.
For more information, see Creating Content. and Maintaining Content.
A document in the CM subsystem may represent a simple, finite piece of content such as an image, or it may be a complex entity that comprises other documents. A document can be any data that you want to use directly or indirectly in your exteNd Director application.
The CM subsystem uses metadata fields to describe a document. There are standard fields for every document, such as name, title, author, and abstract. You can also associate content-related fields with a document type. This extension metadata can hold additional searchable information specific to that document type.
A document object can be associated with an EbiDocContent object that holds the text or binary data, but a document doesn't need to have a content object. The metadata for the document may store all the information you need. For a short text document, you could store the entire text in the abstract field. If the document doesn't have content, specify null for the MIME type and content.
The supplied content, if any, becomes the first version of the document. If you want to publish the content, you can call publishDocumentContentVersion() anytime or rely on your scheduled task to publish it. Documents without content cannot have versions (including a published version), but you could use another field (such as status) to label a document as publicly available.
The EbiContentMgmtDelegate interface provides access to most of the document-related methods in the CM subsystem.
For information, see About the CM API.
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 anyas 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.
|
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. |
This code example presents a method called addDocument() that illustrates how to add a document of type Movie Review. This method sets all required document parametersdocument type, name, title, author, and parent folderas 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); }
This code example presents a method called addMultipleDocuments() that converts a set of files into new documents of type Movie Review and adds them to the CM subsystem.
This method sets all required document parametersdocument type, name, title, author, and parent folderas 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); } }
When you add a document, you must create a set of field values that match the fields defined for the document's type. Each field can have one or more values, and null values are allowed. The fields and their values are called extension metadata, in contrast to the standard metadata defined for an EbiDocument object (such as title, author, abstract, and status).
You manage the extension metadata via two objects:
Object |
Description |
---|---|
EbiDocExtnMeta |
A holder for all the extension metadata for all the fields |
EbiDocExtnMetaInfo |
Associates a field with a set of values |
After you create an EbiDocExtnMetaInfo object for a specific field, you set the values for the field as an array, even if there is only one value. The type of the array must correspond to the data type of the field.
After you've created an EbiDocExtnMetaInfo object for each field and added it to the EbiDocExtnMeta object, call setExtensionMetaData() for EbiAddDocumentParams to associate it with the document you are adding.
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); } }
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); }
This example presents a method called setFieldValues() that performs the following tasks:
Creates an EbiDocExtnMeta holder and EbiDocExtnMetaInfo objects for the Director and Genre fields
Associates the EbiDocExtnMeta object with an EbiAddDocumentParams object that it uses to add the new document to the content respository
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); }
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 interestall 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); } }
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 interestall 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);
This table lists methods that let you manage documents, edit the metadata, and get 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.
What a layout set is good for A layout set is meant for locking in a presentation so that the document always looks the same. As layout styles for a document type evolve with new versions, the presentation of an individual document will change. Use a layout set when it is important to preserve the original presentation.
What a layout set is less appropriate for The layout set is less appropriate for giving a document a unique look. It may be more appropriate to add a new document type. However, you can also add a custom style to the document type in order to make a special layout available for the document. If you don't want to be constrained to styles for the document type, you could design your application to locate style documents another wayfor 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.
These methods of EbiContentMgmtDelegate manage layout sets:
To associate a layout set with a new document, call the setLayoutSet() method of EbiAddDocumentParams.
To change the XSL documents in the layout set of an existing document, call getDocumentLayoutSet(), call methods of EbiDocLayoutSet to make changes, and then call updateDocumentLayoutSet().
NOTE: Currently, you cannot add a layout set to a document if it didn't have one when it was added.
You can specify relationships between documents by specifying that one document is a child of another.
This section includes these topics:
The content repository supports two types of document relationshipshierarchical and compound
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.
Hierarchical linking lets you create a threaded discussion. The following diagram shows two views of a threaded discussion. Each reply has one parent, and each message can be the parent of several replies. The top message in each chain has no parent.
When a user submits a reply, the application uses the ID of the original message as the parent of the new reply document:
These methods of EbiContentMgmtDelegate are useful in managing hierarchical links:
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.
This example presents a method called addChildDocument() that creates a child document as a reply in a message thread. Inside a while loop, the method navigates the thread to the top message, and then uses its title to construct the name and subtitle of the reply.
The addChildDocument() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent document, a message subject, and a replyall 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); }
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 portlet inserts each child document as a node in the DOM with an appropriate element name. An XSL style sheet specifies how those elements are displayed. You don't have to insert the child documents into existing content in any particular order. The order is determined by the style sheet. By selecting different style sheets, you can change the way the different elements are displayed and whether they are included at all.
For 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.
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:
This example presents a method called addDocLink() that adds a link between a parent document and a child document.
The addDocLink() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent and child documents, and the child document versionall 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); }
This example presents a method called updateDocumentContentAndLink() that creates and publishes a new version of a child document, then updates the link from the parent to point to the new version.
If a new version of the child document is published later, this link continues to point to the old version. A link between parent and child must exist. If not, you need to use addDocumentLink() instead of updateDocumentLink().
The updateDocumentContentAndLink() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), the parent and child documents, document content, and a MIME typeall 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 }
This example presents a method called getLinkParentDocuments() that gets the parent documents that are linked to a specified child.
By calling getFilteredLinkParentDocuments(), the code retrieves only documents to which the user has READ access.
The getLinkParentDocuments() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the child document of interestall 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); }
This example presents a method called getLinkChildDocuments() that gets the child documents that are linked to a specified parent.
By calling getFilteredLinkChildDocuments(), the code retrieves only documents to which the user has READ access.
The getLinkChildDocuments() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the parent document of interestall 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); }
The CM subsystem includes functionality that supports checkout, checkin, versioning, and publishing.
Much of the information in the CM subsystem is data about documents. However, when you start using the checkout and checkin methods, you also get multiple versions of document content. Each time a document is checked in, a new version is created. When a document is published, there is also a released version of the content, which comes from the set of versions. You can continue creating new versions, while the publicly available version remains stable.
The diagram that follows shows the relationship between an EbiDocument object, which holds the document metadata, and its version objects. The content for each version is stored in an EbiDocVersion object. When you select a version for publishing, that version's content is copied to an EbiDocContent object.
NOTE: It is important to remember that only the content has multiple versions. There is only one version of the document's metadata.
You might program portlets for source control and publishing to accomplish tasks like these:
To find out if a document is published, you call the EbiDocument method getPublishStatus(). If it returns null, then the document has no published content.
A publish date does not automatically reflect the time the document was published. It just indicates when it should be published; for example, a publish date of null means publish immediately. However, your publishing portlet can set the publish date if you want to track the date a document became available.
The document's status field is available for your own document tracking. You can establish your own application-specific set of status values and update the document's status field to reflect its progress through your document processing procedures. For example, you could specify submitted, reviewed, approved, rejected, published, unpublished, archived, and purged as status values for your application.
Setting document status This example presents a method called setDocumentStatusToRejected() that sets a document's status to rejectedperhaps to indicate that the document has been rejected by a content administrator and requires further changes before it can be published. Note that after setting status, you must call the updateDocument() method for the change to take effect.
The setDocumentStatusToRejected() method needs to access a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the document of interestall 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); }
These methods of EbiContentMgmtDelegate are available for source control and publishing:
Portlets in your online application get a document's metadata and content, retrieve linked content, and use the associated layout styles to display the document to the user.
If the content type of a document is HTML and it has no linked documents, the portlet might simply get and set the content, as shown below:
EbiContentMgmtDelegate cm = null; try { cm = com.sssw.cm.client.EboFactory.getDefaultContentMgmtDelegate(); } catch (EboFactoryException ebfe) { throw new EboUnrecoverableSystemException(ebfe, "Unable to get ContentManager"); } try { EbiDocument doc = (EbiDocument) cm.lookupDirectoryEntry(context, "MyFolder/TDBDoc1", EbiDocument.EL_DOCUMENT); EbiDocContent content = cm.getContent(context, doc.getID(), true); if (content != null) { PrintWriter writer = response.getWriter(); byte [] html = content.getData(); String shtml = new String(html); writer.print(shtml); } } catch (EboItemExistenceException eiee) { throw new EboUnrecoverableSystemException(eiee, "Unable to get Content"); } catch (EboSecurityException ese) { throw new EboUnrecoverableSystemException(ese, "Security exception"); }
If the content of a document is an XML String and it has no linked documents, the portlet could get the content and the document layout (also as an XML String) and use the layout XSL to transform the XML.
This concept is illustrated in the displayContent() example method shown below. In this example, methods in com.sssw.fw.util.EboXmlHelper convert a String to a DOM and apply an XSL transformation to a DOM. The displayContent() method accesses a content manager (EbiContentMgmtDelegate), the context object (EbiContext), and the document of interestall of which are passed as arguments:
public void displayContent( EbiContentMgmtDelegate cmgr, EbiPortalContext context, String docID) throws EboUnrecoverableSystemException, EboSecurityException, EboItemExistenceException { EbiDocument doc = (EbiDocument)cmgr.lookupDirectoryEntry( context, "MyFolder/TDBDoc1", EbiDocument.EL_DOCUMENT); EbiDocContent doccnt = cmgr.getContent(context, doc.getID(), true); if (doccnt != null) { byte[] xml = doccnt.getData(); EbiDocVersionDescriptor layoutver = cmgr.getDocumentLayout( context, docID, EbiContentMgmtDelegate.COMPARE_ALL, true); EbiDocVersion layoutcnt = cmgr.getDocumentContentVersion( context, layoutver.getDocumentID(), layoutver.getDocumentVersionID(), true); byte[] xsl = layoutcnt.getData(); String sxml = new String(xml); String sxsl = new String(xsl); String content = EboXmlHelper.processXML( EboXmlHelper.getDOM(sxml), EboXmlHelper.getDOM(sxsl)); // Set type according to results of xsl transformation response.setContentType(EbiPortletConstants.MIME_TYPE_HTML); // Use a PrintWriter to render writer.print(content); } }
A composite document could be constructed in many different ways. It is up to your portlet to gather the pieces and put them together in an appropriate way. Typically, you would build an XML DOM for the composite document and add elements for each piece. For a simpler composite document where the pieces are HTML fragments, you might concatenate them into a larger HTML fragment.
To illustrate the process of building an XML DOM, suppose you are displaying a movie review, a document of type Movie Review. The content of the movie review document is the text paragraphs of the review. The document's metadata provides the title, author, and other information specific to the Movie Review type, such as genre, director, year of release, and cast. Child documents refer to an image of the movie and cast biographies. To display all the data, the portlet builds an XML DOM of the pieces and provides an XSL style sheet for display specifications.
You will want to plan an XML structure for defining the XSL and building the DOM in the portlet's code. You may want to formalize that structure in a DTD. The XML structure might look like this (shown without closing tags):
<REVIEW> <TITLE> <AUTHOR> <GENRE> <DIRECTOR> <CAST> <CASTMEMBER> <CASTPICTURE> <BIO> </CASTMEMBER> <CASTMEMBER> <CASTPICTURE> <BIO> </CASTMEMBER> </CAST> <CONTENT> </REVIEW>
The coding steps might be:
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.
Get the cast metadata and add a CAST element, with child CASTMEMBER elements for each one.
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.
Call getLinkChildDocuments() to get the linked child documents.
For each linked document, get the MIME type and other information to determine the document's purpose:
For an image from the film, add a MOVIEPICTURE element whose attributes have information needed by the XSL to build an image link.
For a cast biography, find the corresponding CASTMEMBER element and add a child BIO element. Depending on the page design, you could insert information to build a link or include the paragraphs.
For a picture of a cast member, find the CASTMEMBER element and add a CASTPICTURE element with information to build an image link.
When the XML DOM is complete, call methods of the context object to set the MIME type and the content.
Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved. more ...