package abbot.script; import java.util.*; import org.jdom.Element; import abbot.i18n.Strings; /** Script step which groups a sequence of other Steps. The sub-Steps have a * fixed order and are executed in the order contained in the sequence. * Events sent by sub-Steps are propagated by this one. */ public class Sequence extends Step { private static final String USAGE = "<sequence ...>...</sequence>"; private ArrayList sequence = new ArrayList(); /** Construct a <code>Sequence</code> from XML data. */ public Sequence(Resolver resolver, Element el, Map atts) { super(resolver, atts); try { parseChildren(el); } catch(InvalidScriptException ise) { setScriptError(ise); } } public Sequence(Resolver resolver, Map atts) { super(resolver, atts); } public Sequence(Resolver resolver, String desc) { this(resolver, desc, null); } /** Create an aggregate from a list of existing <code>Step</code>s. */ public Sequence(Resolver resolver, String desc, List steps) { super(resolver, desc); if (steps != null) { Iterator iter = steps.iterator(); synchronized(sequence) { while(iter.hasNext()) { addStep((Step)iter.next()); } } } } protected void parseChild(Element el) throws InvalidScriptException { Step step = createStep(getResolver(), el); addStep(step); } protected void parseChildren(Element el) throws InvalidScriptException { synchronized(sequence) { Iterator iter = el.getContent().iterator(); while (iter.hasNext()) { Object obj = iter.next(); if (obj instanceof Element) parseChild((Element)obj); else if (obj instanceof org.jdom.Comment) { String text = ((org.jdom.Comment)obj).getText(); addStep(new abbot.script.Comment(getResolver(), text)); } } } } public String getDefaultDescription() { return Strings.get("sequence.desc", new Object[] { String.valueOf(size()) }); } public String getXMLTag() { return TAG_SEQUENCE; } protected Element addContent(Element el) { ArrayList seq; synchronized(sequence) { seq = (ArrayList)sequence.clone(); } Iterator iter = seq.iterator(); while (iter.hasNext()) { Step step = (Step)iter.next(); if (step instanceof abbot.script.Comment) el.addContent(new org.jdom.Comment(step.getDescription())); else el.addContent(step.toXML()); } return el; } /** Returns a string describing the proper XML usage for this class. */ public String getUsage() { return USAGE; } /** Only thing directly editable on a sequence is its description. */ public String toEditableString() { return getDescription(); } /** Process each event in our list. */ protected void runStep() throws Throwable { runStep(null); } /** Process each event in our list, using the given runner. */ protected void runStep(StepRunner runner) throws Throwable { Iterator iter; synchronized(sequence) { iter = ((ArrayList)sequence.clone()).iterator(); } if (runner != null) { while (iter.hasNext() && !runner.stopped()) { runner.runStep((Step)iter.next()); } } else { while (iter.hasNext()) { ((Step)iter.next()).run(); } } } /** Returns the number of steps contained in this one. */ public int size() { synchronized(sequence) { return sequence.size(); } } /** Remove all stepchildren. More effective than Cinderella's stepmother. */ public void clear() { synchronized(sequence) { sequence.clear(); } } /** Returns a list of the steps contained in this one. */ public java.util.List steps() { return sequence; } /** Returns the index of the given step in the sequence, or -1 if the step is not in the sequence. */ public int indexOf(Step step) { synchronized(sequence) { return sequence.indexOf(step); } } /** Return the step at the given index in the sequence. */ public Step getStep(int index) { synchronized(sequence) { return (Step)sequence.get(index); } } /** Inserts a step at the given index in the sequence. */ public void addStep(int index, Step step) { synchronized(sequence) { sequence.add(index, step); } } /** Adds a step to the end of the sequence. */ public void addStep(Step step) { synchronized(sequence) { sequence.add(step); } } /** Replaces the step at the given index. */ public void setStep(int index, Step step) { synchronized(sequence) { sequence.set(index, step); } } /** Removes the step if it exists in the sequence. */ public void removeStep(Step step) { synchronized(sequence) { sequence.remove(step); } } /** Removes the step at the given index in the sequence. */ public void removeStep(int index) { synchronized(sequence) { sequence.remove(index); } } }