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 ActionDescriptor extends AbstractDescriptor implements
022: Validatable {
023: //~ Instance fields ////////////////////////////////////////////////////////
024:
025: protected List conditionalResults = new ArrayList();
026: protected List postFunctions = new ArrayList();
027: protected List preFunctions = new ArrayList();
028: protected List validators = new ArrayList();
029: protected Map metaAttributes = new HashMap();
030: protected RestrictionDescriptor restriction;
031: protected ResultDescriptor unconditionalResult;
032: protected String name;
033: protected String view;
034: protected boolean autoExecute = false;
035: protected boolean common;
036: protected boolean finish = false;
037:
038: //~ Constructors ///////////////////////////////////////////////////////////
039:
040: /**
041: * @deprecated use {@link DescriptorFactory} instead
042: */
043: ActionDescriptor() {
044: }
045:
046: /**
047: * @deprecated use {@link DescriptorFactory} instead
048: */
049: ActionDescriptor(Element action) {
050: init(action);
051: }
052:
053: //~ Methods ////////////////////////////////////////////////////////////////
054:
055: public void setAutoExecute(boolean autoExecute) {
056: this .autoExecute = autoExecute;
057: }
058:
059: public boolean getAutoExecute() {
060: return autoExecute;
061: }
062:
063: public boolean isCommon() {
064: return common;
065: }
066:
067: public List getConditionalResults() {
068: return conditionalResults;
069: }
070:
071: public void setFinish(boolean finish) {
072: this .finish = finish;
073: }
074:
075: public boolean isFinish() {
076: return finish;
077: }
078:
079: public void setMetaAttributes(Map metaAttributes) {
080: this .metaAttributes = metaAttributes;
081: }
082:
083: public Map getMetaAttributes() {
084: return metaAttributes;
085: }
086:
087: public void setName(String name) {
088: this .name = name;
089: }
090:
091: public String getName() {
092: return name;
093: }
094:
095: public List getPostFunctions() {
096: return postFunctions;
097: }
098:
099: public List getPreFunctions() {
100: return preFunctions;
101: }
102:
103: public void setRestriction(RestrictionDescriptor restriction) {
104: this .restriction = restriction;
105: }
106:
107: public RestrictionDescriptor getRestriction() {
108: return restriction;
109: }
110:
111: public void setUnconditionalResult(
112: ResultDescriptor unconditionalResult) {
113: this .unconditionalResult = unconditionalResult;
114: }
115:
116: public ResultDescriptor getUnconditionalResult() {
117: return unconditionalResult;
118: }
119:
120: public List getValidators() {
121: return validators;
122: }
123:
124: public void setView(String view) {
125: this .view = view;
126: }
127:
128: public String getView() {
129: return view;
130: }
131:
132: public String toString() {
133: StringBuffer sb = new StringBuffer();
134:
135: if (name != null) {
136: sb.append(name);
137: }
138:
139: if ((view != null) && (view.length() > 0)) {
140: sb.append(" (").append(view).append(")");
141: }
142:
143: return sb.toString();
144: }
145:
146: public void validate() throws InvalidWorkflowDescriptorException {
147: ValidationHelper.validate(preFunctions);
148: ValidationHelper.validate(postFunctions);
149: ValidationHelper.validate(validators);
150: ValidationHelper.validate(conditionalResults);
151:
152: if ((conditionalResults.size() > 0)
153: && (unconditionalResult == null)) {
154: throw new InvalidWorkflowDescriptorException(
155: "Action "
156: + name
157: + " has conditional results but no fallback unconditional result");
158: }
159:
160: if (restriction != null) {
161: restriction.validate();
162: }
163:
164: if (unconditionalResult != null) {
165: unconditionalResult.validate();
166: }
167: }
168:
169: public void writeXML(PrintWriter out, int indent) {
170: XMLUtil.printIndent(out, indent++);
171:
172: StringBuffer buf = new StringBuffer("<action id=\"");
173: buf.append(getId());
174: buf.append("\"");
175:
176: if ((name != null) && (name.length() > 0)) {
177: buf.append(" name=\"");
178: buf.append(XMLUtil.encode(name));
179: buf.append("\"");
180: }
181:
182: if ((view != null) && (view.length() > 0)) {
183: buf.append(" view=\"");
184: buf.append(XMLUtil.encode(view));
185: buf.append("\"");
186: }
187:
188: if (finish) {
189: buf.append(" finish=\"true\"");
190: }
191:
192: if (autoExecute) {
193: buf.append(" auto=\"true\"");
194: }
195:
196: buf.append(">");
197: out.println(buf.toString());
198:
199: Iterator iter = metaAttributes.entrySet().iterator();
200:
201: while (iter.hasNext()) {
202: Map.Entry entry = (Map.Entry) iter.next();
203: XMLUtil.printIndent(out, indent);
204: out.print("<meta name=\"");
205: out.print(XMLUtil.encode(entry.getKey()));
206: out.print("\">");
207: out.print(XMLUtil.encode(entry.getValue()));
208: out.println("</meta>");
209: }
210:
211: if (restriction != null) {
212: restriction.writeXML(out, indent);
213: }
214:
215: if (validators.size() > 0) {
216: XMLUtil.printIndent(out, indent++);
217: out.println("<validators>");
218:
219: for (int i = 0; i < validators.size(); i++) {
220: ValidatorDescriptor validator = (ValidatorDescriptor) validators
221: .get(i);
222: validator.writeXML(out, indent);
223: }
224:
225: XMLUtil.printIndent(out, --indent);
226: out.println("</validators>");
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: XMLUtil.printIndent(out, indent++);
244: out.println("<results>");
245:
246: for (int i = 0; i < conditionalResults.size(); i++) {
247: ConditionalResultDescriptor result = (ConditionalResultDescriptor) conditionalResults
248: .get(i);
249: result.writeXML(out, indent);
250: }
251:
252: if (unconditionalResult != null) {
253: unconditionalResult.writeXML(out, indent);
254: }
255:
256: XMLUtil.printIndent(out, --indent);
257: out.println("</results>");
258:
259: if (postFunctions.size() > 0) {
260: XMLUtil.printIndent(out, indent++);
261: out.println("<post-functions>");
262:
263: for (int i = 0; i < postFunctions.size(); i++) {
264: FunctionDescriptor function = (FunctionDescriptor) postFunctions
265: .get(i);
266: function.writeXML(out, indent);
267: }
268:
269: XMLUtil.printIndent(out, --indent);
270: out.println("</post-functions>");
271: }
272:
273: XMLUtil.printIndent(out, --indent);
274: out.println("</action>");
275: }
276:
277: protected void init(Element action) {
278: try {
279: setId(Integer.parseInt(action.getAttribute("id")));
280: } catch (Exception ex) {
281: throw new IllegalArgumentException(
282: "Invalid action id value '"
283: + action.getAttribute("id") + "'");
284: }
285:
286: this .name = action.getAttribute("name");
287: this .view = action.getAttribute("view");
288: this .autoExecute = "true".equalsIgnoreCase(action
289: .getAttribute("auto"));
290: this .finish = "true".equalsIgnoreCase(action
291: .getAttribute("finish"));
292:
293: NodeList children = action.getChildNodes();
294:
295: for (int i = 0; i < children.getLength(); i++) {
296: Node child = children.item(i);
297:
298: if (child.getNodeName().equals("meta")) {
299: Element meta = (Element) child;
300: String value = XMLUtil.getText(meta);
301: this .metaAttributes.put(meta.getAttribute("name"),
302: value);
303: }
304: }
305:
306: // set up validators - OPTIONAL
307: Element v = XMLUtil.getChildElement(action, "validators");
308:
309: if (v != null) {
310: List validators = XMLUtil.getChildElements(v, "validator");
311:
312: for (int k = 0; k < validators.size(); k++) {
313: Element validator = (Element) validators.get(k);
314: ValidatorDescriptor validatorDescriptor = DescriptorFactory
315: .getFactory().createValidatorDescriptor(
316: validator);
317: validatorDescriptor.setParent(this );
318: this .validators.add(validatorDescriptor);
319: }
320: }
321:
322: // set up pre-functions - OPTIONAL
323: Element pre = XMLUtil.getChildElement(action, "pre-functions");
324:
325: if (pre != null) {
326: List preFunctions = XMLUtil.getChildElements(pre,
327: "function");
328:
329: for (int k = 0; k < preFunctions.size(); k++) {
330: Element preFunction = (Element) preFunctions.get(k);
331: FunctionDescriptor functionDescriptor = DescriptorFactory
332: .getFactory().createFunctionDescriptor(
333: preFunction);
334: functionDescriptor.setParent(this );
335: this .preFunctions.add(functionDescriptor);
336: }
337: }
338:
339: // set up results - REQUIRED
340: Element resultsElememt = XMLUtil.getChildElement(action,
341: "results");
342: List results = XMLUtil.getChildElements(resultsElememt,
343: "result");
344:
345: for (int k = 0; k < results.size(); k++) {
346: Element result = (Element) results.get(k);
347: ConditionalResultDescriptor conditionalResultDescriptor = new ConditionalResultDescriptor(
348: result);
349: conditionalResultDescriptor.setParent(this );
350: this .conditionalResults.add(conditionalResultDescriptor);
351: }
352:
353: Element unconditionalResult = XMLUtil.getChildElement(
354: resultsElememt, "unconditional-result");
355:
356: // [KAP] This allows loading a workflow with actions without unconditional-results
357: if (unconditionalResult != null) {
358: this .unconditionalResult = DescriptorFactory.getFactory()
359: .createResultDescriptor(unconditionalResult);
360: this .unconditionalResult.setParent(this );
361: }
362:
363: // set up post-functions - OPTIONAL
364: Element post = XMLUtil
365: .getChildElement(action, "post-functions");
366:
367: if (post != null) {
368: List postFunctions = XMLUtil.getChildElements(post,
369: "function");
370:
371: for (int k = 0; k < postFunctions.size(); k++) {
372: Element postFunction = (Element) postFunctions.get(k);
373: FunctionDescriptor functionDescriptor = DescriptorFactory
374: .getFactory().createFunctionDescriptor(
375: postFunction);
376: functionDescriptor.setParent(this );
377: this .postFunctions.add(functionDescriptor);
378: }
379: }
380:
381: // set up restrict-to - OPTIONAL
382: Element restrictElement = XMLUtil.getChildElement(action,
383: "restrict-to");
384:
385: if (restrictElement != null) {
386: restriction = new RestrictionDescriptor(restrictElement);
387:
388: if (restriction.getConditionsDescriptor() == null) {
389: restriction = null;
390: } else {
391: restriction.setParent(this );
392: }
393: }
394: }
395:
396: void setCommon(boolean common) {
397: this.common = common;
398: }
399: }
|