Package org.jbpm.graph.node

Source Code of org.jbpm.graph.node.TaskNode

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.graph.node;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.dom4j.Element;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.taskmgmt.def.Task;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.jbpm.taskmgmt.exe.TaskMgmtInstance;

/**
* is a node that relates to one or more tasks.
* Property <code>signal</code> specifies how task completion
* triggers continuation of execution.
*/
public class TaskNode extends Node {

  private static final long serialVersionUID = 1L;

  /**
   * execution always continues, regardless whether tasks are created or still unfinished.
   */
  public static final int SIGNAL_UNSYNCHRONIZED = 0;
  /**
   * execution never continues, regardless whether tasks are created or still unfinished.
   */
  public static final int SIGNAL_NEVER = 1;
  /**
   * proceeds execution when the first task instance is completed.  
   * when no tasks are created on entrance of this node, execution is continued.  
   */
  public static final int SIGNAL_FIRST = 2;
  /**
   * proceeds execution when the first task instance is completed.  
   * when no tasks are created on entrance of this node, execution waits in the task node till tasks are created.  
   */
  public static final int SIGNAL_FIRST_WAIT = 3;
  /**
   * proceeds execution when the last task instance is completed.
   * when no tasks are created on entrance of this node, execution is continued.
   */
  public static final int SIGNAL_LAST = 4;
  /**
   * proceeds execution when the last task instance is completed.
   * when no tasks are created on entrance of this node, execution waits in the task node till tasks are created.  
   */
  public static final int SIGNAL_LAST_WAIT = 5;
 
  public static int parseSignal(String text) {
    if ("unsynchronized".equalsIgnoreCase(text)) {
      return SIGNAL_UNSYNCHRONIZED;
    } else if ("never".equalsIgnoreCase(text)) {
      return SIGNAL_NEVER;
    } else if ("first".equalsIgnoreCase(text)) {
      return SIGNAL_FIRST;
    } else if ("first-wait".equalsIgnoreCase(text)) {
      return SIGNAL_FIRST_WAIT;
    } else if ("last-wait".equalsIgnoreCase(text)) {
      return SIGNAL_LAST_WAIT;
    } else { // return default
      return SIGNAL_LAST;
    }
  }
 
  public static String signalToString(int signal) {
    if (signal==SIGNAL_UNSYNCHRONIZED) {
      return "unsynchronized";
    } else if (signal==SIGNAL_NEVER) {
      return "never";
    } else if (signal==SIGNAL_FIRST) {
      return "first";
    } else if (signal==SIGNAL_FIRST_WAIT) {
      return "first-wait";
    } else if (signal==SIGNAL_LAST) {
      return "last";
    } else if (signal==SIGNAL_LAST_WAIT) {
      return "last-wait";
    } else {
      return null;
    }
  }
 
  Set<Task> tasks = null;
  int signal = SIGNAL_LAST;
  boolean createTasks = true;
  boolean endTasks = false;
 
  public TaskNode() {
  }

  public TaskNode(String name) {
    super(name);
  }

  @Override
  public NodeType getNodeType()
  {
    return NodeType.Task;
  }

  @Override
  public void read(Element element, JpdlXmlReader jpdlReader) {
    // get the signal
    String signalText = element.attributeValue("signal");
    if (signalText!=null) {
      signal = parseSignal(signalText);
    }

    // create tasks
    String createTasksText = element.attributeValue("create-tasks");
    if (createTasksText!=null) {
      if (("no".equalsIgnoreCase(createTasksText))
           || ("false".equalsIgnoreCase(createTasksText)) ) {
        createTasks = false;
      }
    }
   
    // create tasks
    String removeTasksText = element.attributeValue("end-tasks");
    if (removeTasksText!=null) {
      if (("yes".equalsIgnoreCase(removeTasksText))
           || ("true".equalsIgnoreCase(removeTasksText)) ) {
        endTasks = true;
      }
    }
   
    // parse the tasks
    jpdlReader.readTasks(element, this);
  }

  public void addTask(Task task) {
    if (tasks==null) tasks = new HashSet<Task>();
    tasks.add(task);
    task.setTaskNode(this);
  }

  // node behaviour methods
  /////////////////////////////////////////////////////////////////////////////
 
  public void execute(ExecutionContext executionContext) {
   
    TaskMgmtInstance tmi = getTaskMgmtInstance(executionContext.getToken());
   
    // if this tasknode should create instances
    if ( (createTasks)
         && (tasks!=null) ) {
      for (Task task : tasks) {
        executionContext.setTask(task);
        if (evaluateTaskCondition(task.getCondition(), executionContext)) {
          tmi.createTaskInstance(task, executionContext);
        }       
      }
    }

    // check if we should continue execution
    boolean continueExecution;
    switch (signal) {
      case SIGNAL_UNSYNCHRONIZED:
        continueExecution = true;
        break;
      case SIGNAL_FIRST:
      case SIGNAL_LAST:
        continueExecution = tmi.getSignallingTasks(executionContext).isEmpty();
        break;
      default:
        continueExecution = false;
    }

    if (continueExecution) {
      leave(executionContext);
    }
  }
 
  boolean evaluateTaskCondition(String condition, ExecutionContext executionContext) {
    if (condition==null) return true;
    Object result = JbpmExpressionEvaluator.evaluate(condition, executionContext);
    if (Boolean.TRUE.equals(result)) {
      return true;
    }
    return false;
  }

  public void leave(ExecutionContext executionContext, Transition transition) {
    TaskMgmtInstance tmi = getTaskMgmtInstance(executionContext.getToken());
    if (tmi.hasBlockingTaskInstances(executionContext.getToken()) ) {
      throw new IllegalStateException("task-node '"+name+"' still has blocking tasks");
    }
    removeTaskInstanceSynchronization(executionContext.getToken());
    super.leave(executionContext, transition);
  }
 
  // task behaviour methods
  /////////////////////////////////////////////////////////////////////////////

  public boolean completionTriggersSignal(TaskInstance taskInstance) {
    boolean completionTriggersSignal;
    switch (signal) {
    case SIGNAL_FIRST:
    case SIGNAL_FIRST_WAIT:
      completionTriggersSignal = true;
      break;
    case SIGNAL_LAST:
    case SIGNAL_LAST_WAIT:
      completionTriggersSignal = isLastToComplete(taskInstance);
      break;
    default:
      completionTriggersSignal = false;
    }
    return completionTriggersSignal;
  }

  boolean isLastToComplete(TaskInstance taskInstance) {
    Token token = taskInstance.getToken();
    TaskMgmtInstance tmi = getTaskMgmtInstance(token);
   
    boolean isLastToComplete = true;
    for (TaskInstance other : tmi.getTaskInstances()) {
      if ( (token!=null)
          && (token.equals(other.getToken()))
          && (! other.equals(taskInstance))
          && (other.isSignalling())
          && (!other.hasEnded())
      ) {
        isLastToComplete = false;
        break;
      }     
    }
   
    return isLastToComplete;
  }

  public void removeTaskInstanceSynchronization(Token token) {
    TaskMgmtInstance tmi = getTaskMgmtInstance(token);
    Collection<TaskInstance> taskInstances = tmi.getTaskInstances();
    if (taskInstances!=null) {
      for (TaskInstance taskInstance : taskInstances) {
        if (token.equals(taskInstance.getToken())) {
          // remove signalling
          if (taskInstance.isSignalling()) {
            taskInstance.setSignalling(false);
          }
          // remove blocking
          if (taskInstance.isBlocking()) {
            taskInstance.setBlocking(false);
          }
          // if this is a non-finished task and all those
          // tasks should be finished
          if ( (! taskInstance.hasEnded())
              && (endTasks)
          ) {
            if (tasks.contains(taskInstance.getTask())) {
              // end this task
              taskInstance.end();
            }
          }
        }
      }
    }
  }

  TaskMgmtInstance getTaskMgmtInstance(Token token) {
    return token.getProcessInstance().getTaskMgmtInstance();
  }

  // getters and setters
  /////////////////////////////////////////////////////////////////////////////

  /**
   * is a Map with the tasks, keyed by task-name or an empty map in case
   * no tasks are present in this task-node.
   */
  public Map<String, Task> getTasksMap() {
    Map<String, Task> tasksMap = new HashMap<String, Task>();
    if (tasks!=null) {
      for (Task task : tasks) {
        tasksMap.put(task.getName(), task);
      }
    }
    return tasksMap;
  }
 
  /**
   * is the task in this task-node with the given name or null if the given task
   * does not exist in this node.
   */
  public Task getTask(String taskName) {
    return getTasksMap().get(taskName);
  }

  public Set<Task> getTasks() {
    return tasks;
  }
  public int getSignal() {
    return signal;
  }
  public boolean getCreateTasks() {
    return createTasks;
  }
  public boolean isEndTasks() {
    return endTasks;
  }
  public void setCreateTasks(boolean createTasks) {
    this.createTasks = createTasks;
  }
  public void setEndTasks(boolean endTasks) {
    this.endTasks = endTasks;
  }
  public void setSignal(int signal) {
    this.signal = signal;
  }
  public void setTasks(Set<Task> tasks) {
    this.tasks = tasks;
  }
}
TOP

Related Classes of org.jbpm.graph.node.TaskNode

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.