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.
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() ); } }
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); }
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; }
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.
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); }
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); }
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);
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); } } }