001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.edl.components;
018:
019: import java.util.ArrayList;
020: import java.util.Date;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.w3c.dom.Document;
025: import org.w3c.dom.Element;
026:
027: import edu.iu.uis.eden.EdenConstants;
028: import edu.iu.uis.eden.clientapp.WorkflowDocument;
029: import edu.iu.uis.eden.edl.EDLContext;
030: import edu.iu.uis.eden.edl.EDLModelComponent;
031: import edu.iu.uis.eden.edl.EDLXmlUtils;
032: import edu.iu.uis.eden.edl.RequestParser;
033: import edu.iu.uis.eden.exception.WorkflowException;
034: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
035: import edu.iu.uis.eden.util.Utilities;
036:
037: /**
038: * Generates document state based on the workflow document in session.
039: *
040: * @author rkirkend
041: * @author ahamid
042: *
043: */
044: public class WorkflowDocumentState implements EDLModelComponent {
045:
046: public void updateDOM(Document dom, Element configElement,
047: EDLContext edlContext) {
048:
049: try {
050: Element documentState = EDLXmlUtils
051: .getDocumentStateElement(dom);
052:
053: Element dateTime = EDLXmlUtils.getOrCreateChildElement(
054: documentState, "dateTime", true);
055: dateTime.appendChild(dom.createTextNode(EdenConstants
056: .getDefaultDateAndTimeFormat().format(new Date())));
057:
058: Element definition = EDLXmlUtils.getOrCreateChildElement(
059: documentState, "definition", true);
060: definition.appendChild(dom.createTextNode(edlContext
061: .getEdocLiteAssociation().getDefinition()));
062:
063: Element docType = EDLXmlUtils.getOrCreateChildElement(
064: documentState, "docType", true);
065: docType.appendChild(dom.createTextNode(edlContext
066: .getEdocLiteAssociation().getEdlName()));
067:
068: Element style = EDLXmlUtils.getOrCreateChildElement(
069: documentState, "style", true);
070: String styleName = edlContext.getEdocLiteAssociation()
071: .getStyle();
072: if (styleName == null) {
073: styleName = "Default";
074: }
075: style.appendChild(dom.createTextNode(styleName));
076:
077: Element showAttachments = EDLXmlUtils
078: .getOrCreateChildElement(documentState,
079: "showAttachments", true);
080: String showContants = Utilities
081: .getApplicationConstant(EdenConstants.APP_CONST_SHOW_ATTACHMENTS);
082: showAttachments.appendChild(dom.createTextNode(Boolean
083: .valueOf(showContants).toString()));
084:
085: WorkflowDocument document = (WorkflowDocument) edlContext
086: .getRequestParser()
087: .getAttribute(
088: RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY);
089:
090: boolean documentEditable = false;
091: if (document != null) {
092: List validActions = determineValidActions(document);
093: documentEditable = isEditable(validActions);
094: edlContext.getTransformer().setParameter("readOnly",
095: String.valueOf(documentEditable));
096: addActions(dom, documentState, validActions);
097: boolean isAnnotatable = isAnnotatable(validActions);
098: EDLXmlUtils.createTextElementOnParent(documentState,
099: "annotatable", String.valueOf(isAnnotatable));
100: EDLXmlUtils
101: .createTextElementOnParent(documentState,
102: "docId", document.getRouteHeaderId()
103: .toString());
104: Element workflowDocumentStatus = EDLXmlUtils
105: .getOrCreateChildElement(documentState,
106: "workflowDocumentState", true);
107: EDLXmlUtils.createTextElementOnParent(
108: workflowDocumentStatus, "status", document
109: .getStatusDisplayValue());
110: EDLXmlUtils.createTextElementOnParent(
111: workflowDocumentStatus, "createDate",
112: EdenConstants.getDefaultDateAndTimeFormat()
113: .format(document.getDateCreated()));
114: String[] nodeNames = document.getPreviousNodeNames();
115: if (nodeNames.length > 0) {
116: Element previousNodes = EDLXmlUtils
117: .getOrCreateChildElement(documentState,
118: "previousNodes", true);
119: // don't include LAST node (where the document is currently...don't want to return to current location)
120: for (int i = 0; i < nodeNames.length - 1; i++) {
121: EDLXmlUtils.createTextElementOnParent(
122: previousNodes, "node", nodeNames[i]);
123: }
124: }
125:
126: }
127:
128: Element editable = EDLXmlUtils.getOrCreateChildElement(
129: documentState, "editable", true);
130: editable.appendChild(dom.createTextNode(String
131: .valueOf(documentEditable)));
132:
133: // display the buttons
134: EDLXmlUtils.createTextElementOnParent(documentState,
135: "actionable", "true");
136:
137: List globalErrors = (List) edlContext.getRequestParser()
138: .getAttribute(RequestParser.GLOBAL_ERRORS_KEY);
139: List globalMessages = (List) edlContext.getRequestParser()
140: .getAttribute(RequestParser.GLOBAL_MESSAGES_KEY);
141: EDLXmlUtils.addErrorsAndMessagesToDocument(dom,
142: globalErrors, globalMessages);
143: } catch (Exception e) {
144: throw new WorkflowRuntimeException(e);
145: }
146: }
147:
148: public static List determineValidActions(WorkflowDocument wfdoc)
149: throws WorkflowException {
150: if (wfdoc == null) {
151: List l = new ArrayList();
152: l.add(WorkflowDocumentActions.ACTION_CREATE);
153: return l;
154: }
155: List list = new ArrayList();
156: if (wfdoc.isAcknowledgeRequested()) {
157: list.add(WorkflowDocumentActions.ACTION_ACKNOWLEDGE);
158: }
159: if (wfdoc.isApprovalRequested()) {
160: list.add(WorkflowDocumentActions.ACTION_APPROVE);
161: if (wfdoc.isBlanketApproveCapable()) {
162: list.add(WorkflowDocumentActions.ACTION_BLANKETAPPROVE);
163: }
164: list.add(WorkflowDocumentActions.ACTION_DISAPPROVE);
165: if (wfdoc.getPreviousNodeNames().length > 0) {
166: list
167: .add(WorkflowDocumentActions.ACTION_RETURN_TO_PREVIOUS);
168: }
169: }
170: if (wfdoc.isCompletionRequested()) {
171: list.add(WorkflowDocumentActions.ACTION_COMPLETE);
172: if (wfdoc.isBlanketApproveCapable()) {// duplicating this because
173: // it determines display
174: // order. this is a
175: // limitation of the style
176: // sheet but most easily
177: // corrected here for now...
178: list.add(WorkflowDocumentActions.ACTION_BLANKETAPPROVE);
179: }
180: list.add(WorkflowDocumentActions.ACTION_CANCEL);
181: }
182: if (wfdoc.isFYIRequested()) {
183: list.add(WorkflowDocumentActions.ACTION_FYI);
184: }
185: if (wfdoc.isRouteCapable()) {
186: list.add(WorkflowDocumentActions.ACTION_ROUTE);
187: if (wfdoc.isBlanketApproveCapable()) {// duplicating this because
188: // it determines display
189: // order. this is a
190: // limitation of the style
191: // sheet but most easily
192: // corrected here for now...
193: list.add(WorkflowDocumentActions.ACTION_BLANKETAPPROVE);
194: }
195: list.add(WorkflowDocumentActions.ACTION_SAVE);
196: list.add(WorkflowDocumentActions.ACTION_CANCEL);
197: }
198: return list;
199: }
200:
201: private static final String[] EDITABLE_ACTIONS = new String[] {
202: WorkflowDocumentActions.ACTION_CREATE,
203: WorkflowDocumentActions.ACTION_ROUTE,
204: WorkflowDocumentActions.ACTION_APPROVE,
205: WorkflowDocumentActions.ACTION_DISAPPROVE,
206: WorkflowDocumentActions.ACTION_COMPLETE };
207:
208: public static boolean isEditable(List actions) {
209: return listContainsItems(actions, EDITABLE_ACTIONS);
210: }
211:
212: public static void addActions(Document dom, Element documentState,
213: List actions) {
214: Element actionsPossible = EDLXmlUtils.getOrCreateChildElement(
215: documentState, "actionsPossible", true);
216: Iterator it = actions.iterator();
217: while (it.hasNext()) {
218: String action = it.next().toString();
219: Element actionElement = dom.createElement(action);
220: // if we use string.xsl we can avoid doing this here
221: // (unless for some reason we decide we want different titles)
222: if (!Character.isUpperCase(action.charAt(0))) {
223: StringBuffer sb = new StringBuffer(action);
224: sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
225: action = sb.toString();
226: }
227: actionElement.setAttribute("title", action);
228: actionsPossible.appendChild(actionElement);
229: }
230:
231: Element annotatable = EDLXmlUtils.getOrCreateChildElement(
232: documentState, "annotatable", true);
233: annotatable.appendChild(dom.createTextNode(String
234: .valueOf(isAnnotatable(actions))));
235: }
236:
237: public static final String[] ANNOTATABLE_ACTIONS = new String[] {
238: WorkflowDocumentActions.ACTION_APPROVE,
239: WorkflowDocumentActions.ACTION_ACKNOWLEDGE,
240: WorkflowDocumentActions.ACTION_COMPLETE,
241: WorkflowDocumentActions.ACTION_FYI,
242: WorkflowDocumentActions.ACTION_DISAPPROVE,
243: WorkflowDocumentActions.ACTION_CANCEL,
244: WorkflowDocumentActions.ACTION_RETURN_TO_PREVIOUS };
245:
246: public static boolean listContainsItems(List list, Object[] items) {
247: for (int i = 0; i < items.length; i++) {
248: if (list.contains(items[i]))
249: return true;
250: }
251: return false;
252: }
253:
254: /**
255: * Determines whether to display the annotation text box
256: * Currently we will show the annotation box if ANY of the possible actions are
257: * annotatable.
258: * But what happens if we have an un-annotatable action?
259: * Hey, why don't we just make all actions annotatable.
260: * @param actions list of possible actions
261: * @return whether to show the annotation text box
262: */
263: public static boolean isAnnotatable(List actions) {
264: return listContainsItems(actions, ANNOTATABLE_ACTIONS);
265: }
266:
267: }
|