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