001    package org.apache.commons.workflow.core;
002    
003    import org.apache.commons.workflow.Context;
004    import org.apache.commons.workflow.Descriptor;
005    import org.apache.commons.workflow.Step;
006    import org.apache.commons.workflow.StepException;
007    
008    
009    /**
010     * <p>Evaluate properties specified by the associated Descriptors, and
011     * transfer control to the specified step if ALL of them are
012     * <code>false</code> (if boolean) or null (if Object).
013     *
014     * <b>This is the exact opposite of AndStep</b>
015     *
016     * To avoid non-deterministic evaluation stack behavior, all of the 
017     * specified Descriptors are always evaluated.</p>
018     *
019     * <p>Supported Attributes:</p>
020     * <ul>
021     * <li><strong>step</strong> - Identifier of the Step to which control
022     *     should be transferred if the condition is not met.</li>
023     * </ul>
024     *
025     * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
026     * @author Preston Sheldon
027     */
028    
029    public class NotAndStep extends GotoStep {
030    
031    
032        // ----------------------------------------------------------= Constructors
033    
034    
035        /**
036         * Construct a default instance of this Step.
037         */
038        public NotAndStep() {
039    
040            super();
041    
042        }
043        /**
044         * Construct an instance of this Step with the specified identifier.
045         *
046         * @param id Step identifier
047         */
048        public NotAndStep(String id) {
049    
050            this(id, null, null);
051    
052        }
053        /**
054         * Construct a fully configured instance of this Step.
055         *
056         * @param id Step identifier of this step
057         * @param step Step identifier to which control should be redirected
058         */
059        public NotAndStep(String id, String step) {
060    
061            this(id, step, null);
062    
063        }
064        /**
065         * Construct a fully configured instance of this Step.
066         *
067         * @param id Step identifier of this step
068         * @param step Step identifier to which control should be redirected
069         * @param descriptor Initial descriptor to be added
070         */
071        public NotAndStep(String id, String step, Descriptor descriptor) {
072    
073            super();
074            setId(id);
075            setStep(step);
076            addDescriptor(descriptor);
077    
078        }
079        // --------------------------------------------------------- Public Methods
080    
081    
082        /**
083         * Perform the executable actions related to this Step, in the context of
084         * the specified Context.
085         *
086         * @param context The Context that is tracking our execution state
087         *
088         * @exception StepException if a processing error has occurred
089         */
090        public void execute(Context context) throws StepException {
091    
092            // Process all associated descriptors
093            boolean condition = true;
094            Descriptor descriptors[] = findDescriptors();
095            for (int i = 0; i < descriptors.length; i++) {
096                Object value = descriptors[i].get(context);
097                if (value == null)
098                    condition = false;
099                else if ((value instanceof Boolean) &&
100                         !((Boolean) value).booleanValue())
101                    condition = false;
102            }
103    
104            // Conditionally forward control to the specified step
105            if (!condition) {
106                Step next = getOwner().findStep(this.step);
107                if (next == null)
108                    throw new StepException("Cannot find step '" + step + "'",
109                                            this);
110                context.setNextStep(next);
111            }
112                    
113        }
114    }