1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.edl.impl.components;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.rice.core.api.util.RiceConstants;
21 import org.kuali.rice.core.api.util.xml.XmlJotter;
22 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
23 import org.kuali.rice.edl.impl.EDLContext;
24 import org.kuali.rice.edl.impl.EDLModelComponent;
25 import org.kuali.rice.edl.impl.EDLXmlUtils;
26 import org.kuali.rice.edl.impl.RequestParser;
27 import org.kuali.rice.edl.impl.UserAction;
28 import org.kuali.rice.edl.impl.service.EdlServiceLocator;
29 import org.kuali.rice.kew.api.KewApiServiceLocator;
30 import org.kuali.rice.kew.api.WorkflowDocument;
31 import org.kuali.rice.kew.api.WorkflowRuntimeException;
32 import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
33 import org.kuali.rice.kew.api.exception.WorkflowException;
34 import org.kuali.rice.kew.api.KewApiConstants;
35 import org.kuali.rice.krad.util.KRADConstants;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38
39 import javax.xml.xpath.XPath;
40 import javax.xml.xpath.XPathConstants;
41 import javax.xml.xpath.XPathExpressionException;
42 import javax.xml.xpath.XPathFactory;
43 import java.util.ArrayList;
44 import java.util.Date;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Map;
48
49
50
51
52
53
54
55
56 public class WorkflowDocumentState implements EDLModelComponent {
57
58 private static final Logger LOG = Logger.getLogger(WorkflowDocumentState.class);
59
60
61 private enum buttons{ACKNOWLEDGE, BLANKETAPPROVE, ROUTE, SAVE, COMPLETE, APPROVE, DISAPPROVE,
62 RETURNTOPREVIOUS, FYI, CANCEL};
63
64 public void updateDOM(Document dom, Element configElement, EDLContext edlContext) {
65
66 try {
67 Element documentState = EDLXmlUtils.getDocumentStateElement(dom);
68
69 Element dateTime = EDLXmlUtils.getOrCreateChildElement(documentState, "dateTime", true);
70 dateTime.appendChild(dom.createTextNode(RiceConstants.getDefaultDateAndTimeFormat().format(new Date())));
71
72 Element definition = EDLXmlUtils.getOrCreateChildElement(documentState, "definition", true);
73 definition.appendChild(dom.createTextNode(edlContext.getEdocLiteAssociation().getDefinition()));
74
75 Element docType = EDLXmlUtils.getOrCreateChildElement(documentState, "docType", true);
76 docType.appendChild(dom.createTextNode(edlContext.getEdocLiteAssociation().getEdlName()));
77
78 Element style = EDLXmlUtils.getOrCreateChildElement(documentState, "style", true);
79 String styleName = edlContext.getEdocLiteAssociation().getStyle();
80 if (styleName == null) {
81 styleName = "Default";
82 }
83 style.appendChild(dom.createTextNode(styleName));
84
85 Element showAttachments = EDLXmlUtils.getOrCreateChildElement(documentState, "showAttachments", true);
86 boolean showConstants = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(KewApiConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.ALL_DETAIL_TYPE, KewApiConstants.SHOW_ATTACHMENTS_IND);
87
88 showAttachments.appendChild(dom.createTextNode(Boolean.valueOf(showConstants).toString()));
89
90 WorkflowDocument document = (WorkflowDocument)edlContext.getRequestParser().getAttribute(RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY);
91
92 boolean documentEditable = false;
93 if (document != null) {
94 List<String> validActions = determineValidActions(document);
95
96 documentEditable = isEditable(edlContext, validActions);
97
98 edlContext.getTransformer().setParameter("readOnly", String.valueOf(documentEditable));
99 addActions(dom, documentState, validActions);
100 boolean isAnnotatable = isAnnotatable(validActions);
101 EDLXmlUtils.createTextElementOnParent(documentState, "annotatable", String.valueOf(isAnnotatable));
102 EDLXmlUtils.createTextElementOnParent(documentState, "docId", document.getDocumentId());
103 Element workflowDocumentStatus = EDLXmlUtils.getOrCreateChildElement(documentState, "workflowDocumentState", true);
104 EDLXmlUtils.createTextElementOnParent(workflowDocumentStatus, "status", document.getStatus().getLabel());
105 EDLXmlUtils.createTextElementOnParent(workflowDocumentStatus, "createDate", RiceConstants.getDefaultDateAndTimeFormat().format(document.getDateCreated().toDate()));
106 List<String> nodeNames = document.getPreviousNodeNames();
107 if (nodeNames.size() > 0) {
108 Element previousNodes = EDLXmlUtils.getOrCreateChildElement(documentState, "previousNodes", true);
109
110 for (int i = 0; i < nodeNames.size(); i++) {
111 EDLXmlUtils.createTextElementOnParent(previousNodes, "node", nodeNames.get(i));
112 }
113 }
114 List<RouteNodeInstance> routeNodeInstances = KewApiServiceLocator.getWorkflowDocumentService().getCurrentRouteNodeInstances(
115 document.getDocumentId());
116
117 for (RouteNodeInstance currentNode : routeNodeInstances) {
118 EDLXmlUtils.createTextElementOnParent(documentState, "currentNodeName", currentNode.getName());
119 }
120
121 }
122
123 Element editable = EDLXmlUtils.getOrCreateChildElement(documentState, "editable", true);
124 editable.appendChild(dom.createTextNode(String.valueOf(documentEditable)));
125
126
127 EDLXmlUtils.createTextElementOnParent(documentState, "actionable", "true");
128
129 List globalErrors = (List)edlContext.getRequestParser().getAttribute(RequestParser.GLOBAL_ERRORS_KEY);
130 List globalMessages = (List)edlContext.getRequestParser().getAttribute(RequestParser.GLOBAL_MESSAGES_KEY);
131 Map<String, String> globalFieldErrors = (Map)edlContext.getRequestParser().getAttribute(RequestParser.GLOBAL_FIELD_ERRORS_KEY);
132 EDLXmlUtils.addErrorsAndMessagesToDocument(dom, globalErrors, globalMessages, globalFieldErrors);
133 if (LOG.isDebugEnabled()) {
134 LOG.debug("Transforming dom " + XmlJotter.jotNode(dom, true));
135 }
136 } catch (Exception e) {
137 throw new WorkflowRuntimeException(e);
138 }
139 }
140
141 public static List<String> determineValidActions(WorkflowDocument wfdoc) throws WorkflowException {
142 String[] flags = new String[10];
143 List<String> list = new ArrayList<String>();
144
145 if (wfdoc == null) {
146 list.add(UserAction.ACTION_CREATE);
147 return list;
148 }
149
150 if (wfdoc.isAcknowledgeRequested()) {
151 flags[buttons.ACKNOWLEDGE.ordinal()] = UserAction.ACTION_ACKNOWLEDGE;
152 }
153
154 if (wfdoc.isApprovalRequested()) {
155 if (wfdoc.isBlanketApproveCapable()) {
156 flags[buttons.BLANKETAPPROVE.ordinal()] = UserAction.ACTION_BLANKETAPPROVE;
157 }
158 if (!wfdoc.isSaved()) {
159 flags[buttons.APPROVE.ordinal()] = UserAction.ACTION_APPROVE;
160 flags[buttons.DISAPPROVE.ordinal()] = UserAction.ACTION_DISAPPROVE;
161 }
162
163
164 flags[buttons.SAVE.ordinal()] = UserAction.ACTION_SAVE;
165 if (wfdoc.getPreviousNodeNames().size() > 0) {
166 flags[buttons.RETURNTOPREVIOUS.ordinal()] = UserAction.ACTION_RETURN_TO_PREVIOUS;
167 }
168 }
169
170
171
172 else if (wfdoc.isCompletionRequested()) {
173 flags[buttons.COMPLETE.ordinal()] = UserAction.ACTION_COMPLETE;
174 if (wfdoc.isBlanketApproveCapable()) {
175 flags[buttons.BLANKETAPPROVE.ordinal()] = UserAction.ACTION_BLANKETAPPROVE;
176 }
177 }
178
179 if (wfdoc.isFYIRequested()) {
180 flags[buttons.FYI.ordinal()] = UserAction.ACTION_FYI;
181 }
182
183 if (wfdoc.isRouteCapable()) {
184 flags[buttons.ROUTE.ordinal()] = UserAction.ACTION_ROUTE;
185 if (wfdoc.isBlanketApproveCapable()) {
186 flags[buttons.BLANKETAPPROVE.ordinal()] = UserAction.ACTION_BLANKETAPPROVE;
187 }
188 }
189
190 if (wfdoc.isApprovalRequested() || wfdoc.isRouteCapable()) {
191 flags[buttons.SAVE.ordinal()] = UserAction.ACTION_SAVE;
192 }
193
194 if (wfdoc.isCompletionRequested() || wfdoc.isRouteCapable()) {
195 flags[buttons.CANCEL.ordinal()] = UserAction.ACTION_CANCEL;
196 }
197
198 for (int i = 0; i < flags.length; i++) {
199 if (flags[i] != null) {
200 list.add(flags[i]);
201 }
202 }
203
204 return list;
205 }
206
207 public static boolean isEditable(EDLContext edlContext, List actions) {
208 boolean editable = false;
209 editable = listContainsItems(actions, UserAction.EDITABLE_ACTIONS);
210
211 Document edlDom = EdlServiceLocator.getEDocLiteService().getDefinitionXml(edlContext.getEdocLiteAssociation());
212
213 XPath xpath = XPathFactory.newInstance().newXPath();
214 String xpathExpression = "//config/param[@name='alwaysEditable']";
215 try {
216 String match = (String) xpath.evaluate(xpathExpression, edlDom, XPathConstants.STRING);
217 if (!StringUtils.isBlank(match) && match.equals("true")) {
218 return true;
219 }
220 } catch (XPathExpressionException e) {
221 throw new WorkflowRuntimeException("Unable to evaluate xpath expression " + xpathExpression, e);
222 }
223
224 return editable;
225 }
226
227
228 public static void addActions(Document dom, Element documentState, List actions) {
229 Element actionsPossible = EDLXmlUtils.getOrCreateChildElement(documentState, "actionsPossible", true);
230 Iterator it = actions.iterator();
231 while (it.hasNext()) {
232 String action = it.next().toString();
233 Element actionElement = dom.createElement(action);
234
235
236 if (!Character.isUpperCase(action.charAt(0))) {
237 StringBuffer sb = new StringBuffer(action);
238 sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
239 action = sb.toString();
240 }
241 actionElement.setAttribute("title", action);
242 actionsPossible.appendChild(actionElement);
243 }
244
245 Element annotatable = EDLXmlUtils.getOrCreateChildElement(documentState, "annotatable", true);
246 annotatable.appendChild(dom.createTextNode(String.valueOf(isAnnotatable(actions))));
247 }
248
249
250
251
252 public static boolean listContainsItems(List list, Object[] items) {
253 for (int i = 0; i < items.length; i++) {
254 if (list.contains(items[i])) return true;
255 }
256 return false;
257 }
258
259
260
261
262
263
264
265
266
267
268 public static boolean isAnnotatable(List actions) {
269 return listContainsItems(actions, UserAction.ANNOTATABLE_ACTIONS);
270 }
271
272 }