/** * Copyright 2007-2010 非也 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License v3 as published by the Free Software * Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, see http://www.gnu.org/licenses/lgpl.html. * */ package org.fireflow.pdl.fpdl.process.impl; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections.list.SetUniqueList; import org.apache.commons.lang.StringUtils; import org.fireflow.model.AbstractModelElement; import org.fireflow.model.ModelElement; import org.fireflow.model.data.Property; import org.fireflow.model.misc.Duration; import org.fireflow.model.process.WorkflowElement; import org.fireflow.model.process.lifecycle.InstanceCreatorDef; import org.fireflow.model.process.lifecycle.InstanceExecutorDef; import org.fireflow.model.process.lifecycle.InstanceTerminatorDef; import org.fireflow.pdl.fpdl.process.Activity; import org.fireflow.pdl.fpdl.process.EndNode; import org.fireflow.pdl.fpdl.process.Node; import org.fireflow.pdl.fpdl.process.Router; import org.fireflow.pdl.fpdl.process.StartNode; import org.fireflow.pdl.fpdl.process.SubProcess; import org.fireflow.pdl.fpdl.process.Transition; import org.fireflow.pdl.fpdl.process.event.EventListenerDef; /** * * @author 非也 nychen2000@163.com * Fire Workflow 官方网站:www.firesoa.com 或者 www.fireflow.org * */ public class SubProcessImpl extends AbstractModelElement implements SubProcess { private Duration duration = null; /** * 流程数据项,运行时转换为流程变量进行存储。 */ private List<Property> properties = new ArrayList<Property>(); private Node entry = null; /** * 流程环节 */ private List<Activity> activities = SetUniqueList.decorate(new ArrayList<Activity>()); /** * 转移 */ private List<Transition> transitions = new ArrayList<Transition>(); /** * 路由器 */ private List<Router> routers = new ArrayList<Router>(); /** * 开始节点 */ private List<StartNode> startNodes = new ArrayList<StartNode>(); /** * 结束节点 */ private List<EndNode> endNodes = new ArrayList<EndNode>(); /** * 事件监听器注册表 */ private List<EventListenerDef> eventListenerDefs = new ArrayList<EventListenerDef>(); private InstanceCreatorDef instanceCreatorDef = null; private InstanceExecutorDef instanceExecutorDef = null; private InstanceTerminatorDef instanceTerminatorDef = null; /** * 构造函数。当采用该函数时,displayName默认等于name; * @param parentElement * @param name flow的name属性,必须符合java变量的命名规范 */ public SubProcessImpl(ModelElement parentElement, String name) { super(parentElement,name); } /** * 构造函数。 * @param parentElement * @param name flow的name属性,必须符合java变量的命名规范 * @param displayName flow的显示名称,可以是中文 */ public SubProcessImpl(ModelElement parentElement, String name,String displayName) { super(parentElement,name,displayName); } /** * 获得该子流程的预计的运行时间 * @return */ public Duration getDuration(){ return this.duration; } /** * 返回该子流程的预计的运行时间 * @param du */ public void setDuration(Duration du){ this.duration = du; } /** * 通过Id查找任意元素的序列号,该方法提供给设计器使用,外部系统禁止使用该方法。 * * @param id * 流程元素的id * @return 流程元素的序列号 */ // public String findSnById(String id) { // ModelElement elem = this.findWFElementById(id); // if (elem != null) { // return elem.getSn(); // } // return null; // } public Node getEntry() { return this.entry; } public List<Router> getRouters() { return this.routers; } public void setEntry(Node start) { this.entry = start; } public Activity getActivity(String activityId) { if (this.activities != null) { for (Activity elm : this.activities) { if (elm.getId().equals(activityId)) { return elm; } } } return null; } public EndNode getEndNode(String endNodeId) { if (this.endNodes != null) { for (EndNode elm : this.endNodes) { if (elm.getId().equals(endNodeId)) { return elm; } } } return null; } public Router getRouter(String routerId) { if (this.routers != null) { for (Router elm : this.routers) { if (elm.getId().equals(routerId)) { return elm; } } } return null; } public StartNode getStartNode(String startNodeId) { if (this.startNodes != null) { for (StartNode startNode : this.startNodes) { if (startNode.getId().equals(startNodeId)) { return startNode; } } } return null; } public Transition getTransition(String transitionId) { if (this.transitions != null) { for (Transition transition : this.transitions) { if (transition.getId().equals(transitionId)) { return transition; } } } return null; } /** * 返回所有的流程数据项 * * @return */ public List<Property> getProperties() { return properties; } /** * 返回所有的环节 * * @return */ public List<Activity> getActivities() { return activities; } /** * 返回所有的转移 * * @return */ public List<Transition> getTransitions() { return transitions; } /** * 返回开始节点 * * @return */ public List<StartNode> getStartNodes() { return startNodes; } public List<EventListenerDef> getEventListeners() { return eventListenerDefs; } /** * 返回所有的结束节点 * * @return */ public List<EndNode> getEndNodes() { return endNodes; } /** * 通过ID查找该流程中的任意元素 * * @param argId * 元素的Id * @return 流程元素,如:Activity,Task,Synchronizer等等 */ public WorkflowElement findWFElementById(String argId) { if (this.getId().equals(argId)) { return this; } int i = 0; List<StartNode> startNodes = this.getStartNodes(); for (StartNode startNode : startNodes){ if (argId.equals(startNode.getId())){ return startNode; } } List<Activity> activityList = this.getActivities(); for (i = 0; i < activityList.size(); i++) { Activity activity = activityList.get(i); if (activity.getId().equals(argId)) { return activity; } } List<Router> routers = this.getRouters(); for (Router router : routers){ if (argId.equals(router.getId())){ return router; } } List<EndNode> endNodeList = this.getEndNodes(); for (i = 0; i < endNodeList.size(); i++) { EndNode endNode =endNodeList.get(i); if (endNode.getId().equals(argId)) { return endNode; } } List<Transition> transitionList = this.getTransitions(); for (i = 0; i < transitionList.size(); i++) { Transition transition = transitionList.get(i); if (transition.getId().equals(argId)) { return transition; } } return null; } /** * 判断两个Activity是否在同一个执行线上 * * @param activityId1 * @param activityId2 * @return true表示在同一个执行线上,false表示不在同一个执行线上 * @deprecated */ public boolean isInSameLine(String activityId1, String activityId2) { return true; } //在计算可到达节点和可进入节点时,默认节点本身不会形成环路,即节点不能同时是一条连线的输入又是这一条连线的输出 /** * 获取可以到达的节点,相比较于fireflow1.0,2.0中activity和activty之间可以直接有连线,那么应当重写该方法 * * @param nodeId * @return */ public List<NodeImpl> getReachableNodes(String nodeId) { List<NodeImpl> reachableNodes = new ArrayList<NodeImpl>(); NodeImpl location = (NodeImpl)findWFElementById(nodeId); //先把自身添加到可到达节点列表 reachableNodes.add(location); List<Transition> outLines = location.getLeavingTransitions(); for(Transition outLine:outLines){ Node nextNode = outLine.getToNode(); if(!reachableNodes.contains(nextNode)){ reachableNodes.add((NodeImpl)nextNode); for(Transition nextNodeOutLine:nextNode.getLeavingTransitions()){ //防止连线形成环 if(!reachableNodes.contains(nextNodeOutLine.getToNode())){ getReachableNodes(nextNodeOutLine.getToNode().getId()); } } } } return reachableNodes; //----------------------------------------------------------------- /* * List<NodeImpl> reachableNodesList = new ArrayList<NodeImpl>(); * NodeImpl node = (NodeImpl) this.findWFElementById(nodeId); if (node * instanceof ActivityImpl) { ActivityImpl activity = (ActivityImpl) * node; TransitionImpl leavingTransition = * activity.getLeavingTransition(); if (leavingTransition != null) { * NodeImpl toNode = leavingTransition.getToNode(); if (toNode != null) * { reachableNodesList.add(toNode); * reachableNodesList.addAll(getReachableNodes(toNode.getId())); } } } * else if (node instanceof Synchronizer) { Synchronizer synchronizer = * (Synchronizer) node; List<TransitionImpl> leavingTransitions = * synchronizer.getLeavingTransitions(); for (int i = 0; * leavingTransitions != null && i < leavingTransitions.size(); i++) { * TransitionImpl leavingTransition = leavingTransitions.get(i); if * (leavingTransition != null) { NodeImpl toNode = (NodeImpl) * leavingTransition.getToNode(); if (toNode != null) { * reachableNodesList.add(toNode); * reachableNodesList.addAll(getReachableNodes(toNode.getId())); } * * } } } //剔除重复节点 List<NodeImpl> tmp = new ArrayList<NodeImpl>(); * boolean alreadyInTheList = false; for (int i = 0; i < * reachableNodesList.size(); i++) { NodeImpl nodeTmp = * reachableNodesList.get(i); alreadyInTheList = false; for (int j = 0; * j < tmp.size(); j++) { NodeImpl nodeTmp2 = tmp.get(j); if * (nodeTmp2.getId().equals(nodeTmp.getId())) { alreadyInTheList = true; * break; } } if (!alreadyInTheList) { tmp.add(nodeTmp); } } * reachableNodesList = tmp; return reachableNodesList; */ // return null; } /** * 获取进入的节点(activity 或者synchronizer) * * @param nodeId * @return */ public List<NodeImpl> getEnterableNodes(String nodeId) { List<NodeImpl> enterableNodes = new ArrayList<NodeImpl>(); NodeImpl location = (NodeImpl)findWFElementById(nodeId); //先把自身加入到可进入节点列表 enterableNodes.add(location); List<Transition> inLines = location.getEnteringTransitions(); for(Transition inLine:inLines){ Node preNode = inLine.getFromNode(); if(!enterableNodes.contains(preNode)){ enterableNodes.add((NodeImpl)preNode); for(Transition preNodeInLine:preNode.getEnteringTransitions()){ //防止连线形成环 if(!enterableNodes.contains(preNodeInLine.getFromNode())){ getEndNode(preNodeInLine.getFromNode().getId()); } } } } return enterableNodes; //----------------------------------------------------- /* * List<NodeImpl> enterableNodesList = new ArrayList<NodeImpl>(); * NodeImpl node = (NodeImpl) this.findWFElementById(nodeId); if (node * instanceof ActivityImpl) { ActivityImpl activity = (ActivityImpl) * node; TransitionImpl enteringTransition = * activity.getEnteringTransition(); if (enteringTransition != null) { * NodeImpl fromNode = enteringTransition.getFromNode(); if (fromNode != * null) { enterableNodesList.add(fromNode); * enterableNodesList.addAll(getEnterableNodes(fromNode.getId())); } } } * else if (node instanceof Synchronizer) { Synchronizer synchronizer = * (Synchronizer) node; List<TransitionImpl> enteringTransitions = * synchronizer.getEnteringTransitions(); for (int i = 0; * enteringTransitions != null && i < enteringTransitions.size(); i++) { * TransitionImpl enteringTransition = enteringTransitions.get(i); if * (enteringTransition != null) { NodeImpl fromNode = * enteringTransition.getFromNode(); if (fromNode != null) { * enterableNodesList.add(fromNode); * enterableNodesList.addAll(getEnterableNodes(fromNode.getId())); } * * } } } * * //剔除重复节点 //TODO mingjie.mj 20091018 改为使用集合是否更好? List<NodeImpl> tmp = * new ArrayList<NodeImpl>(); boolean alreadyInTheList = false; for (int * i = 0; i < enterableNodesList.size(); i++) { NodeImpl nodeTmp = * enterableNodesList.get(i); alreadyInTheList = false; for (int j = 0; * j < tmp.size(); j++) { NodeImpl nodeTmp2 = tmp.get(j); if * (nodeTmp2.getId().equals(nodeTmp.getId())) { alreadyInTheList = true; * break; } } if (!alreadyInTheList) { tmp.add(nodeTmp); } } * enterableNodesList = tmp; return enterableNodesList; */ // return null; } /** * 判断是否可以从from节点到达to节点 * * @param fromNodeId * from节点的id * @param toNodeId * to节点的id * @return */ public boolean isReachable(String fromNodeId, String toNodeId) { if (fromNodeId == null || toNodeId == null) { return false; } if (fromNodeId.equals(toNodeId)) { return true; } List<NodeImpl> reachableList = this.getReachableNodes(fromNodeId); for (int j = 0; reachableList != null && j < reachableList.size(); j++) { NodeImpl node = reachableList.get(j); if (node.getId().equals(toNodeId)) { return true; } } return false; } /** * 验证workflow process是否完整正确。 * * @return null表示流程正确;否则表示流程错误,返回值是错误原因 */ public String validate() { String errHead = "Workflow process is invalid:"; /* * if (this.getStartNode() == null) { return errHead + * "must have one start node"; } if * (this.getStartNode().getLeavingTransitions().size() == 0) { return * errHead + "start node must have leaving transitions."; } * * List<ActivityImpl> activities = this.getActivities(); for (int i = 0; * i < activities.size(); i++) { ActivityImpl activity = * activities.get(i); String theName = (activity.getDisplayName() == * null || activity .getDisplayName().equals("")) ? activity.getName() : * activity.getDisplayName(); if (activity.getEnteringTransition() == * null) { return errHead + "activity[" + theName + * "] must have entering transition."; } if * (activity.getLeavingTransition() == null) { return errHead + * "activity[" + theName + "] must have leaving transition."; } * * // check tasks List<AbstractTask> taskList = activity.getTasks(); for * (int j = 0; j < taskList.size(); j++) { AbstractTask task = * taskList.get(j); if (task.getType() == null) { return errHead + * "task[" + task.getId() + "]'s taskType can Not be null."; } else if * (task.getType().equals(org.fireflow.model.service.impl.FORM)) { * FormTask formTask = (FormTask) task; if (formTask.getPerformer() == * null) { return errHead + "FORM-task[id=" + task.getId() + * "] must has a performer."; } } else if * (task.getType().equals(org.fireflow.model.service.impl.TOOL)) { * ToolTask toolTask = (ToolTask) task; if (toolTask.getApplication() == * null) { return errHead + "TOOL-task[id=" + task.getId() + * "] must has a application."; } } else if * (task.getType().equals(org.fireflow.model.service.impl.SUBFLOW)) { * SubflowTask subflowTask = (SubflowTask) task; if * (subflowTask.getSubWorkflowProcess() == null) { return errHead + * "SUBPROCESS-task[id=" + task.getId() + "] must has a subflow."; } } else * { return errHead + " unknown task type of task[" + task.getId() + * "]"; } } } * * List<Synchronizer> synchronizers = this.getSynchronizers(); for (int * i = 0; i < synchronizers.size(); i++) { Synchronizer synchronizer = * synchronizers.get(i); String theName = (synchronizer.getDisplayName() * == null || synchronizer .getDisplayName().equals("")) ? * synchronizer.getName() : synchronizer.getDisplayName(); if * (synchronizer.getEnteringTransitions().size() == 0) { return errHead * + "synchronizer[" + theName + "] must have entering transition."; } * if (synchronizer.getLeavingTransitions().size() == 0) { return * errHead + "synchronizer[" + theName + * "] must have leaving transition."; } } * * List<EndNodeImpl> endnodes = this.getEndNodes(); for (int i = 0; i < * endnodes.size(); i++) { EndNodeImpl endnode = endnodes.get(i); String * theName = (endnode.getDisplayName() == null || endnode * .getDisplayName().equals("")) ? endnode.getName() : endnode * .getDisplayName(); if (endnode.getEnteringTransitions().size() == 0) * { return errHead + "end node[" + theName + * "] must have entering transition."; } } * * List<TransitionImpl> transitions = this.getTransitions(); for (int i * = 0; i < transitions.size(); i++) { TransitionImpl transition = * transitions.get(i); String theName = (transition.getDisplayName() == * null || transition .getDisplayName().equals("")) ? * transition.getName() : transition.getDisplayName(); if * (transition.getFromNode() == null) { return errHead + "transition[" + * theName + "] must have from node."; * * } if (transition.getToNode() == null) { return errHead + * "transition[" + theName + "] must have to node."; } } * * // check datafield List<DataField> dataFieldList = * this.getDataFields(); for (int i = 0; i < dataFieldList.size(); i++) * { DataField df = dataFieldList.get(i); if (df.getDataType() == null) * { return errHead + "unknown data type of datafield[" + df.getId() + * "]"; } } */ return null; } /* (non-Javadoc) * @see org.fireflow.pdl.fpdl.process.SubProcess#getProperty(java.lang.String) */ public Property getProperty(String name) { if (StringUtils.isEmpty(name))return null; for (Property prop : properties){ if (name.equals(prop.getName())){ return prop; } } return null; } }