Working with Lifecycle-related Objects

To be governed by a lifecycle policy, a Document object requires a DocumentLifecyclePolicy object, which specifies the states through which the document will transition, and, typically, the actions to occur in response to the state transitions. As pointed out in Lifecycle Actions, the actions can be coded in a lifecycle action handler and referenced by a DocumentLifecycleAction object. The DocumentLifecycleAction is then set on the DocumentLifecyclePolicy object.

If the DocumentLifecycleAction object and lifecycle action handler do not already exist, you must first create them, and then associate them with the DocumentLifecyclePolicy object, as shown in the following topics.

After it's been created, a DocumentLifecyclePolicy object is available for assignment to Document objects or to Document classes or subclasses. See Assigning a DocumentLifecyclePolicy Object.

For a DocumentLifecyclePolicy object to have an effect, you must change the states on the documents to which the DocumentLifecyclePolicy object is assigned. See Changing a Document's State.

You can retrieve DocumentLifecyclePolicy objects, as well as set and retrieve properties and permissions for them. See Retrieving DocumentLifecyclePolicy Objects.

For an overview of lifecycle policies, see Lifecycle Policy Concepts.

Creating a Lifecycle Action Handler

To create a document lifecycle action handler, you must implement all of the methods in the Java™ DocumentLifecycleActionHandler interface. The following example shows one such implementation. The parameters of each method are the same: the Document object whose state is changing, and the DocumentLifecyclePolicy object attached to the Document object. For each method, you essentially determine the document's current state, as defined in the policy's list of DocumentState objects, and do something based on that state. Note that states transition in sequential order when a document is promoted or demoted, and, on reset, the document is set to the first state. When in exception, a document is frozen in its current state; when the exception is cleared, the document can be transitioned between states.

The example handler below simply reflects state changes in the name of a document to which the policy is attached. When the document's state changes, the policy appends the current state of the document to the name of the document. So, for example, the name of a car loan document that transitions from an application state to an approval state to a funding state would change from "CarLoan_Application" to "CarLoan_Approval" to "CarLoan_Funding". For a code example of a document lifecycle policy applicable to this scenario, see Creating a DocumentLifecyclePolicy Object.

For best practices in implementing and packaging a DocumentLifecycleActionHandler interface, see Implementation Concepts. To view a sample source code DocumentLifecycleActionHandler implementation packaged with the Content Engine, go to this Content Engine directory: <drive>:/Program Files/Filenet/Content Engine/samples. The DocumentLifecycleActionHandler implementation is LCAHandler.java.

Java Example

package sample.actionhandler;
import com.filenet.api.engine.DocumentLifecycleActionHandler;
import com.filenet.api.events.DocumentLifecyclePolicy;
import com.filenet.api.exception.EngineRuntimeException;
import com.filenet.api.core.Document;

public class LifecycleActionHandler implements DocumentLifecycleActionHandler
{
    public void onDocumentPromote( Document doc, DocumentLifecyclePolicy policy )
    {
        int index = doc.get_Name().indexOf("_");
        String docName = index != -1 ? doc.get_Name().substring(0, index) : doc.get_Name();
        doc.getProperties().putValue( "DocumentTitle", docName + "_" + doc.get_CurrentState() );
    }

    public void onDocumentDemote( Document doc, DocumentLifecyclePolicy policy ) throws EngineRuntimeException
    {
        int index = doc.get_Name().indexOf("_");
        String docName = index != -1 ? doc.get_Name().substring(0, index) : doc.get_Name();
        doc.getProperties().putValue( "DocumentTitle", docName + "_" + doc.get_CurrentState() );
    }
	
    public void onDocumentSetException( Document doc, DocumentLifecyclePolicy policy ) throws EngineRuntimeException
    {
        int index = doc.get_Name().indexOf("_");
        String docName = index != -1 ? doc.get_Name().substring(0, index) : doc.get_Name();
        doc.getProperties().putValue( "DocumentTitle", docName + "_" + doc.get_CurrentState() +"_InException" );
    }
	
    public void onDocumentClearException( Document doc, DocumentLifecyclePolicy policy ) throws EngineRuntimeException
    {
        int index = doc.get_Name().indexOf("_");
        String docName = index != -1 ? doc.get_Name().substring(0, index) : doc.get_Name();
        doc.getProperties().putValue( "DocumentTitle", docName + "_" + doc.get_CurrentState() );
    }
	
    public void onDocumentResetLifecycle( Document doc, DocumentLifecyclePolicy policy ) throws EngineRuntimeException
    {
        int index = doc.get_Name().indexOf("_");
        String docName = index != -1 ? doc.get_Name().substring(0, index) : doc.get_Name();
        doc.getProperties().putValue( "DocumentTitle", docName + "_" + doc.get_CurrentState() );
    }
}

Creating a DocumentLifecycleAction Object

A DocumentLifecycleAction object identifies the document lifecycle action handler to be launched when a document's state changes. The following Java and C# code snippets show how to create a DocumentLifecycleAction object and set the properties that associate it with a document lifecycle action handler: ProgId and, conditionally, CodeModule. You must set the ProgId property with the fully qualified name of the handler class. If, as shown in the examples, the event action handler is contained within a CodeModule stored in an object store, you must also get the CodeModule object, then assign it to the CodeModule property of the DocumentLifecycleAction object. Note that you cannot set the CodeModule property to a reservation (in progress) version of CodeModule. For more information, see Creating a CodeModule Object.

NOTE Do not set the CodeModule property if you set the application server's class path to the location of the document lifecycle action handler.

When saved, a DocumentLifecycleAction object is stored in the Document Lifecycles/Document Lifecycle Actions folder of a Content Engine object store.

Java Example

...
   // Create lifecycle action
   DocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.createInstance(os, 
              ClassNames.DOCUMENT_LIFECYCLE_ACTION);
   // Set ProgId property with fully qualified name of handler class
   lifecycleAction.set_ProgId("sample.actionhandler.LifecycleActionHandler");
   // Get CodeModule object.
   CodeModule cm = Factory.CodeModule.getInstance( os, 
              ClassNames.CODE_MODULE, new Id("{5653773F-D5F2-4292-8684-55E60A654F6B}") ); 
   // Set CodeModule property
   lifecycleAction.set_CodeModule(cm);
   lifecycleAction.set_DisplayName("LoanLifecycleAction");
   lifecycleAction.save(RefreshMode.REFRESH);
}

C# Example

...
   // Create event action
   IDocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.CreateInstance(os, 
              ClassNames.DOCUMENT_LIFECYCLE_ACTION);
   // Set ProgId property with fully qualified name of handler class
   lifecycleAction.ProgId = "sample.actionhandler.LifecycleActionHandler";
   // Get CodeModule object
   ICodeModule cm = Factory.CodeModule.GetInstance(os, 
              ClassNames.CODE_MODULE, new Id("{5653773F-D5F2-4292-8684-55E60A654F6B}") );
   // Set CodeModule property.
   lifecycleAction.CodeModule = cm;
   lifecycleAction.DisplayName = "LoanLifecycleAction";
   lifecycleAction.Save(RefreshMode.REFRESH);
}

Creating a DocumentLifecyclePolicy Object

After creating the document lifecycle action handler and the DocumentLifecycleAction object, you're ready to create a DocumentLifecyclePolicy object and persist it to an object store.

The following Java and C# examples show how to create a DocumentLifecyclePolicy object to be used in a simple loan application client program. Essentially, you create the DocumentLifecyclePolicy object and set its key properties, DocumentLifecycleAction and DocumentStates. The DocumentLifecycleAction property is set to an existing object, whereas the DocumentStates property is set to newly created DocumentState objects, each of which represents a state in a loan application process. With a client program, users will be able to change the states of a loan application document starting with the "Application" state and ending with the "Closed" state.

Note the properties that are set on the last DocumentState object, which represents the "Closed" state. The CanBeDemoted property is set to FALSE, preventing users from reverting a closed loan application to its immediately preceding state, "Servicing". Also set is the TemplatePermissions property, which allows a document's security to be changed on a per-state basis. The property is set to an AccessPermissionList object, returned by the setStatePermissions method shown in the code example. The setStatePermissions method gives the loan manager full control of a loan application, but denies write permission to the loan processing group. Therefore, when a loan application is closed, the new permissions will be applied to the loan application, preventing all users in the loan processing group from resetting the lifecycle. Only the manager of the group will have permission to reset the lifecycle to its initial state, "Application".

When saved, a DocumentLifecyclePolicy object is stored in the Document Lifecycles/Document Lifecycle Policies folder of a Content Engine object store.

Java Example

...
   // Create DocumentLifecyclePolicy object and name the policy
   DocumentLifecyclePolicy lifecyclePolicy = Factory.DocumentLifecyclePolicy.createInstance(os,
                  ClassNames.DOCUMENT_LIFECYCLE_POLICY);
   lifecyclePolicy.set_DisplayName("LoanLifecyclePolicy");

   // Get DocumentLifecycleAction created in previous example,
   // and set policy's DocumentLifecycleAction property
   DocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.fetchInstance(os, 
                  new Id("{4250EEB5-A11F-4BA0-A542-2AEB246204C3}"), null);
   lifecyclePolicy.set_DocumentLifecycleAction(lifecycleAction);

   // Create DocumentState objects for a loan application
   DocumentState ds1 = Factory.DocumentState.createInstance();
   ds1.set_StateName("Application");
   DocumentState ds2 = Factory.DocumentState.createInstance();
   ds2.set_StateName("Approval");
   DocumentState ds3 = Factory.DocumentState.createInstance();
   ds3.set_StateName("Funding");
   DocumentState ds4 = Factory.DocumentState.createInstance();
   ds4.set_StateName("Servicing");
   DocumentState ds5 = Factory.DocumentState.createInstance();
   ds5.set_StateName("Closed");
   ds5.set_CanBeDemoted(Boolean.FALSE);
   ds5.set_TemplatePermissions(setStatePermissions());
   ds5.set_ApplyTemplatePermissions(Boolean.TRUE);

   // Create DocumentStateList, and set policy's DocumentStates property
   DocumentStateList dsl = Factory.DocumentState.createList();
   dsl.add(ds1);
   dsl.add(ds2);
   dsl.add(ds3);
   dsl.add(ds4);
   dsl.add(ds5);
   lifecyclePolicy.set_DocumentStates(dsl);

   // Allow permissions defined in lifecycle policy to override document permissions
   lifecyclePolicy.set_PreserveDirectPermissions(Boolean.FALSE);
   
   // Commit changes to lifecycle policy object
   lifecyclePolicy.save(RefreshMode.REFRESH);
}

public AccessPermissionList setStatePermissions()
{
   AccessPermissionList apl = Factory.AccessPermission.createList();
   
   AccessPermission permManager = Factory.AccessPermission.createInstance();
   permManager.set_GranteeName("loan manager");
   AccessLevel al = AccessLevel.FULL_CONTROL;
   int intMask = al.getValue();
   permManager.set_AccessMask(new Integer(intMask));
   AccessType at = AccessType.ALLOW;
   permManager.set_AccessType(at);
   apl.add(permManager);
   
   AccessPermission permGroup = Factory.AccessPermission.createInstance();
   permGroup.set_GranteeName("loan processing group");
   al = AccessLevel.WRITE_DEFAULT;
   intMask = al.getValue();
   permGroup.set_AccessMask(new Integer(intMask));
   at = AccessType.DENY;
   permGroup.set_AccessType(at);
   apl.add(permGroup);
   
   return apl;
}

C# Example

...
   // Create DocumentLifecyclePolicy object and name the policy
   IDocumentLifecyclePolicy lifecyclePolicy = Factory.DocumentLifecyclePolicy.CreateInstance(os,
                  ClassNames.DOCUMENT_LIFECYCLE_POLICY);
   lifecyclePolicy.DisplayName = "LoanLifecyclePolicyC#";

   // Get DocumentLifecycleAction created in previous example,
   // and set policy's DocumentLifecycleAction property
            IDocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.FetchInstance(os,
   new Id("{4250EEB5-A11F-4BA0-A542-2AEB246204C3}"), null);
   lifecyclePolicy.DocumentLifecycleAction = lifecycleAction;

   // Create DocumentState objects for a loan application
   IDocumentState ds1 = Factory.DocumentState.CreateInstance();
   ds1.StateName = "Application";
   IDocumentState ds2 = Factory.DocumentState.CreateInstance();
   ds2.StateName = "Approval";
   IDocumentState ds3 = Factory.DocumentState.CreateInstance();
   ds3.StateName = "Funding";
   IDocumentState ds4 = Factory.DocumentState.CreateInstance();
   ds4.StateName = "Servicing";
   IDocumentState ds5 = Factory.DocumentState.CreateInstance();
   ds5.StateName = "Closed";
   ds5.CanBeDemoted = false;
   ds5.TemplatePermissions = setStatePermissions();
   ds5.ApplyTemplatePermissions = true;

   // Create DocumentStateList, and set policy's DocumentStates property
   IDocumentStateList dsl = Factory.DocumentState.CreateList();
   dsl.Add(ds1);
   dsl.Add(ds2);
   dsl.Add(ds3);
   dsl.Add(ds4);
   dsl.Add(ds5);
   lifecyclePolicy.DocumentStates = dsl;

   // Allow permissions defined in lifecycle policy to override document permissions
   lifecyclePolicy.PreserveDirectPermissions = false;

   // Commit changes to lifecycle policy object
   lifecyclePolicy.Save(RefreshMode.REFRESH);
}

public IAccessPermissionList setStatePermissions()
{
   IAccessPermissionList apl = Factory.AccessPermission.CreateList();

   IAccessPermission permManager = Factory.AccessPermission.CreateInstance();
   permManager.GranteeName = "loan manager";
   permManager.AccessMask = (int)AccessLevel.FULL_CONTROL;
   permManager.AccessType = AccessType.ALLOW;
   apl.Add(permManager);

   IAccessPermission permGroup = Factory.AccessPermission.CreateInstance();
   permGroup.GranteeName = "loan processing group";
   permGroup.AccessMask = (int) AccessLevel.WRITE_DEFAULT;
   permGroup.AccessType = AccessType.DENY;
   apl.Add(permGroup);

   return apl;
}

Assigning a DocumentLifecycle Policy Object

As shown in the subsections below, you can assign a document lifecycle policy to individual Document objects, or to the Document class or any of its subclasses. Note that for a Document object, you can assign a document lifecycle policy to it only when you create the Document object; you cannot update an existing Document object with a document lifecycle policy.

A document lifecycle policy attached to a class automatically applies to all new Document objects of that class type, unless you explicitly set a different document lifecycle policy when you create a document of that class type.

Assigning to a Document Object

The following Java and C# examples show how to assign an existing DocumentLifecyclePolicy object to a newly created document.

Java Example

...
   Document doc=Factory.Document.createInstance(os, null);
   doc.getProperties().putValue("DocumentTitle", "CarLoanApplication");
   DocumentLifecyclePolicy dlcp = Factory.DocumentLifecyclePolicy.getInstance(os, ClassNames.DOCUMENT_LIFECYCLE_POLICY,
            new Id("{47A1D313-ADC8-4A53-90CC-66B83ABAF229}") );
   doc.set_DocumentLifecyclePolicy(dlcp);
   doc.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
   doc.save(RefreshMode.REFRESH);
}

C# Example

...
IDocument doc=Factory.Document.CreateInstance(os, null);
   doc.Properties["DocumentTitle"] = "CarLoanApplication";
   IDocumentLifecyclePolicy dlcp = Factory.DocumentLifecyclePolicy.GetInstance(os, ClassNames.DOCUMENT_LIFECYCLE_POLICY,
            new Id("{47A1D313-ADC8-4A53-90CC-66B83ABAF229}"));
   doc.DocumentLifecyclePolicy = dlcp;
   doc.Checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
   doc.Save(RefreshMode.REFRESH);
}

Assigning to a Document Class

The following Java and C# examples show how to assign an existing DocumentLifecyclePolicy object to the Document class. The examples essentially involve the DocumentClassDefinition object, which represents the class definition of the Document class, and the PropertyDefinition object that represents the lifecycle policy system property of the Document class. The examples retrieve a list of the PropertyDefinition objects of the Document class, and iterate the list until it finds the PropertyDefinition object for the document lifecycle policy property. By default, this property has no value. Given that it takes a DocumentLifecyclePolicy object value, the PropertyDefinition object is cast to a PropertyDefinitionObject object, and then is assigned a DocumentLifecyclePolicy object.

Java Example

...
   // The GUID is for the "Document Class" ClassDefinition object.
   DocumentClassDefinition classDef = Factory.DocumentClassDefinition.fetchInstance(os, 
          new Id("{01A3A8C2-7AEC-11D1-A31B-0020AF9FBB1C}"), null);
   PropertyDefinitionList propDefList = classDef.get_PropertyDefinitions();
   PropertyDefinition propertyDef = null;
   Iterator iter = propDefList.iterator();
   while (iter.hasNext()) 
   {
      propertyDef = (PropertyDefinition)iter.next();
      if ( propertyDef.get_SymbolicName().equals("DocumentLifecyclePolicy") ) 
         break;
   }
   DocumentLifecyclePolicy dlp = Factory.DocumentLifecyclePolicy.getInstance(os, 
          ClassNames.DOCUMENT_LIFECYCLE_POLICY, new Id("{A94B2678-D9C6-4DA2-9D1A-D12482B8A125}") );
   PropertyDefinitionObject propertyDefObject = (PropertyDefinitionObject)propertyDef;
   propertyDefObject.set_PropertyDefaultObject(dlp);
   classDef.save(RefreshMode.REFRESH);
}

C# Example

...
   // The GUID is for the "Document Class" ClassDefinition object.
   IDocumentClassDefinition classDef = Factory.DocumentClassDefinition.FetchInstance(os, 
          new Id("{01A3A8C2-7AEC-11D1-A31B-0020AF9FBB1C}"), null);
   IPropertyDefinitionList propDefList = classDef.PropertyDefinitions;
   IPropertyDefinition propertyDef = null;
   System.Collections.IEnumerator propDefListIter = propDefList.GetEnumerator();
   while (propDefListIter.MoveNext())
   {
      propertyDef = (IPropertyDefinition)propDefListIter.Current;
      if ( propertyDef.SymbolicName.Equals("DocumentLifecyclePolicy") ) 
         break;
   }
   IDocumentLifecyclePolicy dlp = Factory.DocumentLifecyclePolicy.GetInstance(os,
          ClassNames.DOCUMENT_LIFECYCLE_POLICY, new Id("{A94B2678-D9C6-4DA2-9D1A-D12482B8A125}"));
   IPropertyDefinitionObject propertyDefObject = (IPropertyDefinitionObject)propertyDef;
   propertyDefObject.PropertyDefaultObject = dlp;
   classDef.Save(RefreshMode.REFRESH);
}

Changing a Document's State

As shown in the following Java and C# examples, you can get the current state of a Document object to which a DocumentLifecyclePolicy object is attached, as well as change the state of the Document object.

Getting the current state returns a string that reflects one of the user-defined states represented by a DocumentState object.

The changeState method takes a LifecycleChangeFlags constant. Note that you must save the Document object to commit the change (not shown).

Java Example

// Get current state
String state = document.get_CurrentState();

// Change current state
document.changeState(LifecycleChangeFlags.PROMOTE);

C# Example

// Get current state
String state = document.CurrentState;

// Change current state
document.ChangeState(LifecycleChangeFlags.PROMOTE);

Retrieving DocumentLifecyclePolicy Objects

You can get a single DocumentLifecyclePolicy object with a Factory.DocumentLifecylePolicy method, or by retrieving the DocumentLifecyclePolicy property on a Document object. You can also get a collection of DocumentLifecyclePolicy objects (DocumentLifecyclePolicySet) by retrieving the DocumentLifecyclePolicies property on a DocumentLifecycleAction object or on an ObjectStore object.

A DocumentLifecycleAction object, which is associated with a document lifecycle action handler, can be contained by multiple DocumentLifecyclePolicy objects if you code a single handler to service multiple document lifecycle policies. As shown in Creating a Lifecycle Action Handler, each method in the DocumentLifecycleActionHandler interface is passed a DocumentLifecyclePolicy object. Therefore, you can code conditional actions in a handler based on which DocumentLifecyclePolicy object is passed to the handler.

The following Java and C# examples show how to retrieve a DocumentLifecyclePolicySet collection from a DocumentLifecycleAction object. For each DocumentLifecyclePolicy object in the collection, the DocumentStates property is retrieved, which is set with a DocumentStateList value. The examples iterate the list and print the name of each DocumentState object.

Java Example

...
   DocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.fetchInstance(os, 
                new Id("{4250EEB5-A11F-4BA0-A542-2AEB246204C3}"), null);
   DocumentLifecyclePolicySet dlpSet = lifecycleAction.get_DocumentLifecyclePolicies();
   DocumentLifecyclePolicy dlpObject;
   DocumentState ds;
   Iterator iterOuter = dlpSet.iterator();
   while (iterOuter.hasNext()) 
   {
      dlpObject = (DocumentLifecyclePolicy)iterOuter.next();
      System.out.println("DocumentLifecyclePolicy: " + dlpObject.get_DisplayName() );
      DocumentStateList dsList = dlpObject.get_DocumentStates();
      Iterator iterInner = dsList.iterator();
      while (iterInner.hasNext())
      {
         ds = (DocumentState)iterInner.next(); 
         System.out.println("   DocumentState: " + ds.get_StateName() );
      }
   }
}

C# Example

...
   IDocumentLifecycleAction lifecycleAction = Factory.DocumentLifecycleAction.FetchInstance(os,
                new Id("{4250EEB5-A11F-4BA0-A542-2AEB246204C3}"), null);
   IDocumentLifecyclePolicySet dlpSet = lifecycleAction.DocumentLifecyclePolicies;
   IDocumentLifecyclePolicy dlpObject;
   IDocumentState ds;
   System.Collections.IEnumerator iterOuter = dlpSet.GetEnumerator();
   while (iterOuter.MoveNext())
   {
      dlpObject = (IDocumentLifecyclePolicy)iterOuter.Current;
      System.Console.WriteLine("DocumentLifecyclePolicy: " + dlpObject.DisplayName);
      IDocumentStateList dsList = dlpObject.DocumentStates;
      System.Collections.IEnumerator iterInner = dsList.GetEnumerator();
      while (iterInner.MoveNext())
      {
         ds = (IDocumentState)iterInner.Current;
         System.Console.WriteLine("   DocumentState: " + ds.StateName);
      }
   }
}