1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.engine.node.hierarchyrouting;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.apache.commons.collections.CollectionUtils;
24 import org.apache.commons.collections.Transformer;
25 import org.apache.commons.lang.ObjectUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang.builder.ToStringBuilder;
28 import org.apache.log4j.Logger;
29 import org.kuali.rice.kew.engine.RouteContext;
30 import org.kuali.rice.kew.engine.node.NodeState;
31 import org.kuali.rice.kew.engine.node.RouteNode;
32 import org.kuali.rice.kew.engine.node.RouteNodeConfigParam;
33 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
34 import org.kuali.rice.kew.engine.node.hierarchyrouting.HierarchyProvider;
35 import org.kuali.rice.kew.rule.NamedRuleSelector;
36 import org.kuali.rice.kew.util.Utilities;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.NodeList;
39
40
41
42
43
44
45
46
47
48
49
50
51 public class SimpleHierarchyProvider implements HierarchyProvider {
52 private static final Logger LOG = Logger.getLogger(SimpleHierarchyProvider.class);
53
54
55
56
57
58
59 static class SimpleStop implements Stop {
60 private static enum RecipientType { USER, WORKGROUP };
61 public SimpleStop parent;
62 public List<SimpleStop> children = new ArrayList<SimpleStop>();
63 public RecipientType type;
64 public String recipient;
65 public String id;
66
67 public String toString() {
68 return new ToStringBuilder(this).append("id", id)
69 .append("recipient", recipient)
70 .append("type", type)
71 .append("parent", parent == null ? null : parent.id)
72 .append("children", StringUtils.join(CollectionUtils.collect(children, new Transformer() {
73 public Object transform(Object o) { return ((SimpleStop) o).id; }
74 })
75 , ','))
76 .toString();
77
78 }
79
80 public boolean equals(Object o) {
81 if (!(o instanceof SimpleStop)) return false;
82 return id.equals(((SimpleStop) o).id);
83 }
84
85 public int hashCode() {
86 return ObjectUtils.hashCode(id);
87 }
88 }
89
90
91
92
93 private SimpleStop root;
94
95
96
97 private Map<String, SimpleStop> stops = new HashMap<String, SimpleStop>();
98
99 public void init(RouteNodeInstance nodeInstance, RouteContext context) {
100 init(context.getDocumentContent().getDocument().getDocumentElement());
101 }
102
103
104
105
106
107 public void init(Element element) {
108 Element rootStop = findRootStop(element);
109 root = parseStops(rootStop, null);
110 }
111
112
113
114
115
116
117 protected Element findRootStop(Element e) {
118 if ("stop".equals(e.getNodeName())) return e;
119 NodeList nl = e.getElementsByTagName("stop");
120 if (nl == null || nl.getLength() == 0) {
121 throw new RuntimeException("No stops found");
122 }
123 return (Element) nl.item(0);
124 }
125
126
127
128
129
130
131
132 protected SimpleStop parseStops(Element e, SimpleStop parent) {
133 LOG.debug("parsing element: " + e + " parent: " + parent);
134 SimpleStop stop = parseStop(e);
135 LOG.debug("parsed stop: "+ stop);
136 stop.parent = parent;
137 if (parent != null) {
138 parent.children.add(stop);
139 }
140 stops.put(e.getAttribute("id"), stop);
141 NodeList nl = e.getChildNodes();
142 for (int i = 0; i < nl.getLength(); i++) {
143 org.w3c.dom.Node n = nl.item(i);
144 if (!(n instanceof Element)) continue;
145 parseStops((Element) n, stop);
146 }
147 return stop;
148 }
149
150
151
152
153
154
155 protected SimpleStop parseStop(Element e) {
156 SimpleStop ss = new SimpleStop();
157 String recipient = e.getAttribute("recipient");
158 String type = e.getAttribute("type");
159 String id = e.getAttribute("id");
160 if (id == null) {
161 throw new RuntimeException("malformed document content, missing id attribute: " + e);
162 }
163
164
165
166
167
168
169
170
171
172 ss.id = id;
173 ss.recipient = recipient;
174
175 if (!StringUtils.isEmpty(type)) {
176 SimpleStop.RecipientType rtype = SimpleStop.RecipientType.valueOf(type.toUpperCase());
177 ss.type = rtype;
178 }
179
180 return ss;
181 }
182
183
184 public List<Stop> getLeafStops(RouteContext context) {
185 List<Stop> leafStops = new ArrayList<Stop>();
186 for (SimpleStop stop: stops.values()) {
187 if (stop.children.size() == 0) {
188 leafStops.add(stop);
189 }
190 }
191 return leafStops;
192 }
193
194
195 public Stop getStopByIdentifier(String stopId) {
196 return stops.get(stopId);
197 }
198
199
200 public String getStopIdentifier(Stop stop) {
201 return ((SimpleStop) stop).id;
202 }
203
204 public boolean hasStop(RouteNodeInstance nodeInstance) {
205 return nodeInstance.getNodeState("id") != null;
206 }
207
208 public void setStop(RouteNodeInstance requestNodeInstance, Stop stop) {
209 SimpleStop ss = (SimpleStop) stop;
210 requestNodeInstance.addNodeState(new NodeState("id", getStopIdentifier(stop)));
211
212
213 if (ss.recipient != null) {
214 requestNodeInstance.addNodeState(new NodeState("recipient", ((SimpleStop) stop).recipient));
215 }
216 if (ss.type != null) {
217 requestNodeInstance.addNodeState(new NodeState("type", ((SimpleStop) stop).type.name().toLowerCase()));
218 }
219 }
220
221 public boolean equals(Stop a, Stop b) {
222 return ObjectUtils.equals(a, b);
223 }
224
225 public Stop getParent(Stop stop) {
226 return ((SimpleStop) stop).parent;
227 }
228
229 public boolean isRoot(Stop stop) {
230 return equals(stop, root);
231 }
232
233 public Stop getStop(RouteNodeInstance nodeInstance) {
234 NodeState state = nodeInstance.getNodeState("id");
235 if (state == null) {
236
237 throw new RuntimeException();
238 } else {
239 LOG.warn("id Node state on nodeinstance " + nodeInstance + ": " + state);
240 return stops.get(state.getValue());
241 }
242 }
243
244
245 public void configureRequestNode(RouteNodeInstance hierarchyNodeInstance, RouteNode node) {
246 Map<String, String> cfgMap = Utilities.getKeyValueCollectionAsMap(node.getConfigParams());
247
248 if (!cfgMap.containsKey(RouteNode.RULE_SELECTOR_CFG_KEY)) {
249 Map<String, String> hierarchyCfgMap = Utilities.getKeyValueCollectionAsMap(hierarchyNodeInstance.getRouteNode().getConfigParams());
250 node.getConfigParams().add(new RouteNodeConfigParam(node, RouteNode.RULE_SELECTOR_CFG_KEY, hierarchyCfgMap.get(RouteNode.RULE_SELECTOR_CFG_KEY)));
251 }
252 if (!cfgMap.containsKey(NamedRuleSelector.RULE_NAME_CFG_KEY)) {
253 Map<String, String> hierarchyCfgMap = Utilities.getKeyValueCollectionAsMap(hierarchyNodeInstance.getRouteNode().getConfigParams());
254 node.getConfigParams().add(new RouteNodeConfigParam(node, NamedRuleSelector.RULE_NAME_CFG_KEY, hierarchyCfgMap.get(NamedRuleSelector.RULE_NAME_CFG_KEY)));
255 }
256 }
257 }