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