h1. ECM Migration from DMS 2-3 to DMS 2.4




h1. New features with Symlink and Taxonomy Management

* In order to be able to use a virtual access to a document, we need node type *exo:simlink*. In addition, for *Manage Taxonomy*, we use new nodetype *exo:taxonomyLink* in file *nodetypes-config-extended.xml* in *dms/core/component/cms/src/main/java/conf/portal*:

{code:xml}
<nodeType name="exo:symlink" isMixin="false" hasOrderableChildNodes="false" primaryItemName="exo:primaryType">
 <supertypes>
  <supertype>nt:hierarchyNode</supertype>
 </supertypes>
 <propertyDefinitions>
  <propertyDefinition name="exo:workspace" requiredType="String" autoCreated="false" mandatory="false"
   onParentVersion="COPY" protected="false" multiple="false">
  <valueConstraints/>
  </propertyDefinition>
  <propertyDefinition name="exo:uuid" requiredType="String" autoCreated="false" mandatory="true"
   onParentVersion="COPY" protected="false" multiple="false">
  <valueConstraints/>
  </propertyDefinition>
  <propertyDefinition name="exo:primaryType" requiredType="Name" autoCreated="false" mandatory="true"
   onParentVersion="COPY" protected="false" multiple="false">
  <valueConstraints/>
  </propertyDefinition>
 </propertyDefinitions>
</nodeType>

<nodeType name="exo:taxonomyLink" isMixin="false" hasOrderableChildNodes="false" primaryItemName="exo:primaryType">
 <supertypes>
  <supertype>exo:symlink</supertype>
 </supertypes>
</nodeType>
{code}

* Please refer to [Symlink>http:--wiki.exoplatform.com-xwiki-bin-view-ECM-Creating+a+Symlink] and [Manage Taxonomy>http:--wiki.exoplatform.com-xwiki-bin-view-ECM-Creating+a+new+Taxonomy+Tree] to get the details of these implementations






1 Using new workspace dms-system

 Instead of storing in system workspace, from DMS-2.4, we use *dms-system* to store *taxonomy*, *templates*, *query*, *meta data*, *scripts*...
* In file *repository-configuration.xml* at the location *dms/core/web/portal/.../WEB-INF/conf/jcr*:
  add new workspace *dms-system*

{code:xml}
<workspace name="dms-system">
  <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
 <properties>
   <property name="source-name" value="jdbcexo"/>
   <property name="dialect" value="hsqldb"/>
   <property name="multi-db" value="false"/>
   <property name="max-buffer-size" value="200k"/>
   <property name="swap-directory" value="../temp/swap/dms-system"/>
 </properties>
 <value-storages>
   <value-storage id="dms-system" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
  <properties>
    <property name="path" value="../temp/values/dms-system"/>
  </properties>
  <filters>
    <filter property-type="Binary"/>
  </filters>
   </value-storage>
 </value-storages>
  </container>
  <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
 <properties>
   <property name="root-nodetype" value="nt:unstructured"/>
   <property name="root-permissions" value="any read;*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove"/>
 </properties>
  </initializer>
  <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">
 <properties>
   <property name="max-size" value="20k"/>
   <property name="live-time" value="1h"/>
 </properties>
  </cache>
  <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
 <properties>
   <property name="indexDir" value="../temp/jcrlucenedb/dms-system"/>
   <property name="support-highlighting" value="true"/>
   <property name="excerptprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.DefaultHTMLExcerpt"/>
 </properties>
  </query-handler>
  <lock-manager>
 <time-out>15m</time-out>
 <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
   <properties>
  <property name="path" value="../temp/lock/dms-system"/>
   </properties>
 </persister>
  </lock-manager>
</workspace>
{code}


* To get name of this workspace, we add new configuration file *dms-common-configuration.xml* at the location
  *dms/core/web/portal/.../WEB-INF/conf/dms*

{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>
<configuration>
  <external-component-plugins>
  <target-component>org.exoplatform.services.cms.impl.DMSConfiguration</target-component>
    <component-plugin>
      <name>dmsconfiguration.plugin</name>
      <set-method>addPlugin</set-method>
      <type>org.exoplatform.services.cms.impl.DMSRepositoryConfiguration</type>
      <description>DMS Repository configuration</description>
      <init-params>
       <value-param>
         <name>repository</name>
         <value>repository</value>
       </value-param>
       <value-param>
         <name>systemWorkspace</name>
         <value>dms-system</value>
       </value-param>
      </init-params>
    </component-plugin>
 </external-component-plugins>
</configuration>
{code}


* In file *dms-drives-configuration.xml* at the location *dms/core/web/portal/.../WEB-INF/conf/dms* We change the location of drive *Categorized Documents* and add new drive *DMS Administration* to control data in this new workspace by modifying/appending xml code.

{code:xml}
...
<object-param>
 <name>Categorized Documents</name>
 <description>Categorized Documents</description>
 <object type="org.exoplatform.services.cms.drives.DriveData">
   <field  name="name"><string>Categorized Documents Center</string></field>
   <field  name="repository"><string>repository</string></field>
   <field  name="workspace"><string>dms-system</string></field>
   <field  name="permissions"><string>*:/platform/administrators</string></field>
   <field  name="homePath"><string>/exo:ecm/exo:taxonomyTrees/storage</string></field>
   <field  name="icon"><string></string></field>
   <field  name="views">
  <string>taxonomy-list,taxonomy-icons</string>
   </field>
   <field  name="viewPreferences"><boolean>true</boolean></field>
   <field  name="viewNonDocument"><boolean>true</boolean></field>
   <field  name="viewSideBar"><boolean>true</boolean></field>
   <field  name="showHiddenNode"><boolean>false</boolean></field>
   <field  name="allowCreateFolder"><string>Both</string></field>
 </object>
</object-param>
...
<object-param>
 <name>DMS Administration</name>
 <description>DMS system data area</description>
 <object type="org.exoplatform.services.cms.drives.DriveData">
   <field  name="name"><string>DMS Administration</string></field>
   <field  name="repository"><string>repository</string></field>
   <field  name="workspace"><string>dms-system</string></field>
   <field  name="permissions"><string>*:/platform/administrators</string></field>
   <field  name="homePath"><string>/</string></field>
   <field  name="icon"><string></string></field>
   <field  name="views">
  <string>icon-view, simple-view, admin-view, cover-flow</string>
   </field>
   <field  name="viewPreferences"><boolean>false</boolean></field>
   <field  name="viewNonDocument"><boolean>true</boolean></field>
   <field  name="viewSideBar"><boolean>true</boolean></field>
   <field  name="showHiddenNode"><boolean>false</boolean></field>
   <field  name="allowCreateFolder"><string>Both</string></field>
 </object>
</object-param>
{code}


* We move all data of *taxonomy*, *templates*, *query*, *meta data*, *scripts*... from *system* workspace to new *dms-system* workspace but we still keep data of folksonomy in *system* workspace. These changes are configurated in file *dms-system-configuration.xml* at the location *dms/core/web/portal/.../WEB-INF/conf/dms*
{code:xml}

<?xml version="1.0" encoding="ISO-8859-1"?>
<configuration>
 <external-component-plugins>
  <target-component>org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator</target-component>
  <component-plugin>
   <name>addPaths</name>
   <set-method>addPlugin</set-method>
   <type>org.exoplatform.services.jcr.ext.hierarchy.impl.AddPathPlugin</type>
   <init-params>
    <object-param>
     <name>cms.configuration</name>
     <description>configuration for the cms path</description>
     <object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig">
      <field name="repository">
       <string>repository</string>
      </field>
      <field name="workspaces">
       <collection type="java.util.ArrayList">
        <value>
         <string>dms-system</string>
        </value>
       </collection>
      </field>
      <field name="jcrPaths">
       <collection type="java.util.ArrayList">
        <value>
         <object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
          <field name="alias">
           <string>exoECMSystemPath</string>
          </field>
          <field name="path">
           <string>/exo:ecm</string>
          </field>
          <field name="permissions">
           <collection type="java.util.ArrayList">
            <value>
             <object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
              <field name="identity">
               <string>*:/platform/administrators</string>
              </field>
              <field name="read">
               <string>true</string>
              </field>
              <field name="addNode">
               <string>true</string>
              </field>
              <field name="setProperty">
               <string>true</string>
              </field>
              <field name="remove">
               <string>true</string>
              </field>
             </object>
            </value>
            <value>
 .....
{code}
See complete file: "dms-system-configuration.xml"


1 Create default taxonomy tree to [Manage Taxonomy>http:--wiki.exoplatform.com-xwiki-bin-view-ECM-Creating+a+new+Taxonomy+Tree]
* From DMS 2-4, we remove old taxonomy and create a taxonomy tree named *System*. This tree is defined in *dms-taxonomies-configuration.xml* at the location *dms/core/web/portal/.../WEB-INF/conf/dms/* and is automatically created when tomcat runs

{code:xml}

<?xml version="1.0" encoding="ISO-8859-1"?>
<configuration>

  <component>
   <key>org.exoplatform.services.cms.taxonomy.TaxonomyService</key>
   <type>org.exoplatform.services.cms.taxonomy.impl.TaxonomyServiceImpl</type>
 </component>

 <external-component-plugins>
    <target-component>org.exoplatform.services.cms.taxonomy.TaxonomyService</target-component>
    <component-plugin>
     <name>predefinedTaxonomyPlugin</name>
      <set-method>addTaxonomyPlugin</set-method>
      <type>org.exoplatform.services.cms.taxonomy.impl.TaxonomyPlugin</type>
      <init-params>
       <value-param>
          <name>autoCreateInNewRepository</name>
          <value>true</value>
         </value-param>
         <value-param>
          <name>repository</name>
          <value>repository</value>
         </value-param>
         <value-param>
          <name>treeName</name>
          <value>System</value>
         </value-param>
          <object-param>
            <name>permission.configuration</name>
            <object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig">
              <field name="taxonomies">
                <collection type="java.util.ArrayList">
                  <value>
                    <object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Taxonomy">
                      <field name="permissions">
                  <collection type="java.util.ArrayList">
                     <value>
                       <object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Permission">
                          <field name="identity"><string>any</string></field>
                          <field name="read"><string>true</string></field>
                          <field name="addNode"><string>false</string></field>
                          <field name="setProperty"><string>false</string></field>
                          <field name="remove"><string>false</string></field>
                        </object>
                     </value>
                     <value>
                       <object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Permission">
                        <field name="identity"><string>*:/platform/administrators</string></field>
                          <field name="read"><string>true</string></field>
                          <field name="addNode"><string>true</string></field>
                          <field name="setProperty"><string>true</string></field>
                          <field name="remove"><string>true</string></field>
                       </object>
                     </value>
                    </collection>
                  </field>
                    </object>
                  </value>
                </collection>
              </field>
            </object>
          </object-param>
          <object-param>
            <name>predefined.actions</name>
            <description>description</description>
            <object type="org.exoplatform.services.cms.actions.impl.ActionConfig">
              <field  name="actions">
                <collection type="java.util.ArrayList">
                  <value>
                    <object type="org.exoplatform.services.cms.actions.impl.ActionConfig$TaxonomyAction">
                      <field  name="type"><string>exo:taxonomyAction</string></field>
                      <field  name="name"><string>taxonomyAction</string></field>
                      <field  name="description"><string></string></field>
                      <field  name="homePath"><string>dms-system:/exo:ecm/exo:taxonomyTrees/storage/System</string></field>
                      <field  name="targetWspace"><string>collaboration</string></field>
                      <field  name="targetPath"><string>/Documents</string></field>
                      <field  name="lifecyclePhase"><string>read</string></field>
                      <field  name="roles"><string>*:/platform/administrators</string></field>
                    </object>
                  </value>
                </collection>
              </field>
            </object>
          </object-param>
       <object-param>
...
{code}

See complete file: [^dms-taxonomies-configuration.xml]

h1. Filter all action in File Explorer, ECM Admin

* In DMS 2-4 portlet *ecm* is splited to 4 sub-projects:

# *core/portlet/ecm/core/main*: Only the java part of the old *core/portlet/ecm* project. The pom of this project creates a jar that will be added in the directory *ecm.war/WEB-INF/lib*
# *core/portlet/ecm/core/web*: Only the web part of the old core/portlet/ecm project. The pom of this project creates a war that will be the *ecm.war*
# *core/portlet/ecm/ext/main*: Only the java part of the current extensions. The pom of this project creates a jar that will be added in the directory *ecm.war/WEB-INF/lib*
# *core/portlet/ecm/ext/config*: Only the configuration of those extensions. The pom of this project creates a jar that will be added in the directory *tomcat/lib*


* Now all action in File Explorer and ECM Admin are filtered for each view. All actions are registered and manage by *org.exoplatform.webui.ext.UIExtensionManager*. We configure actions in *dms-ext-configuration.xml* at the location  *dms/core/web/portal/.../WEB-INF/conf/dms/*. A complete example: [^dms-ext-configuration.xml]

{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>

<configuration>
  <component>
  <key>org.exoplatform.webui.ext.UIExtensionManager</key>
  <type>org.exoplatform.webui.ext.impl.UIExtensionManagerImpl</type>
  <component-plugins>
   <component-plugin>
    <name>Add Actions</name>
    <set-method>registerUIExtensionPlugin</set-method>
    <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
    <init-params>
     <object-param>
      <name>AddFolder</name>
      <object type="org.exoplatform.webui.ext.UIExtension">
       <field name="type"><string>$\{typeOfAction}</string></field>
       <field name="name"><string>$\{ActionName}</string></field>
       <field name="component"><string>$\{ActionHandle}</string></field>
      </object>
...
{code}
Please refer to http://wiki.exoplatform.com/xwiki/bin/view/ECM/UI+Extension+Framework









1 Gadget for last edited documents
 *LastEditedDocuments* gadget displays last 5 edited documents with document name and edited time. When user click on the document, its content will be displayed in File Explorer
* In *GetEditedDocumentRESTService.class* (exo.ecm.dms.core.component.cms-2.4.jar) we implement Rest Service to get these document.
* Add new file *LastEditedDocuments.xml* in *src/main/webapp/gadgets* for displaying gadget

{code:xml}
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
 <ModulePrefs author="eXoPlatform"
  title="Last edited documents"
  directory_title="Last edited documents"
  title_url="http://www.exoplatform.org"
  description="The last edited documents"
  height="230">
 </ModulePrefs>
 <Content type="html">
 <![CDATA[

  <script type="text/javascript" src="/eXoDMSGadgets/javascript/script.js"></script>

  <style type="text/css">
   body{
    font: 11px Tahoma,Verdana,Arial,Helvetica,sans-serif;
    height:100%;
    margin:0 auto;
    padding:0;
   }

   a {
    text-decoration: none;
   }

   ...
   </style>
    <script type="text/javascript">
   function LastEditedDocument() {

   }

   var siteUrl = 'http://localhost:8080/portal/rest/presentation/document/edit/repository?showItems=5';
   var accessUrl = 'http://localhost:8080/portal/private/classic/contentmanagement/fileexplorer?portal:componentId=fileexplorer&portal:type=action&uicomponent=UIDocumentInfo&op=ViewDoc'

   LastEditedDocument.prototype.makeRequest = function(url, callback) {
    var params = {};
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
    var ts = new Date().getTime();
     var sep = "?";
     var refreshInterval = 60;
     if (refreshInterval && refreshInterval > 0) {
       ts = Math.floor(ts / (refreshInterval * 1000));
     }
     if (url.indexOf("?") > -1) {
       sep = "&";
     }
     url = [ url, sep, "nocache=", ts ].join("");
    gadgets.io.makeRequest(url, callback, params);
   }

   LastEditedDocument.prototype.init = function() {
    lastEditedDocument.makeRequest(siteUrl,lastEditedDocument.displayValue);
   }

   LastEditedDocument.prototype.displayValue = function(resp) {
    var data = resp.data.lstDocNode;
    var editedDocList = _gel("ListEditDocumentNode");
    var displayTime = new DisplayTime();
    for (var i = 0; i < data.length; i++) {
     var doc = data[i];
     var AppClass = document.createElement('div');
     var showHTML = "<a target='_top' href='";
     showHTML+= accessUrl;
     showHTML+= "&repository=repository";
     showHTML+= "&drive=";
     showHTML+= doc.driveName;
     showHTML+= "&path=";
     showHTML+= doc.path;
     showHTML+= "'>";
     showHTML+=doc.name;
     showHTML+="</a>";
     showHTML+="<div class='DateTime'>";
     showHTML+="";
     showHTML+=displayTime.timeToPrettyString(doc.dateEdited);
     showHTML+="</div>";
     AppClass.innerHTML = showHTML;
     AppClass.className = 'ItemIcon';
     editedDocList.appendChild(AppClass);
    }
    var title = _gel("BgTitle");
    if (data && (data.length > 0) && title) {
     editedDocList.parentNode.removeChild(title);
    }
    gadgets.window.adjustHeight();
   }

   var lastEditedDocument = new LastEditedDocument();
   gadgets.util.registerOnLoadHandler(lastEditedDocument.init);
  </script>

  <body>

   <div class="ContentGadGet">
    <div class="BgLeftTitleContent">
     <div class="BgRightTitleContent">
      <div class="BgCentertTitleContent">
       <div class="IconArrow"><span></span></div>
       <div class="TextTitle">Last Edited Documents</div>
       <div class="ClearRight"><span></span></div>
      </div>
     </div>
    </div>
    <div class="BgRightContent">
     <div class="BgLeftContent">
      <div class="BgCenterContent">
       <div id="BgTitle" class="BgTitle">
        <div class="NotAvailableItemIcon">
         Not available document!
        </div>
       </div>
       <div id="ListEditDocumentNode" class="ListEditDocumentNode">
       </div>
      </div>
     </div>
    </div>
    <div class="BgLeftFooterContent">
     <div class="BgRightFooterContent">
      <div class="BgCenterFooterContent"><span></span></div>
     </div>
    </div>
   </div>
  </body>
 ]]>
 </Content>
</Module>

{code}





h1. Set up size of uploading file
* When we upload file in File Explorer, we need limit size of file. Maximum size of file is set up in *portlet-preferences.xml* at the location *dms/core/web/portal/.../WEB-INF/conf/portal/group/platform/users*. In this file, we set 30M by default for file size

{code:xml}
 <portlet-preferences>
 ...
  <preference>
   <name>uploadFileSizeLimitMB</name>
   <value>30</value>
   <read-only>false</read-only>
  </preference>
 ...
 </portlet-preferences>
{code}



