cancel
Showing results for 
Search instead for 
Did you mean: 

I want to Modify the Document Details page

stevewickii
Champ in-the-making
Champ in-the-making
I am using Alfresco 2.9.0B community tomcat release, on Windows XP SP2 with a Microsoft SQL Server 2000 database, and Java 6.

Right now I have the following category hierarchy…

Audience/A/Regions/USA/MO
Audience/A/Regions/USA/KS
Audience/A/Regions/USA/FL
Audience/B/Regions/USA/MO
Audience/B/Regions/USA/KS
Audience/B/Regions/USA/FL

My problem is that it is impossible to destinguish between the categories Audience/A/Regions/USA/MO and Audience/B/Regions/USA/MO on the Document Details > Category panel, which lists the categories currently assigned to a document, because the panel does not list the parent categories - it just lists "MO" and "MO".

I need to modify the Category panel to show each category, along with it's ancestors.  This may be modifying an XML file, or modifying a JSP.  I don't know.

I have the Alfresco book, by Munwar Shariff, and I have been reading through forums and wikis, and I cannot figure out where to start.

I could really use some help.
3 REPLIES 3

jbarmash
Champ in-the-making
Champ in-the-making
You'll need to write a component generator that displays the category hierarchy instead of just the category.
    http://wiki.alfresco.com/wiki/Displaying_Custom_Metadata#Component_Generators

    This way you should be able to display something Audience/A/Regions/USA/KS in your property sheet.

Another way that some people have done it is use a freemarker template on top of the page that walks up the hierarchy and displays it as well, although that's not as user friendly.

stevewickii
Champ in-the-making
Champ in-the-making
Thanks Jbarmash

stevewickii
Champ in-the-making
Champ in-the-making
Here's what I ended up doing.

The document-details.jsp uses the DocumentDetailsBean.getCategoriesOverviewHTML() method to produce the list of categories associated with a document.  I extended DocumentDetailsBean as "DocumentDetailsBeanExt" and overrided the getCategoriesOverviewHTML() method, so that the method returns a list of categories (including all ancestors (parents)) up to but not including the "General" category.

Implementation

Create a folder structure to hold the extension:

DocumentDetailsExtension/build.xml
DocumentDetailsExtension/source/org/alfrescox/web/bean/DocumentDetailsBeanExt.java
DocumentDetailsExtension/web
DocumentDetailsExtension/web/WEB-INF/faces-config-custom.xml


DocumentDetailsBeanExt.java

package org.alfrescox.web.bean;

import java.util.Collection;
import java.util.List;
import java.util.Vector;

import javax.faces.context.FacesContext;

import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.DocumentDetailsBean;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Backing bean providing access to the details of a document
*
* @author swick
*/
public class DocumentDetailsBeanExt extends DocumentDetailsBean
{
   protected Log logger = LogFactory.getLog(getClass());
   static final String MSG_HAS_FOLLOWING_CATEGORIES = "has_following_categories";
   static final String MSG_NO_CATEGORIES_APPLIED = "no_categories_applied";

   /**
    * Returns a list of objects representing the categories applied to the
    * current document
    *
    * @return List of categories
    */
   public String getCategoriesOverviewHTML()
   {
      String html = null;

      if (isCategorised())
      {
         // we know for now that the general classifiable aspect only will be
         // applied so we can retrive the categories property direclty
         Collection<NodeRef> categories = (Collection<NodeRef>)this.nodeService.getProperty(getDocument().getNodeRef(), ContentModel.PROP_CATEGORIES);

         if (categories == null || categories.size() == 0)
         {
            html = Application.getMessage(FacesContext.getCurrentInstance(), MSG_NO_CATEGORIES_APPLIED);
         }
         else
         {
            StringBuilder builder = new StringBuilder(Application.getMessage(FacesContext.getCurrentInstance(),
                  MSG_HAS_FOLLOWING_CATEGORIES));

            builder.append("<ul>");
            for (NodeRef ref : categories)
            {
               if (this.nodeService.exists(ref))
               {
                  builder.append("<li>");
                  builder.append(getFullPath(ref));
                  builder.append("</li>");
               }
            }
            builder.append("</ul>");

            html = builder.toString();
         }
      }

      return html;
   }

   public String getFullPath(NodeRef ref)
   {
      if(logger.isDebugEnabled())
         logger.debug("getFullPath for "+ref);
      StringBuffer buffer = new StringBuffer(Repository.getNameForNode(nodeService, ref));
      List<ChildAssociationRef> parents = null;
      NodeRef parent = ref;
      while(parent!=null && (parents = nodeService.getParentAssocs(parent))!=null)
      {
         parent=null;
         // there shouldn't be more than one ChildAssociationRef
         for(ChildAssociationRef car : parents)
         {
            if(logger.isDebugEnabled())
               logger.debug("getFullPath - considering child association reference: "+car);
            String parentName = Repository.getNameForNode(nodeService, car.getParentRef());
            if(parentName.equalsIgnoreCase("general"))
               break; // break for loop.  parent is still null, which will break the while loop as well.
            parent = car.getParentRef(); // store parent for next loop
            buffer.insert(0,"/");
            buffer.insert(0,parentName);
         }
      }
      
      if(logger.isDebugEnabled())
         logger.debug("getFullPath returning path: "+buffer.toString());
      
      return buffer.toString();
   }
}

faces-config-custom.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
   <managed-bean>
      <description>
         Backing bean used by the document details dialog
      </description>
      <managed-bean-name>DocumentDetailsBean</managed-bean-name>
      <managed-bean-class>org.alfrescox.web.bean.DocumentDetailsBeanExt</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
         <property-name>browseBean</property-name>
         <value>#{BrowseBean}</value>
      </managed-property>
      <managed-property>
         <property-name>nodeService</property-name>
         <value>#{NodeService}</value>
      </managed-property>
      <managed-property>
         <property-name>lockService</property-name>
         <value>#{LockService}</value>
      </managed-property>
      <managed-property>
         <property-name>versionService</property-name>
         <value>#{VersionService}</value>
      </managed-property>
      <managed-property>
         <property-name>copyService</property-name>
         <value>#{CopyService}</value>
      </managed-property>
      <managed-property>
         <property-name>ownableService</property-name>
         <value>#{OwnableService}</value>
      </managed-property>
      <managed-property>
         <property-name>checkOutCheckInService</property-name>
         <value>#{CheckoutCheckinService}</value>
      </managed-property>
      <managed-property>
         <property-name>navigator</property-name>
         <value>#{NavigationBean}</value>
      </managed-property>
     <managed-property>
         <property-name>multilingualContentService</property-name>
         <value>#{MultilingualContentService}</value>
      </managed-property>
      <managed-property>
         <property-name>contentFilterLanguagesService</property-name>
         <value>#{ContentFilterLanguagesService}</value>
      </managed-property>
      <managed-property>
         <property-name>editionService</property-name>
         <value>#{EditionService}</value>
      </managed-property>
      <managed-property>
         <property-name>permissionService</property-name>
         <value>#{PermissionService}</value>
      </managed-property>
   </managed-bean>
</faces-config>

build.xml

<?xml version="1.0"?>

<project name="Custom JSP Build File" default="package-extension" basedir=".">
   
   <property name="project.dir" value="."/>
   <property name="source.dir" value="${project.dir}/source"/>
   <property name="build.dir" value="${project.dir}/build"/>
   <property name="classes.dir" value="${build.dir}/classes"/>
   <property name="tomcat.home" value="C:\\Program Files\\Apache\\apache-tomcat-5.5.25"/>
   <property name="alfresco-lib.dir" value="${tomcat.home}/webapps/alfresco/WEB-INF/lib"/>
   <property name="web.dir" value="${project.dir}/web" />
   <property name="package.file.jar" value="${build.dir}/custom-jsp.jar"/>
   <property name="package.file.zip" value="${build.dir}/custom-jsp.zip"/>
   
   <target name="compile">
      <mkdir dir="${build.dir}" /> 
      <mkdir dir="${classes.dir}" /> 
      <javac srcdir="${source.dir}" destdir="${classes.dir}">
           <classpath>
      <fileset dir="${alfresco-lib.dir}">
         <include name="**/*.jar"/>
      </fileset>
      <fileset dir="${tomcat.home}/common/lib">
         <include name="**/*.jar"/>
      </fileset>
      </classpath>
      </javac>
   </target>
  
   <target name="package-jar" depends="compile">
      <delete file="${package.file.jar}" /> 
      <jar destfile="${package.file.jar}">
         <fileset dir="${source.dir}" excludes="*.java"/>
         <fileset dir="${classes.dir}"/>
      </jar>
   </target>
  
   <target name="package-extension" depends="package-jar">
      <delete file="${package.file.zip}" />
      <zip destfile="${package.file.zip}">
         <zipfileset file="${package.file.jar}" prefix="WEB-INF/lib" />
         <zipfileset dir="${web.dir}" />
      </zip>
   </target>
  
   <target name="integrate-extension" depends="package-extension">
      <available file="alfresco.war" type="file" property="alfresco.war.present" />
      <fail unless="alfresco.war.present"
            message="Could not find alfresco.war, please copy it to ${basedir}" />
      <zip destfile="alfresco.war" update="true">
         <zipfileset file="${package.file.jar}" prefix="WEB-INF/lib" />
         <zipfileset dir="${web.dir}" />
      </zip>
   </target>

</project>

I got this build.xml from the Alfresco SDK/examples/CustomJSP, so there might be some unnecessary stuff in there.

Make sure that the properties tomcat.home and alfresco-lib.dir are set correctly in build.xml.  Then copy your alfresco.war to the DocumentDetailsExtension folder.  The document details extension will be integrated into this alfresco.war file so make sure you have a backup copy.  From the DocumentDetailsExtension folder (in DOS/Shell or your IDE) execute 'ant integrate-extension'.  Finally, copy the alfresco.war to your app server's autodeploy folder (ie: tomcat_home/webapps).

Let me know what you think of this solution, and please post suggestions if you have an alternative solution.

Cheers