View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2012-7-9 上午11:25:26
4    */
5   package gboat2.serviceflow.service.impl;
6   
7   import gboat2.serviceflow.JBPMHelper;
8   import gboat2.serviceflow.business.IJbpmWorkFlowBusiness;
9   import gboat2.serviceflow.model.ProcessInfo;
10  import gboat2.serviceflow.service.IFlowFilter;
11  import gboat2.serviceflow.service.IServiceFlowService;
12  import gboat2.serviceflow.service.ServiceFlowException;
13  import gboat2.serviceflow.util.WorkflowUtil;
14  
15  import java.net.URL;
16  import java.util.Comparator;
17  import java.util.HashMap;
18  import java.util.Iterator;
19  import java.util.LinkedList;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.TreeMap;
23  
24  import org.apache.commons.lang3.StringUtils;
25  import org.drools.builder.KnowledgeBuilder;
26  import org.drools.builder.KnowledgeBuilderError;
27  import org.drools.builder.KnowledgeBuilderErrors;
28  import org.drools.builder.ResourceType;
29  import org.drools.definition.process.Connection;
30  import org.drools.definition.process.Node;
31  import org.drools.io.Resource;
32  import org.drools.io.ResourceFactoryService;
33  import org.jbpm.workflow.core.node.HumanTaskNode;
34  import org.jbpm.workflow.core.node.Join;
35  import org.jbpm.workflow.core.node.Split;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  import org.springframework.beans.factory.annotation.Autowired;
39  
40  /**
41   * 
42   * 业务流程服务接口
43   * @author lysming
44   * @since jdk1.6
45   * @date 2012-7-9
46   *  
47   */
48  public class ServiceFlowServiceImpl implements IServiceFlowService {
49  
50  	private Logger logger = LoggerFactory.getLogger(ServiceFlowServiceImpl.class);
51  
52  	@Autowired
53  	private IJbpmWorkFlowBusiness workflowService;
54  	
55  	private Map<String,URL> picturePaths = new HashMap<String,URL>();
56  	
57  	private Map<ProcessDefine,IFlowFilter> processes = new TreeMap<ProcessDefine,IFlowFilter>(new Comparator<ProcessDefine>(){
58  
59  		@Override
60  		public int compare(ProcessDefine o1, ProcessDefine o2) {
61  			if(o1.getPriority()!=o2.getPriority()){
62  				return o1.getPriority()-o2.getPriority();
63  			}else{
64  				return o1.getProcessId().compareTo(o2.getProcessId());
65  			}
66  		}});
67  
68  	/**
69  	 * {@inheritDoc}   
70  	 * @see gboat2.IServiceflowService.service.IWorkFlowService#completeTask(java.lang.String, java.lang.String, java.util.Map) 
71  	 */
72  	@Override
73  	public void completeTask(String businessObjectId, String nodeName, Map<String, Object> params) {
74  		logger.debug("complete task " + nodeName + " : " + businessObjectId);
75  		//流程匹配
76  		String processId = getDealProcessId(businessObjectId, nodeName, params);
77  		if(StringUtils.isEmpty(processId)){
78  			throw new ServiceFlowException("Can't find process for "+nodeName);
79  		}
80  		//设置流程退出节点状态
81  		WorkflowUtil.onExitAction(processId, businessObjectId, nodeName, params);
82  		
83  		Node node = workflowService.getNode(nodeName, processId);
84  		Node to;
85  		String toType;
86  		if(node!=null){
87  			Map<String,List<Connection>> outs = node.getOutgoingConnections();
88  			List<Connection> conns;
89  			for(String out : outs.keySet()){
90  				conns = outs.get(out);
91  				for(Connection conn : conns){
92  					toType = conn.getToType();
93  					to = conn.getTo();
94  					if (to instanceof HumanTaskNode) {
95  						HumanTaskNode task = (HumanTaskNode) to;
96  						String taskNameOfNode = (String) task.getWork().getParameter("TaskName");
97  						logger.debug("Next : ["+toType+"] - "+to.getName()+" - "+taskNameOfNode);
98  						//设置流程进入节点状态
99  						WorkflowUtil.onEntryAction(processId, businessObjectId, taskNameOfNode, params);
100 					}else if(to instanceof Split){
101 						List<Node> nodes = getNextTaskNode((Split)to);
102 						for(Node nd : nodes){
103 							HumanTaskNode task = (HumanTaskNode) nd;
104 							String taskNameOfNode = (String) task.getWork().getParameter("TaskName");
105 							logger.debug("Next : ["+toType+"] - "+to.getName()+" - "+taskNameOfNode);
106 							WorkflowUtil.onEntryAction(processId, businessObjectId, taskNameOfNode, params);
107 						}
108 					}else if(to instanceof Join){
109 						List<Node> nodes = getNextTaskNode((Join)to);
110 						for(Node nd : nodes){
111 							HumanTaskNode task = (HumanTaskNode) nd;
112 							String taskNameOfNode = (String) task.getWork().getParameter("TaskName");
113 							logger.debug("Next : ["+toType+"] - "+to.getName()+" - "+taskNameOfNode);
114 							WorkflowUtil.onEntryAction(processId, businessObjectId, taskNameOfNode, params);
115 						}
116 					}
117 				}
118 			}
119 		}
120 	}
121 	
122 	private String getDealProcessId(String objectId, String nodeName, Map<String, Object> params) {
123 		for(ProcessDefine pd:processes.keySet()){
124 			if(workflowService.includeNode(nodeName, pd.getProcessId())&&processes.get(pd).accept(objectId, nodeName, params)){
125 				return pd.getProcessId();
126 			}
127 		}
128 		
129 		return null;
130 	}
131 	
132 	private List<Node> getNextTaskNode(Split split){
133 		List<Node> nodes = new LinkedList<Node>();
134 		Map<String,List<Connection>> outs = split.getOutgoingConnections();
135 		List<Connection> conns;
136 		Node to;
137 		for(String out : outs.keySet()){
138 			conns = outs.get(out);
139 			for(Connection conn : conns){
140 				to = conn.getTo();
141 				if (to instanceof HumanTaskNode) {
142 					nodes.add(to);
143 				}else if(to instanceof Split){
144 					nodes.addAll(getNextTaskNode((Split)to));
145 				}else if(to instanceof Join){
146 					nodes.addAll(getNextTaskNode((Join)to));
147 				}
148 			}
149 		}
150 		
151 		return nodes;
152 	}
153 	
154 	private List<Node> getNextTaskNode(Join join){
155 		List<Node> nodes = new LinkedList<Node>();
156 		Map<String,List<Connection>> outs = join.getOutgoingConnections();
157 		List<Connection> conns;
158 		Node to;
159 		for(String out : outs.keySet()){
160 			conns = outs.get(out);
161 			for(Connection conn : conns){
162 				to = conn.getTo();
163 				if (to instanceof HumanTaskNode) {
164 					nodes.add(to);
165 				}else if(to instanceof Split){
166 					nodes.addAll(getNextTaskNode((Split)to));
167 				}else if(to instanceof Join){
168 					nodes.addAll(getNextTaskNode((Join)to));
169 				}
170 			}
171 		}
172 		
173 		return nodes;
174 	}
175 
176 	/**
177 	 * {@inheritDoc}   
178 	 * @see gboat2.IServiceflowService.service.IWorkFlowService#registProcess(java.net.URL) 
179 	 */
180 	@Override
181 	public synchronized void registProcess(IFlowFilter filter, String processId, URL processDefine) {
182 		registProcess(0, filter, processId, processDefine);
183 	}
184 	
185 	@Override
186 	public synchronized void registProcess(int priority,IFlowFilter filter, String processId, URL processDefine) {
187 		KnowledgeBuilder kbuilder = JBPMHelper.getKnowledgeBuilder();
188 		ResourceFactoryService resourceFactoryService = (ResourceFactoryService) JBPMHelper.getServiceRegistry().get(ResourceFactoryService.class);
189 		Resource resource = resourceFactoryService.newUrlResource(processDefine);
190 		kbuilder.add(resource, ResourceType.BPMN2);
191 		if (kbuilder.hasErrors()) {
192 			StringBuilder errorMessages = new StringBuilder("failed to add process define " + processDefine.getPath() + ". the errors like below :\n");
193 			KnowledgeBuilderErrors errors = kbuilder.getErrors();
194 			for (Iterator<KnowledgeBuilderError> it = errors.iterator(); it.hasNext();) {
195 				errorMessages.append(it.next().toString()).append("\n");
196 			}
197 			logger.error(errorMessages.toString());
198 			throw new ServiceFlowException(errorMessages.toString());
199 		} else {
200 			processes.put(new ProcessDefine(priority,processId),filter);
201 			JBPMHelper.getKnowledgeBase().addKnowledgePackages(kbuilder.getKnowledgePackages());
202 		}
203 	}
204 	
205 	@Override
206 	public synchronized void registProcess(IFlowFilter filter, String processId, URL processDefine, URL picturePath) {
207 		registProcess(0, filter, processId, processDefine, picturePath);
208 	}
209 	
210 	@Override
211 	public synchronized void registProcess(int priority,IFlowFilter filter, String processId, URL processDefine, URL picturePath) {
212 		KnowledgeBuilder kbuilder = JBPMHelper.getKnowledgeBuilder();
213 		ResourceFactoryService resourceFactoryService = (ResourceFactoryService) JBPMHelper.getServiceRegistry().get(ResourceFactoryService.class);
214 		Resource resource = resourceFactoryService.newUrlResource(processDefine);
215 		kbuilder.add(resource, ResourceType.BPMN2);
216 		if (kbuilder.hasErrors()) {
217 			StringBuilder errorMessages = new StringBuilder("failed to add process define " + processDefine.getPath() + ". the errors like below :\n");
218 			KnowledgeBuilderErrors errors = kbuilder.getErrors();
219 			for (Iterator<KnowledgeBuilderError> it = errors.iterator(); it.hasNext();) {
220 				errorMessages.append(it.next().toString()).append("\n");
221 			}
222 			logger.error(errorMessages.toString());
223 			throw new ServiceFlowException(errorMessages.toString());
224 		} else {
225 			processes.put(new ProcessDefine(priority,processId),filter);
226 			JBPMHelper.getKnowledgeBase().addKnowledgePackages(kbuilder.getKnowledgePackages());
227 			picturePaths.put(processId, picturePath);
228 		}
229 	}
230 	
231 	@Override
232 	public List<ProcessInfo> getProcessInfos() {
233 		List<ProcessInfo> processInfoList = workflowService.getProcessInfos();
234 		return processInfoList;
235 	}
236 
237 	@Override
238 	public ProcessInfo getProcessInfo(String processId) {
239 		ProcessInfo processInfo = workflowService.getProcessInfo(processId);
240 		return processInfo;
241 	}
242 
243 	@Override
244 	public String getProcessIdForStepName(String stepName) {
245 		for(ProcessDefine pd:processes.keySet()){
246 			if(workflowService.includeNode(stepName, pd.getProcessId())){
247 				return pd.getProcessId();
248 			}
249 		}
250 		return null;
251 	}
252 
253 	@Override
254 	public boolean hasContainsStepName(String processId, String stepName) {
255 		return workflowService.includeNode(stepName, processId);
256 	}
257 	
258 	@Override
259 	public String getPathForDisplay(String processId) {
260 		if(picturePaths.containsKey(processId)){
261 			URL url = picturePaths.get(processId);
262 			String path = url.getPath();
263 			return path.substring(path.indexOf("/static"));
264 		}
265 		return null;
266 	}
267 }