Package org.springmodules.workflow.osworkflow

Source Code of org.springmodules.workflow.osworkflow.OsWorkflowTemplate

/*
* Copyright 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springmodules.workflow.osworkflow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;

import com.opensymphony.module.propertyset.PropertySet;

import com.opensymphony.workflow.Workflow;
import com.opensymphony.workflow.WorkflowException;
import com.opensymphony.workflow.basic.BasicWorkflow;
import com.opensymphony.workflow.config.Configuration;
import com.opensymphony.workflow.config.DefaultConfiguration;
import com.opensymphony.workflow.loader.WorkflowDescriptor;
import com.opensymphony.workflow.query.WorkflowExpressionQuery;
import com.opensymphony.workflow.spi.Step;

/**
* Template class that simplifies interaction with the <a href="http://www.opensymphony.com/osworkflow">OSWorkflow</a>
* workflow engine by hiding the management of context parameters such as the caller and workflow ID.
* <p/>
* Translates all checked <code>com.opensymphony.workflow.WorkflowException</code>s into unchecked
* <code>org.springmodules.workflow.WorkflowException</code>s.
* <p/>
* Most operations on the <code>Workflow</code> instance are mirrored here, but for operations that require
* lengthy interaction with a <code>Workflow</code> a custom <code>OsWorkflowCallback</code> can be used in conjunction
* with the <code>execute(OsWorkflowCallback)</code> method.
* <p/>
* It is intended that a single <code>OsWorkflowTemplate</code> will be used to manage all instances of a single workflow
* within your application. Because of this, the workflow name is not a parameter on any of operations exposed by this
* class. Instead, the workflow name is set via the required <code>workflowName</code> property. The same workflow name
* is used for all operations.
* <p/>
* Workflow context parameters such as the caller name and current instance ID are stored in an <code>OsWorkflowContext</code>
* which is bound to the current thread using the <code>OsWorkflowContextHolder</code>. It is intended that context
* information be set externally to the core application code. For this purpose, Spring Modules provides the
* <code>AbstractWorkflowContextHandlerInterceptor</code> (and its implementations) which allows for context information
* to be managed transparently in a web environment.
* <p/>
* Both the <code>workflowName</code> and <code>contextManager</code> parameters are required.
* <p/>
*
* @author Rob Harrop
* @see WorkflowException
* @see org.springmodules.workflow.WorkflowException
* @see #execute(OsWorkflowCallback)
* @see OsWorkflowContext
* @see OsWorkflowContextHolder
* @see org.springmodules.workflow.osworkflow.web.AbstractWorkflowContextHandlerInterceptor
* @see #setWorkflowName(String)
* @since 0.2
*/
public class OsWorkflowTemplate implements InitializingBean {

  /**
   * The <code>Configuration</code> used to load workflow definitions. Uses the OSWorkflow <code>DefaultConfiguration</code>
   * class by default.
   */
  private Configuration configuration = new DefaultConfiguration();

  /**
   * The ID of the initial action to call when initializing a workflow instance. Defaults to <code>0</code>.
   */
  private Integer initialAction = new Integer(0);

  /**
   * The name of the workflow definition to use.
   */
  private String workflowName;

  /**
   * Sets the <code>Configuration<code> used to load workflow definitions.
   */
  public void setConfiguration(Configuration configuration) {
    this.configuration = configuration;
  }

  /**
   * Sets the inital action used when initializing a workflow instance.
   */
  public void setInitialAction(Integer initialAction) {
    this.initialAction = initialAction;
  }

  /**
   * Sets the name of the workflow definition to use. Required.
   */
  public void setWorkflowName(String workflowName) {
    this.workflowName = workflowName;
  }

  /**
   * Gets the workflow name.
   */
  public String getWorkflowName() {
    return this.workflowName;
  }

  /**
   * Checks that both the <code>workflowName</code> and <code>contextManager</code> properties have both been specified.
   *
   * @throws FatalBeanException if any of the required properties is not set.
   */
  public void afterPropertiesSet() throws Exception {
    if (!StringUtils.hasText(this.workflowName)) {
      throw new FatalBeanException("Property [workflowName] is required.");
    }
  }

  /**
   * Initialize a workflow instance using the default initial action.
   *
   * @see #setInitialAction(Integer)
   * @see #initialize(int, java.util.Map)
   */
  public void initialize() {
    this.initialize(this.initialAction.intValue(), null);
  }

  /**
   * Initialize a workflow instance using the default initial action and the supplied inputs.
   *
   * @see #setInitialAction(Integer)
   * @see #initialize(int, java.util.Map)
   */
  public void initialize(final Map inputs) {
    this.initialize(this.initialAction.intValue(), inputs);
  }

  /**
   * Initialize a workflow instance using the supplied inital action.
   *
   * @see #initialize(int, java.util.Map)
   */
  public void initialize(final int initialAction) {
    this.initialize(initialAction, null);
  }

  /**
   * Initialize a workflow instance using the supplied initial action and inputs. The caller's identity is retreived
   * from the <code>WorkflowContextManager</code>. The resulting workflow instance ID is stored using the
   * <code>WorkflowContextManager</code>.
   *
   * @see OsWorkflowContext#getCaller()
   * @see OsWorkflowContext#setInstanceId(long)
   */
  public void initialize(final int initialAction, final Map inputs) {
    this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        long id = workflow.initialize(OsWorkflowTemplate.this.workflowName, initialAction, inputs);
        bindInstanceIdToWorkflowContext(id);
        return null;
      }
    });
  }

  /**
   * Do the workflow action specified by the given action ID.
   *
   * @see #doAction(int, java.util.Map)
   */
  public void doAction(final int actionId) {
    this.doAction(actionId, null);
  }

  /**
   * Do the workflow action specified by the given action ID. Passes in a single input under the specified key.
   *
   * @param actionId the ID of the action to execute
   * @param inputKey the key of the input
   * @param inputVal the value of the input
   * @see #doAction(int, java.util.Map)
   */
  public void doAction(final int actionId, Object inputKey, Object inputVal) {
    Map inputs = new HashMap();
    inputs.put(inputKey, inputVal);
    this.doAction(actionId, inputs);
  }

  /**
   * Do the workflow action specified by the given action ID passing in the supplied inputs. The workflow instance ID
   * to execute the action against is retreived from the <code>WorkflowContextManager</code>.
   *
   * @see OsWorkflowContext#getInstanceId()
   */
  public void doAction(final int actionId, final Map inputs) {
    this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        workflow.doAction(getInstanceId(), actionId, inputs);
        return null;
      }
    });
  }

  /**
   * Gets the <code>WorkflowDescriptor</code> for the configured workflow.
   *
   * @see #getWorkflowName()
   * @see #setWorkflowName(String)
   */
  public WorkflowDescriptor getWorkflowDescriptor() {
    return (WorkflowDescriptor) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.getWorkflowDescriptor(OsWorkflowTemplate.this.workflowName);
      }
    });
  }

  /**
   * Gets the <code>List</code> of history <code>Step</code>s for the current workflow instance.
   */
  public List getHistorySteps() {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.getHistorySteps(getInstanceId());
      }
    });
  }

  /**
   * Gets the <code>List</code> of current <code>Step</code>s for the current workflow instance.
   */
  public List getCurrentSteps() {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.getCurrentSteps(getInstanceId());
      }
    });
  }

  /**
   * Gets the <code>List</code> of history <code>StepDescriptor</code>s for the current workflow instance.
   */
  public List getHistoryStepDescriptors() {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        List steps = workflow.getHistorySteps(getInstanceId());
        return convertStepsToStepDescriptors(steps, workflow);
      }
    });
  }

  /**
   * Gets the <code>List</code> of current <code>StepDescriptor</code>s for the current workflow instance.
   */
  public List getCurrentStepDescriptors() {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        List steps = workflow.getCurrentSteps(getInstanceId());
        return convertStepsToStepDescriptors(steps, workflow);
      }
    });
  }

  /**
   * Gets the IDs of actions available to the caller on the current workflow instance.
   */
  public int[] getAvailableActions() {
    return this.getAvailableActions(null);
  }

  /**
   * Gets the IDs of actions available to the caller that match the supplied inputs on the current workflow instance.
   */
  public int[] getAvailableActions(final Map inputs) {
    return (int[]) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.getAvailableActions(getInstanceId(), inputs);
      }
    });
  }

  /**
   * Gets a <code>List</code> of the <code>ActionDescriptor</code>s available to the caller on the current workflow instance.
   */
  public List getAvailableActionDescriptors() {
    return this.getAvailableActionDescriptors(null);
  }

  /**
   * Gets a <code>List</code> of the <code>ActionDescriptor</code>s available to the caller that match the supplied
   * inputs on the current workflow instance.
   */
  public List getAvailableActionDescriptors(final Map inputs) {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        WorkflowDescriptor descriptor = workflow.getWorkflowDescriptor(OsWorkflowTemplate.this.workflowName);

        int[] availableActions = workflow.getAvailableActions(getInstanceId(), inputs);
        List actionDescriptors = new ArrayList(availableActions.length);

        for (int i = 0; i < availableActions.length; i++) {
          actionDescriptors.add(descriptor.getAction(availableActions[i]));
        }

        return actionDescriptors;
      }
    });
  }

  /**
   * Gets the entry state for the current workflow instance.
   */
  public int getEntryState() {
    Integer state = (Integer) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return new Integer(workflow.getEntryState(getInstanceId()));
      }
    });

    return state.intValue();
  }

  /**
   * Gets the <code>PropertySet</code> for the current workflow instance.
   *
   * @return
   */
  public PropertySet getPropertySet() {
    return (PropertySet) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.getPropertySet(getInstanceId());
      }
    });
  }

  /**
   * Returns <code>true</code> if the configured workflow can be configured with the supplied initial step.
   *
   * @see #setWorkflowName(String)
   * @see #getWorkflowName()
   */
  public boolean canInitialize(final int initialStep) {
    return this.canInitialize(initialStep, null);
  }

  /**
   * Returns <code>true</code> if the configured workflow can be configured with the supplied initial step and inputs.
   *
   * @see #setWorkflowName(String)
   * @see #getWorkflowName()
   */
  public boolean canInitialize(final int initialStep, final Map inputs) {
    Boolean returnValue = (Boolean) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        boolean canInit = workflow.canInitialize(OsWorkflowTemplate.this.workflowName, initialStep,
            inputs);
        return (canInit) ? Boolean.TRUE : Boolean.FALSE;
      }
    });
    return returnValue.booleanValue();
  }

  /**
   * Returns <code>true</code> if the entry state of the current workflow can be modified to the supplied state.
   *
   * @see #changeEntryState(int)
   */
  public boolean canModifyEntryState(final int newState) {
    Boolean returnValue = (Boolean) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        boolean canModify = workflow.canModifyEntryState(getInstanceId(), newState);
        return (canModify) ? Boolean.TRUE : Boolean.FALSE;
      }
    });

    return returnValue.booleanValue();
  }

  /**
   * Changes the entry state of the current workflow to the supplied state.
   *
   * @see #canModifyEntryState(int)
   */
  public void changeEntryState(final int newState) {
    this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        workflow.changeEntryState(getInstanceId(), newState);
        return null;
      }
    });
  }

  /**
   * Executes the supplied <code>WorkflowExpressionQuery</code> and returns a <code>List</code> of IDs that match the
   * query criteria.
   *
   * @see com.opensymphony.workflow.query.WorkflowExpressionQuery
   * @see com.opensymphony.workflow.Workflow#query(com.opensymphony.workflow.query.WorkflowExpressionQuery)
   */
  public List query(final WorkflowExpressionQuery query) {
    return (List) this.execute(new OsWorkflowCallback() {
      public Object doWithWorkflow(Workflow workflow) throws WorkflowException {
        return workflow.query(query);
      }
    });
  }

  /**
   * Executes the supplied <code>OsWorkflowCallback</code> against the current workflow instance as the caller bound
   * to the current <code>OsWorkflowContext</code>.
   */
  public Object execute(OsWorkflowCallback callback) {
    try {
      Workflow workflow = createWorkflow(OsWorkflowContextHolder.getWorkflowContext().getCaller());
      workflow.setConfiguration(this.configuration);
      return callback.doWithWorkflow(workflow);
    }
    catch (WorkflowException ex) {
      // TODO: proper exception translation
      throw new org.springmodules.workflow.WorkflowException("", ex);
    }
  }

  /**
   * Creates a <code>Workflow</code> for the supplied caller. The method acts as a hook
   * for subclasses that want to change the way the workflow is created.
   */
  protected Workflow createWorkflow(String caller) throws WorkflowException {
    return new BasicWorkflow(caller);
  }

  /**
   * Binds the supplied instance ID to the current <code>OsWorkflowContext</code>.
   */
  protected void bindInstanceIdToWorkflowContext(long id) {
    OsWorkflowContextHolder.getWorkflowContext().setInstanceId(id);
  }

  /**
   * Retrieves the instance ID bound to the current <code>OsWorkflowContext</code>.
   */
  protected long getInstanceId() {
    return OsWorkflowContextHolder.getWorkflowContext().getInstanceId();
  }

  /**
   * Converts a <code>List</code> of <code>Step</code>s to a <code>List</code> of <code>StepDescriptor</code>s.
   */
  private List convertStepsToStepDescriptors(List steps, Workflow workflow) {
    WorkflowDescriptor descriptor = workflow.getWorkflowDescriptor(OsWorkflowTemplate.this.workflowName);

    List stepDescriptors = new ArrayList();

    for (int i = 0; i < steps.size(); i++) {
      Step step = (Step) steps.get(i);
      stepDescriptors.add(descriptor.getStep(step.getStepId()));
    }

    return Collections.unmodifiableList(stepDescriptors);
  }
}
TOP

Related Classes of org.springmodules.workflow.osworkflow.OsWorkflowTemplate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.