オープンソースのワークフローFireflowソース分析のプロセスファイル解析
17380 ワード
Javaがxmlを解析するのは難しくないです。fireflowの作者はdom 4 jを使って解析します。具体的な解析の種類はDom 4 JPDDL Paserです。他にもDom 4 JFP_Dlerializerの種類があります。ワークフローモデルをXmlと書く役割を果たしています。
1):どのようにxml解像器を配置するかについて、著者は二つのモードを提供しています。一つは開発段階用のdefinitionService 4 FileSystemで、一つは実施段階のdefinitionService 4 DBMSです。
注意してください。開発段階でworkflowProcessをキャッシュする役割はテストを加速することです。他の意味はありません。作者が本当にキャッシュしているのはワークフローの実例です。これは後話です。
著者のソースファイルは説明がよくそろっている。
1):どのようにxml解像器を配置するかについて、著者は二つのモードを提供しています。一つは開発段階用のdefinitionService 4 FileSystemで、一つは実施段階のdefinitionService 4 DBMSです。
<bean id="definitionService4FileSystem"
class="org.fireflow.engine.definition.DefinitionService4FileSystem">
<property name="definitionFiles">
<list>
<value>
/process_definition/LeaveApplicationProcess.xml
</value>
</list>
</property>
</bean>
<bean id="runtimeContext"
class="org.fireflow.engine.RuntimeContext"
init-method="initialize">
……
<property name="definitionService">
<ref local="definitionService4FileSystem"/>
</property>
……
</bean>
2):開発段階であれば、システム起動時に自動的にxmlを解析し、キャッシュを行います。実施段階であれば、起動時には解析しません。初めて使うと、システムが解析します。注意してください。開発段階でworkflowProcessをキャッシュする役割はテストを加速することです。他の意味はありません。作者が本当にキャッシュしているのはワークフローの実例です。これは後話です。
// definitionService4FileSystem: xml .
public void setDefinitionFiles(List<String> workflowProcessFileNames)
throws IOException, FPDLParserException,EngineException {
if (workflowProcessFileNames != null) {
Dom4JFPDLParser parser = new Dom4JFPDLParser();
for (int i = 0; i < workflowProcessFileNames.size(); i++) {
InputStream inStream = this.getClass().getResourceAsStream(
workflowProcessFileNames.get(i).trim());
if (inStream == null) {
throw new IOException(" " + workflowProcessFileNames.get(i) + " ");
}
WorkflowProcess workflowProcess = parser.parse(inStream);
WorkflowDefinition workflowDef = new WorkflowDefinition();
workflowDef.setVersion(new Integer(1));
workflowDef.setWorkflowProcess(workflowProcess);
String latestVersionKey = workflowProcess.getId() + "_V_" + workflowDef.getVersion();
workflowDefinitionMap.put(latestVersionKey, workflowDef);
latestVersionKeyMap.put(workflowProcess.getId(), latestVersionKey);
}
}
// , definitionService4DBMS xml
// ID
public WorkflowDefinition getWorkflowDefinitionByProcessIdAndVersionNumber(String id, Integer version) {
return rtCtx.getPersistenceService().findWorkflowDefinitionByProcessIdAndVersionNumber(id, version);
}
(WorkflowDefinition) getWorkflowprocess
//WorkflowDefinition.java,
public WorkflowProcess getWorkflowProcess() throws RuntimeException{
if (workflowProcess == null) {
if (this.processContent != null && !this.processContent.trim().equals("")) {
ByteArrayInputStream in = null;
try {
Dom4JFPDLParser parser = new Dom4JFPDLParser();// dom4j xml
in = new ByteArrayInputStream(this.processContent.getBytes("utf-8"));
this.workflowProcess = parser.parse(in);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(WorkflowDefinition.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex.getMessage());
} catch (IOException ex) {
Logger.getLogger(WorkflowDefinition.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex.getMessage());
}
catch(FPDLParserException ex){
Logger.getLogger(WorkflowDefinition.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex.getMessage());
} finally {
try {
in.close();
} catch (IOException ex) {
Logger.getLogger(WorkflowDefinition.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
return workflowProcess;
}
3):ワークフローモデルとxmlの対応関係を明らかにする。これは簡単です。WorkflowProcess.javaファイルとxml例を見れば一目瞭然です。著者のソースファイルは説明がよくそろっている。
public class WorkflowProcess extends AbstractWFElement {
/**
* , 。
*/
private List<DataField> dataFields = new ArrayList<DataField>();
/**
* Task
*/
private List<Task> tasks = new ArrayList<Task>();
/**
*
*/
private List<Activity> activities = new ArrayList<Activity>();
/**
*
*/
private List<Transition> transitions = new ArrayList<Transition>();
/**
*
*/
private List<Loop> loops = new ArrayList<Loop>();
/**
*
*/
private List<Synchronizer> synchronizers = new ArrayList<Synchronizer>();
/**
*
*/
private StartNode startNode = null;
/**
*
*/
private List<EndNode> endNodes = new ArrayList<EndNode>();
//
/**
* ( 1.0 )
*/
private String resourceFile = null;
/**
* ( 1.0 )
*/
private String resourceManager = null;
/**
* 。 , DefaultTaskInstanceCreator TaskInstance。
*/
protected String taskInstanceCreator = null;
/**
* FormTask
* Instance 。 , DefaultFormTaskInstanceRunner TaskInstance。
*/
protected String formTaskInstanceRunner = null;
/**
* ToolTask
* Instance 。 , DefaultToolTaskInstanceRunner TaskInstance。
*/
protected String toolTaskInstanceRunner = null;
/**
* SubflowTask
* Instance 。 , DefaultSubflowTaskInstanceRunner TaskInstance。
*/
protected String subflowTaskInstanceRunner = null;
/**
* FormTask Instance , 。<br/>
* , DefaultFormTaskInstanceCompletionEvaluator。
*/
protected String formTaskInstanceCompletionEvaluator = null;
/**
* ToolTask Instance , 。<br/>
* , DefaultToolTaskInstanceCompletionEvaluator。
*/
protected String toolTaskInstanceCompletionEvaluator = null;
/**
* SubflowTask Instance , 。<br/>
* , DefaultSubflowTaskInstanceCompletionEvaluator。
*/
protected String subflowTaskInstanceCompletionEvaluator = null;
…….
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE fpdl:WorkflowProcess PUBLIC "-//Nieyun Chen//ProcessDefinition//CN" "FireFlow_Process_Definition_Language.dtd">
<fpdl:WorkflowProcess DisplayName="LeaveApplicationProcess" Id="LeaveApplicationProcess" Name="LeaveApplicationProcess" ResourceFile="" ResourceManager="" xmlns:fpdl="http://www.fireflow.org/Fireflow_Process_Definition_Language">
<fpdl:DataFields>
<fpdl:DataField DataType="INTEGER" DisplayName=" " Id="LeaveApplicationProcess.leaveDays" InitialValue="1" Name="leaveDays"/>
<fpdl:DataField DataType="BOOLEAN" DisplayName=" " Id="LeaveApplicationProcess.approvalFlag" InitialValue="false" Name="approvalFlag"/>
</fpdl:DataFields>
<fpdl:StartNode DisplayName="" Id="LeaveApplicationProcess.START_NODE" Name="START_NODE">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="18"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="86"/>
</fpdl:ExtendedAttributes>
</fpdl:StartNode>
<fpdl:Tasks/>
<fpdl:Activities>
<fpdl:Activity CompletionStrategy="ALL" DisplayName=" " Id="LeaveApplicationProcess.Fulfill_The_ApplicationForm_Activity" Name="Fulfill_The_ApplicationForm_Activity">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="60"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="100"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="97"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="65"/>
</fpdl:ExtendedAttributes>
<fpdl:Tasks>
<fpdl:Task CompletionStrategy="ANY" DefaultView="EDITFORM" DisplayName=" " Id="LeaveApplicationProcess.Fulfill_The_ApplicationForm_Activity.Fulfill_The_ApplicationForm_Task" LoopStrategy="REDO" Name="Fulfill_The_ApplicationForm_Task" Priority="1" Type="FORM">
<fpdl:Performer DisplayName=" " Name="Self">
<fpdl:Description/>
<fpdl:AssignmentHandler>org.fireflow.example.leaveapplication.workflowextension.CurrentUserAssignmentHandler</fpdl:AssignmentHandler>
</fpdl:Performer>
<fpdl:EditForm DisplayName=" " Name="ApplicationForm">
<fpdl:Description/>
<fpdl:Uri>/org/fireflow/example/leaveapplication/bizpages/SubmitApplication.jsp</fpdl:Uri>
</fpdl:EditForm>
</fpdl:Task>
</fpdl:Tasks>
<fpdl:TaskRefs/>
</fpdl:Activity>
<fpdl:Activity CompletionStrategy="ALL" DisplayName=" " Id="LeaveApplicationProcess.DepartmentManager_Approve_Activity" Name="DepartmentManager_Approve_Activity">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="60"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="100"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="279"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="66"/>
</fpdl:ExtendedAttributes>
<fpdl:Tasks>
<fpdl:Task CompletionStrategy="ANY" DefaultView="EDITFORM" DisplayName=" " Id="LeaveApplicationProcess.DepartmentManager_Approve_Activity.Approval_Task" LoopStrategy="REDO" Name="Approval_Task" Priority="1" Type="FORM">
<fpdl:Performer DisplayName=" " Name="DepartmentManager">
<fpdl:Description/>
<fpdl:AssignmentHandler>org.fireflow.example.leaveapplication.workflowextension.RoleDepartmentBasedAssignmentHandler</fpdl:AssignmentHandler>
</fpdl:Performer>
<fpdl:EditForm DisplayName=" " Name="ApprovalForm">
<fpdl:Description/>
<fpdl:Uri>/org/fireflow/example/leaveapplication/bizpages/ApproveLeaveApplication.jsp</fpdl:Uri>
</fpdl:EditForm>
</fpdl:Task>
</fpdl:Tasks>
<fpdl:TaskRefs/>
</fpdl:Activity>
<fpdl:Activity CompletionStrategy="ALL" DisplayName=" " Id="LeaveApplicationProcess.Send_Email_Activity" Name="Send_Email_Activity">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="60"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="204"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="540"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="65"/>
</fpdl:ExtendedAttributes>
<fpdl:Tasks>
<fpdl:Task DisplayName=" " Execution="SYNCHR" Id="LeaveApplicationProcess.Send_Email_Activity.Send_Email_Task" LoopStrategy="REDO" Name="Send_Email_Task" Priority="1" Type="TOOL">
<fpdl:Application DisplayName=" " Name="EmailSender">
<fpdl:Description/>
<fpdl:Handler>org.fireflow.example.leaveapplication.workflowextension.EmailSender</fpdl:Handler>
</fpdl:Application>
</fpdl:Task>
</fpdl:Tasks>
<fpdl:TaskRefs/>
</fpdl:Activity>
</fpdl:Activities>
<fpdl:Synchronizers>
<fpdl:Synchronizer DisplayName="" Id="LeaveApplicationProcess.Synchronizer1" Name="Synchronizer1">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="228"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="85"/>
</fpdl:ExtendedAttributes>
</fpdl:Synchronizer>
<fpdl:Synchronizer DisplayName="" Id="LeaveApplicationProcess.Synchronizer2" Name="Synchronizer2">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="450"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="86"/>
</fpdl:ExtendedAttributes>
</fpdl:Synchronizer>
</fpdl:Synchronizers>
<fpdl:EndNodes>
<fpdl:EndNode DisplayName="" Id="LeaveApplicationProcess.EndNode1" Name="EndNode1">
<fpdl:ExtendedAttributes>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.height" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.width" Value="20"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.x" Value="814"/>
<fpdl:ExtendedAttribute Name="FIRE_FLOW.bounds.y" Value="85"/>
</fpdl:ExtendedAttributes>
</fpdl:EndNode>
</fpdl:EndNodes>
<fpdl:Transitions>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.START_NODE" Id="LeaveApplicationProcess.Transition1" Name="Transition1" To="LeaveApplicationProcess.Fulfill_The_ApplicationForm_Activity">
<fpdl:Condition/>
</fpdl:Transition>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.Fulfill_The_ApplicationForm_Activity" Id="LeaveApplicationProcess.Transition2" Name="Transition2" To="LeaveApplicationProcess.Synchronizer1">
<fpdl:Condition/>
</fpdl:Transition>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.Synchronizer1" Id="LeaveApplicationProcess.Transition3" Name="Transition3" To="LeaveApplicationProcess.DepartmentManager_Approve_Activity">
<fpdl:Condition/>
</fpdl:Transition>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.DepartmentManager_Approve_Activity" Id="LeaveApplicationProcess.Transition4" Name="Transition4" To="LeaveApplicationProcess.Synchronizer2">
<fpdl:Condition/>
</fpdl:Transition>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.Send_Email_Activity" Id="LeaveApplicationProcess.Transition11" Name="Transition11" To="LeaveApplicationProcess.EndNode1">
<fpdl:Condition/>
</fpdl:Transition>
<fpdl:Transition DisplayName="" From="LeaveApplicationProcess.Synchronizer2" Id="LeaveApplicationProcess.Transition6" Name="Transition6" To="LeaveApplicationProcess.Send_Email_Activity">
<fpdl:Condition/>
</fpdl:Transition>
</fpdl:Transitions>
</fpdl:WorkflowProcess>