EMC Developer Network

Recursive Folder Create

October 2005

Software Environment

FeatureTested on
Operating SystemWindows 2000 Server SP4
CompilerSun JDK 1.4.2_08
RuntimeSun JRE 1.4.2_08
DFC5.3 SP1
Content Server5.3

Abstract

This code snippet demonstrates recursively creating a complete Repository folder path.

Snippet


                                            

/*
 * Created on Oct 24, 2005
 *
 * EMC Documentum Developer Program 2005
 */
package com.documentum.devprog.snippets;

import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfId;
import com.documentum.fc.common.IDfId;
import com.documentum.fc.common.IDfLoginInfo;

import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfFolder;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;

import java.util.StringTokenizer;

import com.documentum.com.DfClientX;
import com.documentum.com.IDfClientX;

public class RecursiveFolderCreate
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        String username = "dmadmin";
        String password = "dmadmin";
        String repoName = "devprog";
        String folderPath = "/a/b/c/d";
        
        IDfSessionManager sessMgr = null;
        IDfSession sess = null;
        try
        {
            sessMgr = createSessionManager();
            addIdentity(sessMgr,username,password,repoName);
            sess = sessMgr.getSession(repoName);
            IDfId newId = createFolder(sess,folderPath,null,null,null);
            System.out.println("Created folder: " + newId);
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            if((sessMgr != null) && (sess != null))
            {
                sessMgr.release(sess);
            }
        }

    }
    
    
    /**
        * Creates a folder specified by folder path. If the folders in the
        * path don't exist, they are created too. Thus, its a recursive
        * docbase folder creation method.
        * 
        * <p>
        * The first component of the path is assumed to be a cabinet and
        * an object of type dm_cabinet is created for the first component if
        * it does not exist.
        * 
        * <p>
        * This method is expensive in terms of time and should be called with discretion.
        * 
        * <p>
        * The last argument of the method specifies a base path. This path specifies
        * the path beyond which the recursive folder creation proceeds. Specifying this
        * value will avoid checks for existence of folders specified in base path. 
        * This will eventually help speed up processing and thus serves as a heuristic. 
        * This is an optional argument and if left empty or <code>null</code> all folders
        * specified in <code>path</code> 
        * are checked for existence and created if not present. This argument should not
        * end with the path separator ('/'). 
        * 
        * @param sess
        * @param path The folder path to be created.
        * @param pathSep (optional) Default value is '/'
        * @param type (optional) The type of the folders. Default is dm_folder.
        * @param basePath (optional) See the the method description above for this argument. 
        * @return
        * @throws DfException
        * @throws RuntimeException This exception is thrown if basePath is not a valid basePath of
        * <br>                     specified path.
        */
    public static IDfId createFolder(
       IDfSession sess,
       String path,
       String pathSep,
       String type,
       String basePath)
       throws DfException
    {
       boolean cabinetStillToBeProcessed = true;

       if (pathSep == null || (pathSep.length() == 0))
       {
          pathSep = "/";
       }

       if ((type == null) || (type.length() == 0))
       {
          type = "dm_folder";
       }

       IDfId currentId = null;

       StringBuffer bufFldrPath = new StringBuffer(48);
       if ((basePath != null) && (basePath.length() > 1))
       {
          currentId = getIdByPath(sess, basePath);
          if (!currentId.isNull())
          {
             //base path actually exists.
             bufFldrPath.append(basePath);
             cabinetStillToBeProcessed = false; //cabinet already processed due to base path.
             
             int basePathLen = basePath.length();            
             if(basePathLen < path.length())
             {
                path = path.substring(basePath.length());
             }            
          }

       }

       StringTokenizer tokFldrNames = new StringTokenizer(path, pathSep);

       if (cabinetStillToBeProcessed)
       {
          //Execution will come here only if basePath was not specified or
          //if specified basePath was not valid.
          String cabinetName = tokFldrNames.nextToken();
          StringBuffer cabQual = new StringBuffer(32);
          cabQual.append("dm_cabinet where object_name='").append(
             cabinetName).append(
             "'");

          currentId = sess.getIdByQualification(cabQual.toString());
          if (currentId.isNull())
          {
             //need to create cabinet.
             IDfFolder cab = (IDfFolder) sess.newObject("dm_cabinet");
             cab.setObjectName(cabinetName);
             cab.save();
             currentId = cab.getObjectId();            
          }
          bufFldrPath.append(pathSep).append(cabinetName);
       }
       //By this point the bufFldrPath will either have the cabinet path
       //or it will have the basePath in it. 
       
       //now create all folders beyond the cabinet or basePath.
       while(tokFldrNames.hasMoreTokens())
       {         
          String parentPath = bufFldrPath.toString();
          
          String fldrName = tokFldrNames.nextToken();
          bufFldrPath.append(pathSep).append(fldrName);
          //by this point the buffer should contain the new expected path
          
          currentId = getIdByPath(sess,bufFldrPath.toString());
          if(currentId.isNull())
          {
             //looks like the new folder in the path does not exist.
             IDfFolder newFldr = (IDfFolder) sess.newObject(type);
             newFldr.setObjectName(fldrName);
             newFldr.link(parentPath);
             newFldr.save();
             currentId = newFldr.getObjectId();            
          }
          //by this point currentId should point to next folder in path                           
       }//while(all folder names)
       
       return currentId;
    }
    
    /**
     * Gets an object id given the path of the object. This method is a simple
     * wrapper around the IDfSession#getIdByQualification(...) method. This method
     * can be used instead of the IDfSession.getObjectByQualification() if all that is
     * needed is the object id instead of a full fetch that getObjectByQualification(...) 
     * method does. This method can be useful to check for the existence of an 
     * object if path is known.
     * 
     * @param sess Docbase session
     * @param path Docbase path of the object whose id needs to be obtained.
     * @return instance of <code>IDfId</code>. This instance will contain
     *         a valid id if the object was found or an invalid id if the
     *         object was not found or if the path was illegal.
     *    
     * @throws DfException
     */
    public static IDfId getIdByPath(IDfSession sess, String path)
       throws DfException
    {       

       int pathSepIndex = path.lastIndexOf('/');
       if (pathSepIndex == -1)
       {
          return new DfId("000");
       }

       StringBuffer bufQual = new StringBuffer(32);
       if (pathSepIndex == 0)
       {
          //its a cabinet path 
          bufQual.append(" dm_cabinet where object_name='");
          bufQual.append(path.substring(1));
          bufQual.append("'");
       }
       else
       {
          bufQual.append(" dm_sysobject where FOLDER('");
          bufQual.append(path.substring(0, pathSepIndex));
          bufQual.append("') ");
          bufQual.append(" and object_name='");
          bufQual.append(path.substring(pathSepIndex + 1));
          bufQual.append("'");
       }

       String strQual = bufQual.toString();
       IDfId id = sess.getIdByQualification(strQual);
       return id;
    }
    
    /**
     * Creates a new session manager instance. The session manager does not have
     * any identities associated with it.
     * 
     * @return a new session manager object.
     * @throws DfException
     */
    private static IDfSessionManager createSessionManager() throws DfException
    {
        IDfClientX clientX = new DfClientX();
        IDfClient localClient = clientX.getLocalClient();
        IDfSessionManager sessMgr = localClient.newSessionManager();
        return sessMgr;
    }

    /**
     * Adds a new identity to the session manager.
     */
    private static void addIdentity(IDfSessionManager sm, String username,
            String password, String repoName) throws DfException
    {
        IDfClientX clientX = new DfClientX();

        IDfLoginInfo li = clientX.getLoginInfo();
        li.setUser(username);
        li.setPassword(password);

        // check if session manager already has an identity.
        // if yes, remove it.
        if (sm.hasIdentity(repoName))
        {
            sm.clearIdentity(repoName);
        }

        sm.setIdentity(repoName, li);
    }

}



                                        

Using the code

The above code snippet comes with a main method and is thus a standalone program. To use it, copy-paste the entire code into a new Java class created in your IDE. Adjust the package and class name of the pasted code according to your preference. Change the username,password, repository name and any other necessary variables. Compile and run the code. For details on setting up your IDE for DFC development, refer to the article Setting up a DFC Development Environment

Note:The above code demonstrates a specific piece of functionality and is not meant to be a complete solution