001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.workflow.loader;
006:
007: import com.opensymphony.workflow.InvalidWorkflowDescriptorException;
008: import com.opensymphony.workflow.util.Validatable;
009:
010: import org.w3c.dom.Element;
011: import org.w3c.dom.Node;
012: import org.w3c.dom.NodeList;
013:
014: import java.io.PrintWriter;
015:
016: import java.util.*;
017:
018: /**
019: * @author <a href="mailto:plightbo@hotmail.com">Pat Lightbody</a>
020: */
021: public class StepDescriptor extends AbstractDescriptor implements
022: Validatable {
023: //~ Instance fields ////////////////////////////////////////////////////////
024:
025: protected List actions = new ArrayList();
026:
027: /**
028: * this list maintained internally to allow for proper xml serialization.
029: * All common-action elements in the XML file are expanded into ActionDescriptors
030: * and are available via getActions()
031: */
032: protected List commonActions = new ArrayList();
033: protected List permissions = new ArrayList();
034: protected List postFunctions = new ArrayList();
035: protected List preFunctions = new ArrayList();
036: protected Map metaAttributes = new HashMap();
037: protected String name;
038: protected boolean hasActions = false;
039:
040: //~ Constructors ///////////////////////////////////////////////////////////
041:
042: /**
043: * @deprecated use {@link DescriptorFactory} instead
044: */
045: StepDescriptor() {
046: }
047:
048: /**
049: * @deprecated use {@link DescriptorFactory} instead
050: */
051: StepDescriptor(Element step) {
052: init(step);
053: }
054:
055: /** sets parent */
056: StepDescriptor(Element step, AbstractDescriptor parent) {
057: setParent(parent);
058: init(step);
059: }
060:
061: //~ Methods ////////////////////////////////////////////////////////////////
062:
063: public ActionDescriptor getAction(int id) {
064: for (Iterator iterator = actions.iterator(); iterator.hasNext();) {
065: ActionDescriptor action = (ActionDescriptor) iterator
066: .next();
067:
068: if (action.getId() == id) {
069: return action;
070: }
071: }
072:
073: return null;
074: }
075:
076: /**
077: * Get a List of {@link ActionDescriptor}s for this step
078: */
079: public List getActions() {
080: return actions;
081: }
082:
083: /**
084: * Get a list of common actions.
085: * @return a List of Integer action id's.
086: */
087: public List getCommonActions() {
088: return commonActions;
089: }
090:
091: public void setMetaAttributes(Map metaAttributes) {
092: this .metaAttributes = metaAttributes;
093: }
094:
095: public Map getMetaAttributes() {
096: return metaAttributes;
097: }
098:
099: public void setName(String name) {
100: this .name = name;
101: }
102:
103: public String getName() {
104: return name;
105: }
106:
107: /**
108: * Get a List of {@link PermissionDescriptor}s for this step
109: */
110: public List getPermissions() {
111: return permissions;
112: }
113:
114: public void setPostFunctions(List postFunctions) {
115: this .postFunctions = postFunctions;
116: }
117:
118: public List getPostFunctions() {
119: return postFunctions;
120: }
121:
122: public void setPreFunctions(List preFunctions) {
123: this .preFunctions = preFunctions;
124: }
125:
126: public List getPreFunctions() {
127: return preFunctions;
128: }
129:
130: /**
131: * Remove all common and regular actions for this step.
132: */
133: public void removeActions() {
134: commonActions.clear();
135: actions.clear();
136: hasActions = false;
137: }
138:
139: public boolean resultsInJoin(int join) {
140: for (Iterator iterator = actions.iterator(); iterator.hasNext();) {
141: ActionDescriptor actionDescriptor = (ActionDescriptor) iterator
142: .next();
143:
144: if (actionDescriptor.getUnconditionalResult().getJoin() == join) {
145: return true;
146: }
147:
148: List results = actionDescriptor.getConditionalResults();
149:
150: for (Iterator iterator2 = results.iterator(); iterator2
151: .hasNext();) {
152: ConditionalResultDescriptor resultDescriptor = (ConditionalResultDescriptor) iterator2
153: .next();
154:
155: if (resultDescriptor.getJoin() == join) {
156: return true;
157: }
158: }
159: }
160:
161: return false;
162: }
163:
164: public void validate() throws InvalidWorkflowDescriptorException {
165: if ((commonActions.size() == 0) && (actions.size() == 0)
166: && hasActions) {
167: throw new InvalidWorkflowDescriptorException(
168: "Step '"
169: + name
170: + "' actions element must contain at least one action or common-action");
171: }
172:
173: if (getId() == -1) {
174: throw new InvalidWorkflowDescriptorException(
175: "Cannot use a step ID of -1 as it is a reserved value");
176: }
177:
178: ValidationHelper.validate(actions);
179: ValidationHelper.validate(permissions);
180: ValidationHelper.validate(preFunctions);
181: ValidationHelper.validate(postFunctions);
182:
183: Iterator iter = commonActions.iterator();
184:
185: while (iter.hasNext()) {
186: Object o = iter.next();
187:
188: try {
189: Integer actionId = new Integer(o.toString());
190: ActionDescriptor commonActionReference = (ActionDescriptor) ((WorkflowDescriptor) getParent())
191: .getCommonActions().get(actionId);
192:
193: if (commonActionReference == null) {
194: throw new InvalidWorkflowDescriptorException(
195: "Common action " + actionId
196: + " specified in step " + getName()
197: + " does not exist");
198: }
199: } catch (NumberFormatException ex) {
200: throw new InvalidWorkflowDescriptorException(
201: "Common action " + o
202: + " is not a valid action ID");
203: }
204: }
205: }
206:
207: public void writeXML(PrintWriter out, int indent) {
208: XMLUtil.printIndent(out, indent++);
209: out.print("<step id=\"" + getId() + "\"");
210:
211: if ((name != null) && (name.length() > 0)) {
212: out.print(" name=\"" + XMLUtil.encode(name) + "\"");
213: }
214:
215: out.println(">");
216:
217: Iterator iter = metaAttributes.entrySet().iterator();
218:
219: while (iter.hasNext()) {
220: Map.Entry entry = (Map.Entry) iter.next();
221: XMLUtil.printIndent(out, indent);
222: out.print("<meta name=\"");
223: out.print(entry.getKey());
224: out.print("\">");
225: out.print(entry.getValue());
226: out.println("</meta>");
227: }
228:
229: if (preFunctions.size() > 0) {
230: XMLUtil.printIndent(out, indent++);
231: out.println("<pre-functions>");
232:
233: for (int i = 0; i < preFunctions.size(); i++) {
234: FunctionDescriptor function = (FunctionDescriptor) preFunctions
235: .get(i);
236: function.writeXML(out, indent);
237: }
238:
239: XMLUtil.printIndent(out, --indent);
240: out.println("</pre-functions>");
241: }
242:
243: if (permissions.size() > 0) {
244: XMLUtil.printIndent(out, indent++);
245: out.println("<external-permissions>");
246:
247: for (int i = 0; i < permissions.size(); i++) {
248: PermissionDescriptor permission = (PermissionDescriptor) permissions
249: .get(i);
250: permission.writeXML(out, indent);
251: }
252:
253: XMLUtil.printIndent(out, --indent);
254: out.println("</external-permissions>");
255: }
256:
257: if ((actions.size() > 0) || (commonActions.size() > 0)) {
258: XMLUtil.printIndent(out, indent++);
259: out.println("<actions>");
260:
261: // special serialization common-action elements
262: for (int i = 0; i < commonActions.size(); i++) {
263: out.println("<common-action id=\""
264: + commonActions.get(i) + "\" />");
265: }
266:
267: for (int i = 0; i < actions.size(); i++) {
268: ActionDescriptor action = (ActionDescriptor) actions
269: .get(i);
270:
271: if (!action.isCommon()) {
272: action.writeXML(out, indent);
273: }
274: }
275:
276: XMLUtil.printIndent(out, --indent);
277: out.println("</actions>");
278: }
279:
280: if (postFunctions.size() > 0) {
281: XMLUtil.printIndent(out, indent++);
282: out.println("<post-functions>");
283:
284: for (int i = 0; i < postFunctions.size(); i++) {
285: FunctionDescriptor function = (FunctionDescriptor) postFunctions
286: .get(i);
287: function.writeXML(out, indent);
288: }
289:
290: XMLUtil.printIndent(out, --indent);
291: out.println("</post-functions>");
292: }
293:
294: XMLUtil.printIndent(out, --indent);
295: out.println("</step>");
296: }
297:
298: protected void init(Element step) {
299: try {
300: setId(Integer.parseInt(step.getAttribute("id")));
301: } catch (Exception ex) {
302: throw new IllegalArgumentException("Invalid step id value "
303: + step.getAttribute("id"));
304: }
305:
306: name = step.getAttribute("name");
307:
308: NodeList children = step.getChildNodes();
309:
310: for (int i = 0; i < children.getLength(); i++) {
311: Node child = children.item(i);
312:
313: if (child.getNodeName().equals("meta")) {
314: Element meta = (Element) child;
315: String value = XMLUtil.getText(meta);
316: this .metaAttributes.put(meta.getAttribute("name"),
317: value);
318: }
319: }
320:
321: // set up pre-functions - OPTIONAL
322: Element pre = XMLUtil.getChildElement(step, "pre-functions");
323:
324: if (pre != null) {
325: List preFunctions = XMLUtil.getChildElements(pre,
326: "function");
327:
328: for (int k = 0; k < preFunctions.size(); k++) {
329: Element preFunction = (Element) preFunctions.get(k);
330: FunctionDescriptor functionDescriptor = DescriptorFactory
331: .getFactory().createFunctionDescriptor(
332: preFunction);
333: functionDescriptor.setParent(this );
334: this .preFunctions.add(functionDescriptor);
335: }
336: }
337:
338: // set up permissions - OPTIONAL
339: Element p = XMLUtil.getChildElement(step,
340: "external-permissions");
341:
342: if (p != null) {
343: List permissions = XMLUtil
344: .getChildElements(p, "permission");
345:
346: for (int i = 0; i < permissions.size(); i++) {
347: Element permission = (Element) permissions.get(i);
348: PermissionDescriptor permissionDescriptor = DescriptorFactory
349: .getFactory().createPermissionDescriptor(
350: permission);
351: permissionDescriptor.setParent(this );
352: this .permissions.add(permissionDescriptor);
353: }
354: }
355:
356: // set up actions - OPTIONAL
357: Element a = XMLUtil.getChildElement(step, "actions");
358:
359: if (a != null) {
360: hasActions = true;
361:
362: List actions = XMLUtil.getChildElements(a, "action");
363:
364: for (int i = 0; i < actions.size(); i++) {
365: Element action = (Element) actions.get(i);
366: ActionDescriptor actionDescriptor = DescriptorFactory
367: .getFactory().createActionDescriptor(action);
368: actionDescriptor.setParent(this );
369: this .actions.add(actionDescriptor);
370: }
371:
372: // look for common-action elements
373: List commonActions = XMLUtil.getChildElements(a,
374: "common-action");
375:
376: for (int i = 0; i < commonActions.size(); i++) {
377: Element commonAction = (Element) commonActions.get(i);
378:
379: WorkflowDescriptor workflowDescriptor = (WorkflowDescriptor) getParent();
380:
381: try {
382: Integer actionId = new Integer(commonAction
383: .getAttribute("id"));
384:
385: ActionDescriptor commonActionReference = (ActionDescriptor) workflowDescriptor
386: .getCommonActions().get(actionId);
387:
388: if (commonActionReference != null) {
389: this .actions.add(commonActionReference);
390: }
391:
392: this .commonActions.add(actionId);
393: } catch (Exception ex) {
394: //log.warn("Invalid common actionId:" + ex);
395: }
396: }
397: }
398:
399: // set up post-functions - OPTIONAL
400: Element post = XMLUtil.getChildElement(step, "post-functions");
401:
402: if (post != null) {
403: List postFunctions = XMLUtil.getChildElements(post,
404: "function");
405:
406: for (int k = 0; k < postFunctions.size(); k++) {
407: Element postFunction = (Element) postFunctions.get(k);
408: FunctionDescriptor functionDescriptor = DescriptorFactory
409: .getFactory().createFunctionDescriptor(
410: postFunction);
411: functionDescriptor.setParent(this);
412: this.postFunctions.add(functionDescriptor);
413: }
414: }
415: }
416: }
|