craigmcc    01/08/25 20:38:11

  Modified:    workflow/src/java/org/apache/commons/workflow/base
                        BaseDescriptor.java
               workflow/src/java/org/apache/commons/workflow/core
                        GotoStep.java
               workflow/src/test/org/apache/commons/workflow/core
                        CoreExecuteTestCase.java
  Added:       workflow/src/java/org/apache/commons/workflow/core
                        AndStep.java InvokeStep.java OrStep.java
  Log:
  Add three new core Step implementations:
  - InvokeStep calls an arbitrary method with an arbitrary set of
    parameters.  If the called method returns a value, it is pushed
    onto the evaluation stack.
  - AndStep evaluates the bean or property values of all associated
    Descriptors and branches to a specified Step if ALL of them return
    true (for boolean values) or non-null (for any other class)
  - OrStep evaluates the bean or property values of all associated
    Descriptors and branches to the specified Step if ANY of them
    return true (for boolean values) or non-null (for any other class).
  
  Degenerate cases of AndStep or OrStep with a single descriptor act like an
  "if" statement that tests the value of that bean or property.
  
  NOTE:  Because it is supported by a Descriptor with no configured
  properties, you can transparently consume objects from the evaluation
  stack when processing descriptor lists for these Steps (and the other
  Steps that now support descriptor lists, indicated by the fact that they
  implement the Descriptors interface).
  
  FIXME:  Think about a better way to deal with exceptions thrown by an
  invoked method.  Right now, it unconditionally throws a StepException,
  which aborts execution of the corresponding Activity.
  
  Revision  Changes    Path
  1.3       +12 -5     
jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/base/BaseDescriptor.java
  
  Index: BaseDescriptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/base/BaseDescriptor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BaseDescriptor.java       2001/08/26 00:17:55     1.2
  +++ BaseDescriptor.java       2001/08/26 03:38:11     1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/base/BaseDescriptor.java,v
 1.2 2001/08/26 00:17:55 craigmcc Exp $
  - * $Revision: 1.2 $
  - * $Date: 2001/08/26 00:17:55 $
  + * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/base/BaseDescriptor.java,v
 1.3 2001/08/26 03:38:11 craigmcc Exp $
  + * $Revision: 1.3 $
  + * $Date: 2001/08/26 03:38:11 $
    *
    * ====================================================================
    * 
  @@ -62,6 +62,7 @@
   package org.apache.commons.workflow.base;
   
   
  +import java.util.EmptyStackException;
   import org.apache.commons.jxpath.JXPathContext;
   import org.apache.commons.workflow.Context;
   import org.apache.commons.workflow.Descriptor;
  @@ -70,7 +71,7 @@
   /**
    * <p>Basic implementation of the <strong>Descriptor</strong> interface.</p>
    *
  - * @version $Revision: 1.2 $ $Date: 2001/08/26 00:17:55 $
  + * @version $Revision: 1.3 $ $Date: 2001/08/26 03:38:11 $
    * @author Craig R. McClanahan
    */
   
  @@ -298,12 +299,18 @@
           if (xpath != null) {
               JXPathContext jpc = context.getJXPathContext();
               return (jpc.getValue("local/" + xpath));
  -        } else {
  +        } else if (name != null) {
               if (scope == null)
                   return (context.get(name));
               else {
                   int scopeId = context.getScopeId(scope);
                   return (context.get(name, scopeId));
  +            }
  +        } else {
  +            try {
  +                return (context.pop());
  +            } catch (EmptyStackException e) {
  +                return (null);
               }
           }
   
  
  
  
  1.3       +33 -17    
jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/GotoStep.java
  
  Index: GotoStep.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/GotoStep.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- GotoStep.java     2001/08/22 01:06:08     1.2
  +++ GotoStep.java     2001/08/26 03:38:11     1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/GotoStep.java,v
 1.2 2001/08/22 01:06:08 craigmcc Exp $
  - * $Revision: 1.2 $
  - * $Date: 2001/08/22 01:06:08 $
  + * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/GotoStep.java,v
 1.3 2001/08/26 03:38:11 craigmcc Exp $
  + * $Revision: 1.3 $
  + * $Date: 2001/08/26 03:38:11 $
    *
    * ====================================================================
    * 
  @@ -63,14 +63,14 @@
   
   
   import org.apache.commons.workflow.Context;
  +import org.apache.commons.workflow.Descriptor;
   import org.apache.commons.workflow.Step;
   import org.apache.commons.workflow.StepException;
  -import org.apache.commons.workflow.base.BaseStep;
  +import org.apache.commons.workflow.base.DescriptorStep;
   
   
   /**
  - * <p>Perform an unconditional transfer of control to another Step (wtihin
  - * the same Activity) that has the specified unique identifier.</p>
  + * <p>Unconditionally transfer control to the specified step.</p>
    *
    * <p>Supported Attributes:</p>
    * <ul>
  @@ -78,11 +78,11 @@
    *     should be transferred.</li>
    * </ul>
    *
  - * @version $Revision: 1.2 $ $Date: 2001/08/22 01:06:08 $
  + * @version $Revision: 1.3 $ $Date: 2001/08/26 03:38:11 $
    * @author Craig R. McClanahan
    */
   
  -public class GotoStep extends BaseStep {
  +public class GotoStep extends DescriptorStep {
   
   
       // ----------------------------------------------------------= Constructors
  @@ -105,8 +105,7 @@
        */
       public GotoStep(String id) {
   
  -        super();
  -        setId(id);
  +        this(id, null);
   
       }
   
  @@ -157,17 +156,34 @@
       public void execute(Context context) throws StepException {
   
           // Locate the step to which we will transfer control
  +        Step next = findStep(this.step);
  +        if (next == null)
  +            throw new StepException("Cannot find step '" + step + "'", this);
  +
  +        // Tell our Context to transfer control
  +        context.setNextStep(next);
  +
  +    }
  +
  +
  +    // ------------------------------------------------------ Protected Methods
  +
  +
  +    /**
  +     * Return the identified Step from our current Activity, if it exists.
  +     * Otherwise, return <code>null</code>.
  +     *
  +     * @param id Identifier of the desired Step
  +     */
  +    protected Step findStep(String id) {
  +
           Step current = getActivity().getFirstStep();
           while (current != null) {
  -            if (step.equals(current.getId()))
  -                break;
  +            if (id.equals(current.getId()))
  +                return (current);
               current = current.getNextStep();
           }
  -        if (current == null)
  -            throw new StepException("Cannot find step '" + step + "'", this);
  -
  -        // Tell our Context to transfer control
  -        context.setNextStep(current);
  +        return (null);
   
       }
   
  
  
  
  1.1                  
jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/AndStep.java
  
  Index: AndStep.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/AndStep.java,v
 1.1 2001/08/26 03:38:11 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/08/26 03:38:11 $
   *
   * ====================================================================
   * 
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */ 
  
  package org.apache.commons.workflow.core;
  
  
  import org.apache.commons.workflow.Context;
  import org.apache.commons.workflow.Descriptor;
  import org.apache.commons.workflow.Step;
  import org.apache.commons.workflow.StepException;
  
  
  /**
   * <p>Evaluate properties specified by the associated Descriptors, and
   * transfer control to the specified step if ALL of them are
   * <code>true</code> (if boolean) or not null (if Object).  To avoid
   * non-deterministic evaluation stack behavior, all of the specified
   * Descriptors are always evaluated.</p>
   *
   * <p>Supported Attributes:</p>
   * <ul>
   * <li><strong>step</strong> - Identifier of the Step to which control
   *     should be transferred if the condition is met.</li>
   * </ul>
   *
   * @version $Revision: 1.1 $ $Date: 2001/08/26 03:38:11 $
   * @author Craig R. McClanahan
   */
  
  public class AndStep extends GotoStep {
  
  
      // ----------------------------------------------------------= Constructors
  
  
      /**
       * Construct a default instance of this Step.
       */
      public AndStep() {
  
          super();
  
      }
  
  
      /**
       * Construct an instance of this Step with the specified identifier.
       *
       * @param id Step identifier
       */
      public AndStep(String id) {
  
          this(id, null, null);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier of this step
       * @param step Step identifier to which control should be redirected
       */
      public AndStep(String id, String step) {
  
          this(id, step, null);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier of this step
       * @param step Step identifier to which control should be redirected
       * @param descriptor Initial descriptor to be added
       */
      public AndStep(String id, String step, Descriptor descriptor) {
  
          super();
          setId(id);
          setStep(step);
          addDescriptor(descriptor);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Perform the executable actions related to this Step, in the context of
       * the specified Context.
       *
       * @param context The Context that is tracking our execution state
       *
       * @exception StepException if a processing error has occurred
       */
      public void execute(Context context) throws StepException {
  
          // Process all associated descriptors
          boolean condition = true;
          Descriptor descriptors[] = findDescriptors();
          for (int i = 0; i < descriptors.length; i++) {
              Object value = descriptors[i].get(context);
              if (value == null)
                  condition = false;
              else if ((value instanceof Boolean) &&
                       !((Boolean) value).booleanValue())
                  condition = false;
          }
  
          // Conditionally forward control to the specified step
          if (condition) {
              Step next = findStep(this.step);
              if (next == null)
                  throw new StepException("Cannot find step '" + step + "'",
                                          this);
              context.setNextStep(next);
          }
                  
      }
  
  
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/InvokeStep.java
  
  Index: InvokeStep.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/InvokeStep.java,v
 1.1 2001/08/26 03:38:11 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/08/26 03:38:11 $
   *
   * ====================================================================
   * 
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */ 
  
  package org.apache.commons.workflow.core;
  
  
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.commons.workflow.Context;
  import org.apache.commons.workflow.Descriptor;
  import org.apache.commons.workflow.StepException;
  import org.apache.commons.workflow.base.DescriptorStep;
  
  
  /**
   * <p>Call the specified method of the specified bean in the specified
   * scope, passing arguments as specified by associated <code>Descriptor</code>
   * objects.  The <strong>first</strong> associated <code>Descriptor</code>
   * identifies the Java object on whom method invocation shall take place.</p>
   *
   * <p><strong>FIXME</strong> - Better way to deal with exceptions???</p>
   *
   * <p>Supported Attributes:</p>
   * <ul>
   * <li><strong>
   * <li><strong>method</strong> - Name of the public method to be called
   *     on the bean specified by either <code>name</code> and
   *     <code>scope</code>, or by <code>xpath</code>.</li>
   * </ul>
   *
   * @version $Revision: 1.1 $ $Date: 2001/08/26 03:38:11 $
   * @author Craig R. McClanahan
   */
  
  public class InvokeStep extends DescriptorStep {
  
  
      // ----------------------------------------------------------= Constructors
  
  
      /**
       * Construct a default instance of this Step.
       */
      public InvokeStep() {
  
          super();
  
      }
  
  
      /**
       * Construct an instance of this Step with the specified identifier.
       *
       * @param id Step identifier
       */
      public InvokeStep(String id) {
  
          super();
          setId(id);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier
       * @param method Method name
       */
      public InvokeStep(String id, String method) {
  
          super();
          setId(id);
          setMethod(method);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier
       * @param method Method name
       * @param descriptor Descriptor for the bean on which to invoke
       */
      public InvokeStep(String id, String method, Descriptor descriptor) {
  
          super();
          setId(id);
          setMethod(method);
          addDescriptor(descriptor);
  
      }
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * The method name to be invoked.
       */
      protected String method = null;
  
      public String getMethod() {
          return (this.method);
      }
  
      public void setMethod(String method) {
          this.method = method;
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Perform the executable actions related to this Step, in the context of
       * the specified Context.
       *
       * @param context The Context that is tracking our execution state
       *
       * @exception StepException if a processing error has occurred
       */
      public void execute(Context context) throws StepException {
  
          // Identify the object on whom a method is to be invoked
          Descriptor descriptors[] = findDescriptors();
          if (descriptors.length < 1)
              throw new StepException("No object descriptor on which to invoke",
                                      this);
          Object bean = descriptors[0].get(context);
          if (bean == null)
              throw new StepException("No object bean on which to invoke",
                                      this);
  
          // Assembe arrays of parameter types and values
          Class types[] = new Class[descriptors.length - 1];
          Object values[] = new Object[descriptors.length - 1];
          for (int i = 1; i < descriptors.length; i++) {
              values[i-1] = descriptors[i].get(context);
              types[i-1] = descriptors[i].getType();
              if (types[i-1] == null) {
                  if (values[i-1] == null)
                      types[i-1] = Object.class;
                  else
                      types[i-1] = values[i-1].getClass();
              }
          }
  
          // Identify a compatible method signature on the bean
          Method method = findMethod(bean, this.method, types);
          if (method == null)
              throw new StepException("No available method " +
                                      signature(this.method, types),
                                      this);
  
          // Invoke the requested method on the requested bean
          // FIXME - better way to deal with exceptions?
          try {
              Class clazz = method.getReturnType();
              if ((clazz != null) && (clazz != Void.TYPE)) {
                  Object result = method.invoke(bean, values);
                  context.push(result);
              } else {
                  method.invoke(bean, values);
              }
          } catch (InvocationTargetException t) {
              Throwable cause = t.getTargetException();
              throw new StepException("Invoke exception", cause, this);
          } catch (Throwable t) {
              throw new StepException("Invoke exception", t, this);
          }
  
      }
  
  
      // ------------------------------------------------------ Protected Methods
  
  
      /**
       * Return a <code>Method</code> of the specified <code>Class</code> with
       * the specified method name, that takes the specified parameter types,
       * if there is one.  Otherwise, return <code>null</code>.
       *
       * @param bean Bean on which method searching is to be done
       * @param name Method name to search for
       * @param types Parameter types to search for
       */
      protected Method findMethod(Object bean, String name, Class types[]) {
  
          try {
              return (bean.getClass().getMethod(name, types));
          } catch (NoSuchMethodException e) {
              return (null);
          }
  
      }
  
  
      /**
       * Return a method signature useful in debugging and exception messages.
       *
       * @param method Method name
       * @param types Parameter types
       */
      protected String signature(String name, Class types[]) {
  
          StringBuffer sb = new StringBuffer(name);
          sb.append('(');
          for (int i = 0; i < types.length; i++) {
              if (i > 0)
                  sb.append(',');
              sb.append(types[i].getName());
          }
          sb.append(')');
          return (sb.toString());
  
      }
  
  
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/OrStep.java
  
  Index: OrStep.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/java/org/apache/commons/workflow/core/OrStep.java,v
 1.1 2001/08/26 03:38:11 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/08/26 03:38:11 $
   *
   * ====================================================================
   * 
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */ 
  
  package org.apache.commons.workflow.core;
  
  
  import org.apache.commons.workflow.Context;
  import org.apache.commons.workflow.Descriptor;
  import org.apache.commons.workflow.Step;
  import org.apache.commons.workflow.StepException;
  
  
  /**
   * <p>Evaluate properties specified by the associated Descriptors, and
   * transfer control to the specified step if ANY of them are
   * <code>true</code> (if boolean) or not null (if Object).  To avoid
   * non-deterministic evaluation stack behavior, all of the specified
   * Descriptors are always evaluated.</p>
   *
   * <p>Supported Attributes:</p>
   * <ul>
   * <li><strong>step</strong> - Identifier of the Step to which control
   *     should be transferred if the condition is met.</li>
   * </ul>
   *
   * @version $Revision: 1.1 $ $Date: 2001/08/26 03:38:11 $
   * @author Craig R. McClanahan
   */
  
  public class OrStep extends GotoStep {
  
  
      // ----------------------------------------------------------= Constructors
  
  
      /**
       * Construct a default instance of this Step.
       */
      public OrStep() {
  
          super();
  
      }
  
  
      /**
       * Construct an instance of this Step with the specified identifier.
       *
       * @param id Step identifier
       */
      public OrStep(String id) {
  
          this(id, null, null);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier of this step
       * @param step Step identifier to which control should be redirected
       */
      public OrStep(String id, String step) {
  
          this(id, step, null);
  
      }
  
  
      /**
       * Construct a fully configured instance of this Step.
       *
       * @param id Step identifier of this step
       * @param step Step identifier to which control should be redirected
       * @param descriptor Initial descriptor to be added
       */
      public OrStep(String id, String step, Descriptor descriptor) {
  
          super();
          setId(id);
          setStep(step);
          addDescriptor(descriptor);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Perform the executable actions related to this Step, in the context of
       * the specified Context.
       *
       * @param context The Context that is tracking our execution state
       *
       * @exception StepException if a processing error has occurred
       */
      public void execute(Context context) throws StepException {
  
          // Process all associated descriptors
          boolean condition = false;
          Descriptor descriptors[] = findDescriptors();
          for (int i = 0; i < descriptors.length; i++) {
              Object value = descriptors[i].get(context);
              if (value != null) {
                  if (value instanceof Boolean) {
                      if (((Boolean) value).booleanValue())
                          condition = true;
                  } else {
                      condition = true;
                  }
              }
          }
  
          // Conditionally forward control to the specified step
          if (condition) {
              Step next = findStep(this.step);
              if (next == null)
                  throw new StepException("Cannot find step '" + step + "'",
                                          this);
              context.setNextStep(next);
          }
                  
      }
  
  
  }
  
  
  
  1.5       +103 -4    
jakarta-commons-sandbox/workflow/src/test/org/apache/commons/workflow/core/CoreExecuteTestCase.java
  
  Index: CoreExecuteTestCase.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/workflow/src/test/org/apache/commons/workflow/core/CoreExecuteTestCase.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- CoreExecuteTestCase.java  2001/08/26 00:06:51     1.4
  +++ CoreExecuteTestCase.java  2001/08/26 03:38:11     1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/test/org/apache/commons/workflow/core/CoreExecuteTestCase.java,v
 1.4 2001/08/26 00:06:51 craigmcc Exp $
  - * $Revision: 1.4 $
  - * $Date: 2001/08/26 00:06:51 $
  + * $Header: 
/home/cvs/jakarta-commons-sandbox/workflow/src/test/org/apache/commons/workflow/core/CoreExecuteTestCase.java,v
 1.5 2001/08/26 03:38:11 craigmcc Exp $
  + * $Revision: 1.5 $
  + * $Date: 2001/08/26 03:38:11 $
    *
    * ====================================================================
    *
  @@ -85,7 +85,7 @@
    * implementations.</p>
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.4 $ $Date: 2001/08/26 00:06:51 $
  + * @version $Revision: 1.5 $ $Date: 2001/08/26 03:38:11 $
    */
   
   public class CoreExecuteTestCase extends TestCase
  @@ -219,6 +219,105 @@
               assertEquals("Popped value is 'Only after resume'",
                            "Only after resume",
                            (String) context.pop());
  +        } catch (StepException e) {
  +            e.printStackTrace(System.out);
  +            if (e.getCause() != null) {
  +                System.out.println("ROOT CAUSE");
  +                e.getCause().printStackTrace(System.out);
  +            }
  +            fail("Threw StepException " + e);
  +        } catch (Throwable e) {
  +            e.printStackTrace();
  +            fail("Threw exception " + e);
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Test invoking arbitrary methods with various combinations of
  +     * parameter mechanisms.
  +     */
  +    public void testInvoke() {
  +
  +        // Stash a bean in local scope to play with
  +        TestBean bean = new TestBean();
  +        context.put("bean", bean);
  +
  +        // Configure the steps in this activity
  +        activity.addStep(new InvokeStep("01", "getStringProperty",
  +                                        new BaseDescriptor("bean")));
  +        activity.addStep(new SuspendStep("02"));
  +        activity.addStep(new StringStep("03", "New String Value"));
  +        InvokeStep step04 =
  +            new InvokeStep("04", "setStringProperty",
  +                           new BaseDescriptor("bean"));
  +        step04.addDescriptor(new BaseDescriptor()); // Consume top of stack
  +        activity.addStep(step04);
  +        activity.addStep(new SuspendStep("04"));
  +        activity.addStep(new InvokeStep("05", "getStringProperty",
  +                                        new BaseDescriptor("bean")));
  +        activity.addStep(new SuspendStep("06"));
  +
  +        // Execute the activity and validate results #1
  +        try {
  +            context.execute();
  +            assertTrue("Context is suspended",
  +                       context.getSuspend());
  +            assertTrue("Stack is not empty",
  +                       !context.isEmpty());
  +            Object top = context.pop();
  +            assertTrue("Stack is empty",
  +                       context.isEmpty());
  +            assertTrue("getStringProperty() returned a String",
  +                       top instanceof String);
  +            assertEquals("getStringProperty() old value",
  +                         bean.getStringProperty(), (String) top);
  +        } catch (StepException e) {
  +            e.printStackTrace(System.out);
  +            if (e.getCause() != null) {
  +                System.out.println("ROOT CAUSE");
  +                e.getCause().printStackTrace(System.out);
  +            }
  +            fail("Threw StepException " + e);
  +        } catch (Throwable e) {
  +            e.printStackTrace();
  +            fail("Threw exception " + e);
  +        }
  +
  +        // Execute the activity and validate results #2
  +        try {
  +            context.execute();
  +            assertTrue("Context is suspended",
  +                       context.getSuspend());
  +            assertTrue("Stack is empty",
  +                       context.isEmpty());
  +        } catch (StepException e) {
  +            e.printStackTrace(System.out);
  +            if (e.getCause() != null) {
  +                System.out.println("ROOT CAUSE");
  +                e.getCause().printStackTrace(System.out);
  +            }
  +            fail("Threw StepException " + e);
  +        } catch (Throwable e) {
  +            e.printStackTrace();
  +            fail("Threw exception " + e);
  +        }
  +
  +        // Execute the activity and validate results #3
  +        try {
  +            context.execute();
  +            assertTrue("Context is suspended",
  +                       context.getSuspend());
  +            assertTrue("Stack is not empty",
  +                       !context.isEmpty());
  +            Object top = context.pop();
  +            assertTrue("Stack is empty",
  +                       context.isEmpty());
  +            assertTrue("getStringProperty() returned a String",
  +                       top instanceof String);
  +            assertEquals("getStringProperty() new value",
  +                         bean.getStringProperty(), (String) top);
           } catch (StepException e) {
               e.printStackTrace(System.out);
               if (e.getCause() != null) {
  
  
  

Reply via email to