1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.rice.kew.engine;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
23 import org.kuali.rice.kew.doctype.bo.DocumentType;
24 import org.kuali.rice.kew.engine.node.Process;
25 import org.kuali.rice.kew.engine.node.RouteNode;
26 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
27 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
28 import org.kuali.rice.kew.util.KEWConstants;
29
30
31
32
33
34
35
36
37
38
39 public class CompatUtils {
40
41 private static RouteHelper helper = new RouteHelper();
42
43 public static Integer getLevelForNode(DocumentType documentType, String nodeName) {
44 if (isRouteLevelCompatible(documentType)) {
45 return getLevelForNode(documentType.getPrimaryProcess().getInitialRouteNode(), nodeName, new Integer(0));
46 }
47 return new Integer(KEWConstants.INVALID_ROUTE_LEVEL);
48 }
49
50 private static Integer getLevelForNode(RouteNode node, String nodeName, Integer currentLevel) {
51
52
53 if (node.getRouteNodeName().equals(nodeName)) {
54 return currentLevel;
55 }
56 List nextNodes = node.getNextNodes();
57 if (nextNodes.isEmpty()) {
58 throw new WorkflowRuntimeException("Could not locate node with name '"+nodeName+"'");
59 }
60 if (nextNodes.size() > 1) {
61 throw new WorkflowRuntimeException("Can only determine route level for document types with no splitting");
62 }
63 RouteNode nextNode = (RouteNode)nextNodes.get(0);
64 return getLevelForNode(nextNode, nodeName, new Integer(currentLevel.intValue()+1));
65 }
66
67
68
69
70
71
72 public static RouteNode getNodeForLevel(DocumentType documentType, Integer routeLevel) {
73 Object[] node = getNodeForLevel(documentType.getPrimaryProcess().getInitialRouteNode(), routeLevel, new Integer(0));
74 return (RouteNode)node[0];
75 }
76
77 private static Object[] getNodeForLevel(RouteNode node, Integer routeLevel, Integer currentLevel) {
78 if (helper.isSubProcessNode(node)) {
79 Object[] result = getNodeForLevel(node.getDocumentType().getNamedProcess(node.getRouteNodeName()).getInitialRouteNode(), routeLevel, currentLevel);
80 if (result[0] != null) {
81 node = (RouteNode)result[0];
82 }
83 currentLevel = (Integer)result[1];
84 }
85 if (currentLevel.equals(routeLevel)) {
86 return new Object[] { node, currentLevel };
87 }
88 List nextNodes = node.getNextNodes();
89 if (nextNodes.isEmpty()) {
90 return new Object[] { null, currentLevel };
91 }
92 if (nextNodes.size() > 1) {
93 throw new WorkflowRuntimeException("Cannot determine a route level number for documents with splitting.");
94 }
95 currentLevel = new Integer(currentLevel.intValue()+1);
96 return getNodeForLevel((RouteNode)nextNodes.get(0), routeLevel, currentLevel);
97 }
98
99 public static boolean isRouteLevelCompatible(DocumentType documentType) {
100 return KEWConstants.ROUTING_VERSION_ROUTE_LEVEL.equals(documentType.getRoutingVersion());
101 }
102
103 public static boolean isRouteLevelCompatible(DocumentRouteHeaderValue document) {
104 return isRouteLevelCompatible(document.getDocumentType());
105 }
106
107 public static boolean isNodalDocument(DocumentRouteHeaderValue document) {
108 return KEWConstants.DOCUMENT_VERSION_NODAL == document.getDocVersion().intValue();
109 }
110
111 public static boolean isNodalRequest(ActionRequestValue request) {
112 return KEWConstants.DOCUMENT_VERSION_NODAL == request.getDocVersion().intValue();
113 }
114
115 public static boolean isRouteLevelDocument(DocumentRouteHeaderValue document) {
116 return KEWConstants.DOCUMENT_VERSION_ROUTE_LEVEL == document.getDocVersion().intValue();
117 }
118
119 public static boolean isRouteLevelRequest(ActionRequestValue request) {
120 return KEWConstants.DOCUMENT_VERSION_ROUTE_LEVEL == request.getDocVersion().intValue();
121 }
122
123
124
125
126
127 public static List getRouteLevelCompatibleNodeList(DocumentType documentType) {
128 if (!isRouteLevelCompatible(documentType)) {
129 throw new WorkflowRuntimeException("Attempting to invoke a 'route level' operation on a document which is not route level compatible.");
130 }
131 Process primaryProcess = documentType.getPrimaryProcess();
132 RouteNode routeNode = primaryProcess.getInitialRouteNode();
133 List nodes = new ArrayList();
134 int count = 0;
135 int maxCount = 100;
136 while (true) {
137 nodes.add(routeNode);
138 List nextNodes = routeNode.getNextNodes();
139 if (nextNodes.size() == 0) {
140 break;
141 }
142 if (nextNodes.size() > 1) {
143 throw new RuntimeException("Node has more than one next node! It is not route level compatible!" + routeNode.getRouteNodeName());
144 }
145 if (count >= maxCount) {
146 throw new RuntimeException("A runaway loop was detected when attempting to create route level compatible node graph. documentType=" + documentType.getDocumentTypeId()+","+documentType.getName());
147 }
148 routeNode = (RouteNode) nextNodes.iterator().next();
149 }
150 return nodes;
151 }
152
153 public static int getMaxRouteLevel(DocumentType documentType) {
154 return getRouteLevelCompatibleNodeList(documentType).size();
155 }
156 }