Create an IBM Lotus WCM site structure with one click

 

+

Search Tips   |   Advanced Search

 

 

Introduction

If you work with IBM Lotus Web Content Management, one of your recurring tasks is defining site structure. This task by its nature is time-consuming and repetitive; you are required to take more than 10 distinct steps to create a single site or site area. Moreover, site structures are not portable by design; you cannot export your site structure from one library on one server to a different library on a different server. Instead, you need to recreate the entire site structure manually.

Because the number of sites and site areas that make up a single site structure can reach the thousands, you need a method to automate the process of defining the site structure and to make it easier to move, export, and import. In this article, we use Lotus WCM APIs to define your site structure as an XML file and deploy it accordingly.

NewsSiteStructure.xml contains the site structure and is validated against SiteCreation.xsd.

 

Prerequisites

  1. Create these prerequisites:

    • Lotus WCM library
    • Authoring templates to be used in the site structure
    • Presentation templates to be used in the site structure
    • Users to be used in the security settings section
    • Workflows, workflow actions, and workflow stages to be used in the authoring templates

  2. Define the site structure in the form of an XML file, NewsSiteStructure.xml, which specifies...

    • library
    • sites
    • site areas
    • etc...

  3. Create a JSP component to parse NewsSiteStructure.xml and create the site areas defined in it.

 

Create the XML site file

Create an XML file that conforms to your requirements.

The XML site file contains all the information needed to create the site structure, including...

  • library name
  • site structure
  • site area structure
  • default contents

...to create...

 

Listing 1. XML example used in the creation of the site structure

<Library Name="Library" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="SiteCreation.xsd">

  <Site Name="SITE" DisplayName="SITE">

  <SiteArea Name="News" DisplayName="News">

      <Settings>

        <TemplateMapping>
          <AuthoringTemp>auth_news</AuthoringTemp>
          <PresentationTemp>pt_newsDetail</PresentationTemp>
        </TemplateMapping>

        <SecuritySettings>
          <AccessRight Type="addReadAccessMembers">
            <Access>[all authenticated portal users]</Access>
            <Access>anonymous portal user</Access>
          </AccessRight>
        </SecuritySettings>

      </Settings>

      <DefaultContent>
        <Name>Default_News</Name>
        <DisplayName>Default_News</DisplayName>
        <AuthoringTemp>auth_news</AuthoringTemp>
        <TextComponent>    
          <FieldName>txt_headline</FieldName>
          <Value>Headline for default Content</Value>
        </TextComponent>
        <RichTextComponent>    
          <FieldName>rtf_body</FieldName>
          <Value>Body for the default Content</Value>
        </RichTextComponent>
      </DefaultContent>    

      <SiteArea Name="2009News" DisplayName="2009 News">

        <DefaultContent>
          <Name>Default_News</Name>
          <DisplayName>Default_News</DisplayName>
          <AuthoringTemp>auth_news</AuthoringTemp>
          <TextComponent>    
            <FieldName>txt_headline</FieldName>
            <Value>Headline for default Content</Value>
          </TextComponent>
          <RichTextComponent>    
            <FieldName>rtf_body</FieldName>
            <Value>Body for the default Content</Value>
          </RichTextComponent>
      </DefaultContent>            

    </SiteArea>        

    <SiteArea Name="2008News" DisplayName="2008 News">

      <DefaultContent>
        <Name>Default_News</Name>
      </DefaultContent>            

    </SiteArea>        

  </SiteArea>

  <Settings><!Site Settings -
      <TemplateMapping>
        <AuthoringTemp>auth_news</AuthoringTemp>
        <PresentationTemp>pt_newsDetail</PresentationTemp>
      </TemplateMapping>
      <SecuritySettings>
        <AccessRight Type="addReadAccessMembers">
          <Access>[all authenticated portal users]</Access>
          <Access>anonymous portal user</Access>
        </AccessRight>
      </SecuritySettings>
    </Settings>
  </Site>

</Library>

Figure 2 shows a sample mapping between the XML elements and the output created after you implement the solution.

As you can see, the mapping from the actual site structure to NewsSiteStructure.xml is straightforward with a root element representing the library. This root element then contains another element that corresponds to the site, defining its name and display name. Site areas are defined in a nesting fashion in NewsSiteStructure.xml to obtain the required site structure.

Every site and site area contains a settings section that holds the security settings and template mapping sections. The following are restrictions that need to considered: Security settings and template mapping can be created for each site or site area in its respective element or in the highest site or site area in the tree, with its child elements inheriting them.

Content security settings and workflows are added in the authoring template component, not in the default content section in NewsSiteStructure.xml.

Authoring templates and presentation templates used in the template mapping and in the creation of the default content have to be created previously.

Default content can be reused in multiple site areas by defining its name. After you define a complete default content element in NewsSiteStructure.xml, you can then use it by defining a default content tag with only the name element. This feature of reusing the default content in different and multiple places can also be used if the default content already exists for that library.

 

XML schema validations

To avoid missing data that Lotus WCM requires for site creation, you need to have NewsSiteStructure.xml conform to an XSD. This conformance guarantees that the validations listed in table 1 hold true.

 

Table 1. XML schema element/ attributes validations

Element Element/attribute Type Valid range Value
Library Sites Element 0..n NA
Library Name Attribute Mandatory string
Site SiteArea Element 0..n NA
Site Name Attribute Mandatory string
Site DisplayName Attribute Optional string
Site Settings Element Optional NA
SiteArea SiteArea Element 0..n NA
SiteArea Name Attribute Mandatory string
SiteArea DisplayName Attribute Optional string
SiteArea Settings Element Optional NA
SiteArea DefaultContent Element Optional NA
DefaultContent Name Element Mandatory NA
DefaultContent DisplayName Element Optional NA
DefaultContent AuthoringTemp Element Optional (if item already created before) NA
DefaultContent TextComponent Element 0..n NA
DefaultContent RichTextComponent Element Optional NA
TextComponent FieldName Element Mandatory (referencing the Lotus WCM TextComponent field name as in the authoring template) NA
TextComponent TextComponent Element Mandatory NA
TextComponent FieldName Element Mandatory (referencing the Lotus WCM RichTextComponent field name as in the authoring template) NA
TextComponent TextComponent Element Mandatory NA
Settings TemplateMapping Element 0..n NA
Settings SecuritySettings Element Optional NA
TemplateMapping AuthoringTemp Element Mandatory (references the Lotus WCM authoring template name) NA
TemplateMapping PresentationTemp Element Mandatory (references the Lotus WCM presentation template) NA
SecuritySettings AccessRight Element 0..n NA
AccessRight Type Attribute Mandatory addReadAccessMembers/

addEditAccessMembers

or

addDeleteAccessMembers

AccessRight Access Element 1..n NA

 

JSP component

Now that you have defined your site structure in an XML file that conforms to the XSD, you need to create a JSP component to handle the parsing of NewsSiteStructure.xml and do the actual Lotus WCM site creation using the Lotus WCM APIs to import your site structure into the Lotus WCM library.

Select...

New | JSP component

Create the JSP component with the name jsp_createSiteStructure, and let it point to a JSP file whose path is...

/jsp/html/createSiteStructure.jsp

Store your JSP components in the local Rendering portlet. The physical path of the JSP file is in a directory similar to...

c:\IBM\Portal61\wp_profile\installedApps\WCM_Local_ng_Portlet_PA_dvme0nk.ear\PA_dvme0nk.war\jsp\html\createSiteStructure.jsp

The JSP file creates a button called...

Create Site Structure

...that, when clicked, starts parsing NewsSiteStructure.xml by first parsing every site. The path to NewsSiteStructure.xml can be edited. The file used in listing 3 is assumed to be at the same location as the JSP file. The code gets the workspace and connects to the library defined in the file. See the code in listing 3.

 

Listing 3. The JSP file that creates the new comment content

<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
.
.
.
<%@ include file="wcmUtil.jsp"%>
<FORM name="form1" method="post" action="#">
        
    <INPUT TYPE="HIDDEN" NAME="buttonName" VALUE="CreateSiteStructure">
           
    <INPUT TYPE="SUBMIT" value="Create Site Structure">
</FORM>
<%
 try {           
          
// If button clicked if( request.getParameter("buttonName") !=  null && request.getParameter("buttonName").equals("CreateSiteStructure")) {

  // Path to NewsSiteStructure.xml containing the site structure
  File file = newFile("/opt/app/WebSphere/PortalServer/installedApps/WCM_Local_ng_
  Portlet_PA_dm010y1.ear/dm010y1.war/jsp/html/NewsSiteStructure.xml");
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(file);

            
      doc.getDocumentElement().normalize();

      Element docEle = doc.getDocumentElement();            
      String libraryName = docEle.getAttribute("Name");
                
      System.out.println("libraryName = " +libraryName);
      workspace = openWorkspaceLibrary(request, libraryName);
         
      // Retrieve all site elements
      NodeList nl = docEle.getElementsByTagName("Site");        
         
      //loop over site elements
      if(nl != null) {
        for(int i = 0 ; i < nl.getLength();i++) {
    
          Element el = (Element)nl.item(i);
          Site site = createSite(el);
                    
          DocumentId siteId =  site.getId();
          System.out.println("site = "+ site.getName());
                    
          //for every site element, retrieve site area child elements
          NodeList SiteAreaNodeList = el.getChildNodes();    
          for (Node node = el.getFirstChild(); node != null; 
          node = node.getNextSibling()) {
          if (node.getNodeType() == Node.ELEMENT_NODE && 
          node.getNodeName().equals("SiteArea")) {
          Element siteAreaEL = (Element)node;
                            
            SiteArea sa = createSiteArea(siteAreaEL, siteId);
            if (sa != null){
            System.out.println("site area = " + sa.getName());
            }
            else{
            out.println("Error in creation of site area tree, 
            check logs for more information about the error");
            }
          }
        }
      }
    }        
    closeWorkspace();    
    out.println("Cretion Completed");                
  }
    }catch(FileNotFoundException e){
      out.println("XML File not found!");
    }catch (org.xml.sax.SAXParseException saxEx){
      out.println("Exception In parsing document: "+ saxEx.getMessage());
    } 
    catch (Exception e) {
      System.out.println("Exception: "+ e.getClass());
      e.printStackTrace();
    }     
%>

A utility class is used that contains all helper methods used from the JSP code to create the site structure. For this article's purpose, a JSP component can be created called wcmUtil.jsp that contains all those methods. The JSP component is included in createSiteStructure.jsp, as it is shown in listing 3, using the following listing <%@ include file="wcmUtil.jsp"%>.

Listings 4 - 20 show the methods used in a helper class to create the site structure.

 private Workspace workspace;
/*
    *Connect to Lotus WCM workspace with current user if 
    *logged in or anonymous if user is not logged in
    *
    *Set the Lotus WCM document library to aLibraryName
*/ public Workspace openWorkspaceLibrary(HttpServletRequest request, String aLibraryName)  throws ServiceNotAvailableException, OperationFailedException {
    // Connect to WCM Workspace
    if (request.getUserPrincipal() != null)
    {
        workspace = WCM_API.getRepository().getWorkspace
        (request.getUserPrincipal());
    } else
    {
        workspace = WCM_API.getRepository().getAnonymousWorkspace();
    }
    
    //set library to the passed library name
    if (workspace != null) {
        DocumentLibrary docLib = workspace.getDocumentLibrary
        (aLibraryName);
        if(docLib != null){
            workspace.setCurrentDocumentLibrary(docLib);
        }
    }
    
    return workspace;
}

/*
    *Parse site element 
    *If site already available, retrieve the site object, edit the site
    *If site not already created, create a new site and set the name and 
    *display name and its settings
    *Save the site to the workspace
*/ public Site createSite(Element aSiteElement){
    
    String siteName = aSiteElement.getAttribute("Name");
    String siteDisplayName = aSiteElement.getAttribute("DisplayName");
    Site site = null;    
    try{
    
        DocumentId siteId = getWCMDocumentByName(siteName, DocumentTypes.Site);
        if (siteId != null){
            site = (Site)workspace.getById(siteId);
        }
        else{
            site = workspace.createSite();        
            site.setName(siteName);
        }
        site.setTitle(siteDisplayName);            
        site = (Site)retrieveAddSettings(site, aSiteElement, false);    
        
        workspace.save(site);
    
    }catch(Exception e){
        System.out.println("Exception = "+e);
        e.printStackTrace();
        
    }    
    return site;
} 

 

Listing 6. Parse and create site area

/*
*Parse site area element 
*If site area already available, retrieve the site area object, edit the site area
*If site area not already created, create a new site area and set the name 
*and display name and its settings
*Add a default content to the site area if available
*Save the site area to the workspace
*/ public SiteArea createSiteArea(Element aSiteAreaElement, DocumentId parentId){
  String siteAreaName = aSiteAreaElement.getAttribute("Name");
  String siteAreaDisplayName = aSiteAreaElement.getAttribute("DisplayName");
        
  SiteArea sa = null;
  try{
    String parentPath = workspace.getPathById(parentId,  true, true);
    String siteAreaPath = parentPath+ "/"+ siteAreaName;
    DocumentId siteAreaId = getWCMDocumentByPath(siteAreaPath,  
    Workspace.WORKFLOWSTATUS_ALL);
                
    if (siteAreaId != null){
      sa = (SiteArea)workspace.getById(siteAreaId);
    }else{
      sa = workspace.createSiteArea(parentId, null, 1);
    }
        
    sa = (SiteArea)retrieveAddSettings(sa, aSiteAreaElement, true);            
    if (sa != null){
      sa.setTitle(siteAreaDisplayName);
            
      sa.setName(siteAreaName);    
      workspace.save(sa);
      sa = addDefaultContentToSiteArea(sa, aSiteAreaElement);            
            
      if (sa != null){
            
        boolean saved = saveToWorkspace(sa);
        System.out.println("site area = " + sa.getName());
                
        if (!saved){
          return null;
        }                    
                
        //checking if site area contains any other site area children
        NodeList SiteAreaNodeList = aSiteAreaElement.getChildNodes();
                
        for (Node node = aSiteAreaElement.getFirstChild(); node != null; 
        node = node.getNextSibling()) {
          if (node.getNodeType() == Node.ELEMENT_NODE && 
          node.getNodeName().equals("SiteArea")) {
          Element siteAreaEL = (Element)node;
                        
            SiteArea childSA = createSiteArea(siteAreaEL, sa.getId());
            if (childSA != null){
            System.out.println("childSA  for = " +sa.getName()+ " = 
            " + childSA.getName());
          }
          else{
          return null;
          }
        }
      }                
    }
      else{
        return null;
      }
    }            
    return sa;
  }catch(Exception e){
    System.out.println("Exception = "+e);
    e.printStackTrace();
        
  }        
  return null;
}

 

Listing 7. Parse and create default content

/*
*Parse the default content element 
*If content already available, retrieve the content object, and edit it
*If content not already created, create a new content object and set the 
*name and display name and its settings
*If authoring template provided, overwrite if already set
*Add text components and rich text components to the content
*Save the default content to the site area
*/ public SiteArea addDefaultContentToSiteArea(SiteArea aSiteArea,  Element aSiteAreaElement){
    
    DocumentId defaultContentId = null;                
    
    Element defaultel = getChildByName(aSiteAreaElement, "DefaultContent");
    String contentName = getElementValueByTagName("Name", defaultel);
    
    defaultContentId = getWCMDocumentByName(contentName, DocumentTypes.Content);
    
    Content content = null;        
    
    String contentDisplayName = getElementValueByTagName("DisplayName", defaultel);
    
    String authoringTempName = getElementValueByTagName("AuthoringTemp", defaultel);
    
    DocumentId defaultAuthId = null;
    
    if (! authoringTempName.equals("")){
      defaultAuthId = getWCMDocumentByName(authoringTempName, 
      DocumentTypes.AuthoringTemplate);
        
    }
    System.out.println("defaultAuthId = "+ defaultAuthId);
    try{
        
      //if content already existing in the library, re-use it
      if (defaultContentId != null){
        content = (Content)workspace.getById(defaultContentId);
             
        //if authoring template provided in the file, overwrite the existing one
        if (defaultAuthId != null){
          content.setAuthoringTemplateID(defaultAuthId);
        }
      }
      else if (defaultAuthId != null){
        //if content not available, create a new one
        content = workspace.createContent(defaultAuthId, aSiteArea.getId(),null, 
        ChildPosition.START);
           defaultContentId = content.getId();
           content.setName(contentName);
      }
      else{
        System.out.println("Exception = Authoring Template for default content "+ 
        contentName + " is missing");
        return null;
      }
        
      if (! contentDisplayName.equals("")){
        content.setTitle(contentDisplayName);
      }
        
      content = retrieveAddTextComponentToContent(content, defaultel);
        
      if (content == null){
        return null;
      }
      content = retrieveAddRichTextComponentToContent(content, defaultel);
        
      if (content == null){
        return null;
      }
         while(!content.isPublished()){ content.nextWorkflowStage();
} workspace.save(content);
        
  }catch(Exception e){
    System.out.println("Exception = "+e);
    e.printStackTrace();                            
  }
    
  System.out.println("defaultContent  for = " +aSiteArea.getName()+ " = " + 
  defaultContentId.getName());
  aSiteArea.setDefaultContent(defaultContentId);            
  return aSiteArea;
}

 

Listing 8. Parse text component

/*
*Parse DefaultContent element 
*Search for text component elements
*Looping over all text component child elements
*Calling method addTextComponent to add the 
*text component to the content
*/ public Content retriveAddTextComponentToContent(Content aContent,  Element aContentElement){
    
  NodeList texttnl = aContentElement.getChildNodes();
    
  for (Node node = aContentElement.getFirstChild(); 
  node != null; 
  node = node.getNextSibling()) {
    if (node.getNodeType() == 
    Node.ELEMENT_NODE && 
    node.getNodeName().equals("TextComponent")) {
      Element textCompel = (Element)node;
        
      String textField = 
      getElementValueByTagName("FieldName", textCompel);                
      String text = 
      getElementValueByTagName("Value", textCompel);
      aContent = 
      addTextComponent(aContent, textField, text);
                                
      if (aContent != null){
        System.out.println("adding textField = 
        "+ textField+" to content "
        +aContent.getName());                        
      }
    }
  }    
  if (aContent == null){
    return null;
  }
  else{
        
    return aContent;
  }
    
}

 

Listing 9. Parse rich text component

/*
*Parse DefaultContent element 
*Search for rich text component elements
*Looping over all rich text component child elements
*Calling method addRichTextComponent to add the rich text 
*component to the content
*/ public Content retrieveAddRichTextComponentToContent
(Content aContent, Element aContentElement){
  NodeList richTexttnl = aContentElement.getChildNodes();
  for (Node node = aContentElement.getFirstChild(); node != null; 
  node = node.getNextSibling()) {
    if (node.getNodeType() == Node.ELEMENT_NODE && 
    node.getNodeName().equals("RichTextComponent")) {
      Element richtextCompel = (Element)node;
            
      String textField = 
      getElementValueByTagName("FieldName", 
      richtextCompel);                    
      String text = 
      getElementValueByTagName("Value", 
      richtextCompel);                
            
      aContent = 
      addRichTextComponent(aContent, textField, text);
            
      if (aContent != null){
        System.out.println("adding richtextField = 
        "+ textField+" to content "+
        aContent.getName());                        
      }
    }
  }
  if (aContent == null){
    return null;
  }
  else{
    return aContent;
  }
}

 

Listing 10. Create and add text component

/*
* Get text component from the content according to 
*the text component name
* Set the text component with the value sent
* Add the text component to the content
*/ public Content addTextComponent
(Content aContent, String aTextField, String aValue){
    
    try{            
        TextComponent txtComp = 
        (TextComponent) aContent.getComponent(aTextField);
        txtComp.setText(aValue);        
        aContent.setComponent(aTextField,  txtComp);
    }catch(ComponentNotFoundException ex){
        System.out.println
        ("Exception: "+aTextField+" is not a valid TextComponent");
        return null;
    }catch(Exception e){
        System.out.println("Exception = "+e);
        return null;
    }
    
    return aContent;
}

 

Listing 11. Create and add rich text component

/*
* Get rich text component from the content according to the RTF name
* Set the rich text component with the value sent
* Add the rich text component to the content
*/ public Content addRichTextComponent(Content aContent,  String aTextField, String aValue){
    try{
        RichTextComponent richTxtComp = 
        (RichTextComponent) aContent.getComponent(aTextField);
        richTxtComp.setRichText(aValue);        
        aContent.setComponent(aTextField,  richTxtComp);
        RichTextComponent rtf = 
        (RichTextComponent)aContent.getComponent(aTextField);
    }catch(ComponentNotFoundException ex){
        System.out.println("Exception: 
        "+aTextField+" is not a valid RichTextComponent");
        return null;
    }catch(Exception e){
        System.out.println("Exception = "+e);
        return null;
    }
    
    return aContent;
}

 

Listing 12. Parse settings element

/*
*Parse site area or site element 
*Search for settings element
*call method retrieveAddTemplateMapping to add template mapping to site or site area
*call method addSecuritySettings to add security settings to site or site area
*/ public Object retrieveAddSettings(SiteFrameworkContainer aWCMObject,  Element aObjectElement, boolean isSiteArea){

    Element settingsel = getChildByName(aObjectElement, "Settings");
    if ( settingsel!= null){
        if(isSiteArea )
        {
            aWCMObject = (SiteArea)retrieveAddTemplateMapping
            (aWCMObject, settingsel);
            aWCMObject = (SiteArea)addSecuritySettings
            (aWCMObject, settingsel);
        }
        else
        {
            aWCMObject = (Site)retrieveAddTemplateMapping
            (aWCMObject, settingsel);
            aWCMObject = (Site)addSecuritySettings
            (aWCMObject, settingsel);
        }
    }
    return aWCMObject;
}

 

Listing 13. Add SecuritySettings to Lotus WCM objects

/*
*Parse settings element 
*Search for SecuritySettings element
*For every SecuritySettings element, find the AccessRight element
*loop over the AccessRight elements and get the type of the access
*According to the access type, a specific method in Lotus 
*Web Content Management 
*will be called to add the access rights
*/ public Object addSecuritySettings
(SiteFrameworkContainer aWCMObject, Element settingsel){
    
  for (Node node = settingsel.getFirstChild(); node != null; 
  node = node.getNextSibling()) {
    if (node.getNodeType() == Node.ELEMENT_NODE && 
    node.getNodeName().equals("SecuritySettings")) {
      Element secel = (Element)node;    
      NodeList accessRightsnl = secel.getChildNodes();
            
      for (Node accessRightNode = secel.getFirstChild(); accessRightNode != 
      null; accessRightNode = accessRightNode.getNextSibling()) {
        if (accessRightNode.getNodeType() == Node.ELEMENT_NODE && 
        accessRightNode.getNodeName().equals("AccessRight")) {
         Element accessRightsel = (Element)accessRightNode;
                
         String accessType = accessRightsel.getAttribute("Type");
                    
         NodeList accessnl = accessRightsel.getChildNodes();
                    
         if(accessnl != null ) {    
        
            for(int y = 0 ; y < accessnl.getLength();y++) {            
                            
              Node accnode = accessnl.item(y);
                            
           if (accnode.getNodeType() == 
           accnode.ELEMENT_NODE && 
           accnode.getNodeName().equals("Access")) {
           Element el = (Element)accnode;            
           String access = el.getFirstChild().getNodeValue();    
           if (accessType.equals("addReadAccessMembers")){
           aWCMObject.addReadAccessMembers(new String[]{access});
             System.out.println("addReadAccessMembers for Object = 
             "+aWCMObject.getName()+" members = "+access);
              }else if(accessType.equals
              ("addEditAccessMembers")){
              aWCMObject.addEditAccessMembers(new String[]{access});
              System.out.println("addEditAccessMembers for Object = 
                "+aWCMObject.getName()+" members = 
                "+access);
                
              }else if(accessType.equals
              
              ("addDeleteAccessMembers")){    
                                                      
              aWCMObject.addDeleteAccessMembers
              (new String[]{access});
              System.out.println
              ("addDeleteAccessMembers for Object = 
              "+aWCMObject.getName()+" members = "+access);
            }        
                                                    
          }
        }
      }    
    }
  }        
  }        
  }    
    return aWCMObject;
}

 

Listing 14. Parse and add Template Mapping SiteArea

/*
*Parse settings element 
*Search for TemplateMapping element
*For every TemplateMapping element
*Get the authoring template and presentation template names
*Retrieve the Lotus WCM object from the names
*If item already contains a template mapping with the same authoring template, 
*remove it and add the new one
*Else, add the new template mapping
*Save the object, either the site or site area
*/ public Object retrieveAddTemplateMapping
(SiteFrameworkContainer aWCMObject,  Element settingsel){
  DocumentId authId = null;
  DocumentId presId = null;
        
  NodeList tempnl = settingsel.getChildNodes();
    
  for (Node node = settingsel.getFirstChild(); node != 
  null; node = node.getNextSibling()) {
    if (node.getNodeType() == Node.ELEMENT_NODE && 
    node.getNodeName().equals("TemplateMapping")) {
      Element tempel = (Element)node;
            
      String authoringTemp = 
      getElementValueByTagName("AuthoringTemp", tempel );
      String presTemp = 
      getElementValueByTagName("PresentationTemp", tempel );
            
      authId = getWCMDocumentByName(authoringTemp, 
      DocumentTypes.AuthoringTemplate);
               
      presId = getWCMDocumentByName(presTemp, 
      DocumentTypes.PresentationTemplate);
                               
      if (authId != null){
        try{
        if (aWCMObject.hasTemplateMapping(authId)){
        }
                    
        if (!aWCMObject.hasTemplateMapping(authId)){
          aWCMObject.addTemplateMapping(authId, presId);    
        }
        else{
                
          DocumentIdIterator docIt = aWCMObject.getAuthoringTemplateIds();
            if (docIt.hasNext()){
          DocumentId dids = (DocumentId)docIt.next();
          aWCMObject.removeTemplateMapping(dids);
          aWCMObject.addTemplateMapping(authId, presId);            
        }
    }
                    
          System.out.println("TemplateMapping authName = "+authoringTemp+" 
          and presName = "+presTemp +" added to object " + aWCMObject.getName());
          workspace.save(aWCMObject);
          }catch(Exception e){
          System.out.println("Exception ="+e);
          e.printStackTrace();
        }
        }else{
    return null;
    }
  }
}
    
  return aWCMObject;        
}

 

Listing 15. Saving Lotus WCM objects to the workspace

/*
 * This is a helper method that receives a Lotus WCM 
 * document object and adds it to the workspace
 */ public boolean saveToWorkspace(com.ibm.workplace.wcm.api.Document wcmDocument){

    try{
        String[] errors = workspace.save(wcmDocument);
                    
        for (int i = 0; i < errors.length; i++){
            System.out.println("Error while saving "+ 
            wcmDocument.getName()+ " : "+errors[i]);
        }
        if (errors.length > 0 ){
            return false;
        }
    }catch(Exception e){
        System.out.println("Exception = "+e);
        e.printStackTrace();
        return false;
    }        
    return true;        
}

 

Listing 16. Retrieve Lotus WCM objects by path

/*
 * This is a helper method that retrieves a Lotus WCM 
 * object by its path and returns the DocumentId
 */ public DocumentId getWCMDocumentByPath(String wcmPath, int workFlowStatus) {
    DocumentId wcmDocumentId = null;
    try{
    
    
    if(wcmPath != null){                    
     DocumentIdIterator docIdIter = workspace.findByPath(wcmPath, workFlowStatus);
     if(docIdIter != null && docIdIter.hasNext()){
        wcmDocumentId = docIdIter.nextId();
      }
    }
  }catch(Exception e){
    System.out.println("Exception = "+e);
    e.printStackTrace();
    }
    
    return wcmDocumentId;
}

 

Listing 17. Retrieve child element by name

/*
 * This is a helper method that gets the child element according to
 * its name of another element if 
 * it contains only one child with that name
 */ private Element getChildByName(Element element, String name) {
    Element rEl = null;
    for (Node node = element.getFirstChild(); node != null; node = 
    node.getNextSibling()) {
       if (node.getNodeType() == Node.ELEMENT_NODE && 
       node.getNodeName().equals(name)) {
            rEl = (Element)node;
                break;
        }
    }        
    return rEl;
}

 

Listing 18. Retrieve element value by name

/*
 * This is a helper method that  returns a string value of the given element
 */ public String getElementValueByTagName(String aTagName, Element aElement){
    String elementValue = "";

    NodeList nodeList = aElement.getElementsByTagName(aTagName);
    if(nodeList != null && nodeList.getLength() > 0) {
        Element el = (Element)nodeList.item(0);            
        elementValue = el.getFirstChild().getNodeValue();            
    }
    
    return elementValue;            
}

 

Listing 19. Retrieve Lotus WCM object by name

/*
 * This is a helper method that returns the DocumentId of a Lotus Web  
 * Content Management object based on its name
 */ public DocumentId getWCMDocumentByName(String wcmName, DocumentType documentTypes){
    
  DocumentId wcmDocumentId = null;
  try{
    if(wcmName != null){    
                            
      DocumentIdIterator docIdIter = workspace.findByName(documentTypes, wcmName);
      if(docIdIter != null && docIdIter.hasNext()){
        wcmDocumentId = docIdIter.nextId();
                
      }
    }
  }catch(Exception e){
    System.out.println("Exception = "+e);
    e.printStackTrace();
  }
  if (wcmDocumentId == null && ( (documentTypes.equals
  (DocumentTypes.AuthoringTemplate)) || (documentTypes.equals
  (DocumentTypes.PresentationTemplate)) )){
    System.out.println("Exception:  "+wcmName+" could not be found in the Repository");
  }
  return wcmDocumentId;
}

 

Listing 20. Close Lotus WCM workspace

/**
   * Closes the Lotus WCM workspace
   */ public void closeWorkspace() {
    WCM_API.getRepository().endWorkspace();
}

NOTE: Exception handling is done only for illustration purposes rather than production-quality handling. It should be modified if needed to meet your expectations and requirements.

Key warnings have been reported by the helper class:

  • Users are notified by a warning message that there were errors and that the creation was not completed successfully.
  • Errors are logged in the SystemOut.log file so that you can examine more information about the error.
  • Errors that occur when users in the repository are not found result in an error being logged, but Creation Completed messages for the users are also generated.

Using the proposed solution in this article, you can enhance it. For example, you can do the following:

  • Create contents using XML
  • Add more complex components to the default content and contents
  • Change NewsSiteStructure.xml to create the same structure any number of times by changing only the name of the site area

 

Conclusion

In this article, we present a simple solution that enables you to define site structures in an automated fashion. The uses for such a solution are various; for example, you might need to define site areas on several servers, or you might have a site with a large amount of repeating site structures within it . This solution allows you to save time on an otherwise time-consuming and monotonous task.

 

Acknowledgments

The authors would like to express gratitude to Mourad El-Badry, Raul Munoz Serrano, and Tamer El-Mekky who took time out of their busy schedules to review this article and provide their comments.

 

Downloads

Name Size Download method
SiteCreation.xsd 3628B HTTP
NewsSiteStructure.xml 1933B HTTP

Information about download methods

 

Resources