オープンソースのワークフロー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です。 
  
 <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>