001: package abbot.script;
002:
003: import java.util.*;
004:
005: import org.jdom.Element;
006:
007: import abbot.i18n.Strings;
008:
009: /** Script step which groups a sequence of other Steps. The sub-Steps have a
010: * fixed order and are executed in the order contained in the sequence.
011: * Events sent by sub-Steps are propagated by this one.
012: */
013: public class Sequence extends Step {
014:
015: private static final String USAGE = "<sequence ...>...</sequence>";
016: private ArrayList sequence = new ArrayList();
017:
018: /** Construct a <code>Sequence</code> from XML data. */
019: public Sequence(Resolver resolver, Element el, Map atts) {
020: super (resolver, atts);
021: try {
022: parseChildren(el);
023: } catch (InvalidScriptException ise) {
024: setScriptError(ise);
025: }
026: }
027:
028: public Sequence(Resolver resolver, Map atts) {
029: super (resolver, atts);
030: }
031:
032: public Sequence(Resolver resolver, String desc) {
033: this (resolver, desc, null);
034: }
035:
036: /** Create an aggregate from a list of existing <code>Step</code>s. */
037: public Sequence(Resolver resolver, String desc, List steps) {
038: super (resolver, desc);
039: if (steps != null) {
040: Iterator iter = steps.iterator();
041: synchronized (sequence) {
042: while (iter.hasNext()) {
043: addStep((Step) iter.next());
044: }
045: }
046: }
047: }
048:
049: protected void parseChild(Element el) throws InvalidScriptException {
050: Step step = createStep(getResolver(), el);
051: addStep(step);
052: }
053:
054: protected void parseChildren(Element el)
055: throws InvalidScriptException {
056: synchronized (sequence) {
057: Iterator iter = el.getContent().iterator();
058: while (iter.hasNext()) {
059: Object obj = iter.next();
060: if (obj instanceof Element)
061: parseChild((Element) obj);
062: else if (obj instanceof org.jdom.Comment) {
063: String text = ((org.jdom.Comment) obj).getText();
064: addStep(new abbot.script.Comment(getResolver(),
065: text));
066: }
067: }
068: }
069: }
070:
071: public String getDefaultDescription() {
072: return Strings.get("sequence.desc", new Object[] { String
073: .valueOf(size()) });
074: }
075:
076: public String getXMLTag() {
077: return TAG_SEQUENCE;
078: }
079:
080: protected Element addContent(Element el) {
081: ArrayList seq;
082: synchronized (sequence) {
083: seq = (ArrayList) sequence.clone();
084: }
085: Iterator iter = seq.iterator();
086: while (iter.hasNext()) {
087: Step step = (Step) iter.next();
088: if (step instanceof abbot.script.Comment)
089: el.addContent(new org.jdom.Comment(step
090: .getDescription()));
091: else
092: el.addContent(step.toXML());
093: }
094: return el;
095: }
096:
097: /** Returns a string describing the proper XML usage for this class. */
098: public String getUsage() {
099: return USAGE;
100: }
101:
102: /** Only thing directly editable on a sequence is its description. */
103: public String toEditableString() {
104: return getDescription();
105: }
106:
107: /** Process each event in our list. */
108: protected void runStep() throws Throwable {
109: runStep(null);
110: }
111:
112: /** Process each event in our list, using the given runner. */
113: protected void runStep(StepRunner runner) throws Throwable {
114: Iterator iter;
115: synchronized (sequence) {
116: iter = ((ArrayList) sequence.clone()).iterator();
117: }
118: if (runner != null) {
119: while (iter.hasNext() && !runner.stopped()) {
120: runner.runStep((Step) iter.next());
121: }
122: } else {
123: while (iter.hasNext()) {
124: ((Step) iter.next()).run();
125: }
126: }
127: }
128:
129: /** Returns the number of steps contained in this one. */
130: public int size() {
131: synchronized (sequence) {
132: return sequence.size();
133: }
134: }
135:
136: /** Remove all stepchildren. More effective than Cinderella's
137: stepmother. */
138: public void clear() {
139: synchronized (sequence) {
140: sequence.clear();
141: }
142: }
143:
144: /** Returns a list of the steps contained in this one. */
145: public java.util.List steps() {
146: return sequence;
147: }
148:
149: /** Returns the index of the given step in the sequence, or -1 if the step
150: is not in the sequence. */
151: public int indexOf(Step step) {
152: synchronized (sequence) {
153: return sequence.indexOf(step);
154: }
155: }
156:
157: /** Return the step at the given index in the sequence. */
158: public Step getStep(int index) {
159: synchronized (sequence) {
160: return (Step) sequence.get(index);
161: }
162: }
163:
164: /** Inserts a step at the given index in the sequence. */
165: public void addStep(int index, Step step) {
166: synchronized (sequence) {
167: sequence.add(index, step);
168: }
169: }
170:
171: /** Adds a step to the end of the sequence. */
172: public void addStep(Step step) {
173: synchronized (sequence) {
174: sequence.add(step);
175: }
176: }
177:
178: /** Replaces the step at the given index. */
179: public void setStep(int index, Step step) {
180: synchronized (sequence) {
181: sequence.set(index, step);
182: }
183: }
184:
185: /** Removes the step if it exists in the sequence. */
186: public void removeStep(Step step) {
187: synchronized (sequence) {
188: sequence.remove(step);
189: }
190: }
191:
192: /** Removes the step at the given index in the sequence. */
193: public void removeStep(int index) {
194: synchronized (sequence) {
195: sequence.remove(index);
196: }
197: }
198: }
|