1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.engine.node;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.exception.RiceRuntimeException;
21 import org.kuali.rice.kew.doctype.bo.DocumentType;
22 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
23 import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.Element;
26 import org.w3c.dom.NodeList;
27 import org.xml.sax.InputSource;
28
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.DocumentBuilderFactory;
31 import javax.xml.xpath.XPathConstants;
32 import java.io.StringReader;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41
42
43
44
45
46
47
48
49 public final class RouteNodeUtils {
50
51 private RouteNodeUtils() {
52 throw new UnsupportedOperationException("do not call");
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public static String getValueOfCustomProperty(RouteNode routeNode, String propertyName) {
75 String contentFragment = routeNode.getContentFragment();
76 String elementValue = null;
77 if (!StringUtils.isBlank(contentFragment)) {
78 try {
79 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
80 Document document = db.parse(new InputSource(new StringReader(contentFragment)));
81 elementValue = XPathHelper.newXPath().evaluate("//" + propertyName, document);
82 } catch (Exception e) {
83 throw new RiceRuntimeException("Error when attempting to parse Route Node content fragment for property name: " + propertyName, e);
84 }
85 }
86 return elementValue;
87 }
88
89 public static List<Element> getCustomRouteNodeElements(RouteNode routeNode, String elementName) {
90 String contentFragment = routeNode.getContentFragment();
91 List<Element> elements = new ArrayList<Element>();
92 NodeList nodeList = null;
93 if (!StringUtils.isBlank(contentFragment)) {
94 try {
95 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
96 Document document = db.parse(new InputSource(new StringReader(contentFragment)));
97 nodeList = (NodeList)XPathHelper.newXPath().evaluate("//" + elementName, document, XPathConstants.NODESET);
98 } catch (Exception e) {
99 throw new RiceRuntimeException("Error when attempting to parse Route Node content fragment for element name: " + elementName, e);
100 }
101 }
102 for (int index = 0; index < nodeList.getLength(); index++) {
103 Element element = (Element)nodeList.item(index);
104 elements.add(element);
105 }
106 return elements;
107 }
108
109 public static Element getCustomRouteNodeElement(RouteNode routeNode, String elementName) {
110 List<Element> elements = getCustomRouteNodeElements(routeNode, elementName);
111 if (CollectionUtils.isEmpty(elements)) {
112 return null;
113 } else if (elements.size() > 1) {
114 throw new RiceRuntimeException("More than one element found with the given name: " + elementName);
115 }
116 return elements.get(0);
117 }
118
119 public static List<RouteNodeInstance> getFlattenedNodeInstances(DocumentRouteHeaderValue document, boolean includeProcesses) {
120 List<RouteNodeInstance> nodeInstances = new ArrayList<RouteNodeInstance>();
121 Set<String> visitedNodeInstanceIds = new HashSet<String>();
122 for (RouteNodeInstance initialNodeInstance : document.getInitialRouteNodeInstances())
123 {
124 flattenNodeInstanceGraph(nodeInstances, visitedNodeInstanceIds, initialNodeInstance, includeProcesses);
125 }
126 return nodeInstances;
127 }
128
129 private static void flattenNodeInstanceGraph(List<RouteNodeInstance> nodeInstances, Set<String> visitedNodeInstanceIds, RouteNodeInstance nodeInstance, boolean includeProcesses) {
130 if (visitedNodeInstanceIds.contains(nodeInstance.getRouteNodeInstanceId())) {
131 return;
132 }
133 if (includeProcesses && nodeInstance.getProcess() != null) {
134 flattenNodeInstanceGraph(nodeInstances, visitedNodeInstanceIds, nodeInstance.getProcess(), includeProcesses);
135 }
136 visitedNodeInstanceIds.add(nodeInstance.getRouteNodeInstanceId());
137 nodeInstances.add(nodeInstance);
138 for (RouteNodeInstance nextNodeInstance : nodeInstance.getNextNodeInstances())
139 {
140 flattenNodeInstanceGraph(nodeInstances, visitedNodeInstanceIds, nextNodeInstance, includeProcesses);
141 }
142 }
143
144 public static List<RouteNode> getFlattenedNodes(DocumentType documentType, boolean climbHierarchy) {
145 List<RouteNode> nodes = new ArrayList<RouteNode>();
146 if (!documentType.isRouteInherited() || climbHierarchy) {
147 for (Object o : documentType.getProcesses())
148 {
149 ProcessDefinitionBo process = (ProcessDefinitionBo) o;
150 nodes.addAll(getFlattenedNodes(process));
151 }
152 }
153 Collections.sort(nodes, new RouteNodeSorter());
154 return nodes;
155 }
156
157 public static List<RouteNode> getFlattenedNodes(ProcessDefinitionBo process) {
158 Map<String, RouteNode> nodesMap = new HashMap<String, RouteNode>();
159 if (process.getInitialRouteNode() != null) {
160 flattenNodeGraph(nodesMap, process.getInitialRouteNode());
161 List<RouteNode> nodes = new ArrayList<RouteNode>(nodesMap.values());
162 Collections.sort(nodes, new RouteNodeSorter());
163 return nodes;
164 } else {
165 List<RouteNode> nodes = new ArrayList<RouteNode>();
166 nodes.add(new RouteNode());
167 return nodes;
168 }
169
170 }
171
172
173
174
175
176
177
178 private static void flattenNodeGraph(Map<String, RouteNode> nodes, RouteNode node) {
179 if (node != null) {
180 if (nodes.containsKey(node.getRouteNodeName())) {
181 return;
182 }
183 nodes.put(node.getRouteNodeName(), node);
184 for (RouteNode nextNode : node.getNextNodes())
185 {
186 flattenNodeGraph(nodes, nextNode);
187 }
188 } else {
189 return;
190 }
191 }
192
193
194
195
196
197
198
199 private static class RouteNodeSorter implements Comparator {
200 public int compare(Object arg0, Object arg1) {
201 RouteNode rn1 = (RouteNode)arg0;
202 RouteNode rn2 = (RouteNode)arg1;
203 return rn1.getRouteNodeId().compareTo(rn2.getRouteNodeId());
204 }
205 }
206
207 public static List<RouteNodeInstance> getActiveNodeInstances(DocumentRouteHeaderValue document) {
208 List<RouteNodeInstance> flattenedNodeInstances = getFlattenedNodeInstances(document, true);
209 List<RouteNodeInstance> activeNodeInstances = new ArrayList<RouteNodeInstance>();
210 for (RouteNodeInstance nodeInstance : flattenedNodeInstances)
211 {
212 if (nodeInstance.isActive())
213 {
214 activeNodeInstances.add(nodeInstance);
215 }
216 }
217 return activeNodeInstances;
218 }
219
220 public static RouteNodeInstance findRouteNodeInstanceById(String nodeInstanceId, DocumentRouteHeaderValue document) {
221 List<RouteNodeInstance> flattenedNodeInstances = getFlattenedNodeInstances(document, true);
222 RouteNodeInstance niRet = null;
223 for (RouteNodeInstance nodeInstance : flattenedNodeInstances)
224 {
225 if (nodeInstanceId.equals(nodeInstance.getRouteNodeInstanceId()))
226 {
227 niRet = nodeInstance;
228 break;
229 }
230 }
231 return niRet;
232 }
233
234
235
236 }