All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.bonita.definition.activity.AbstractActivity Maven / Gradle / Ivy

/**
 * Copyright (C) 2007  Bull S. A. S.
 * Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois
 * This library 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
 * version 2.1 of the License.
 * This library 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
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA  02110-1301, USA.
 **/
package org.ow2.bonita.definition.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.ow2.bonita.definition.ActivityType;
import org.ow2.bonita.definition.ClassInfo;
import org.ow2.bonita.definition.JavaHook;
import org.ow2.bonita.definition.MultiInstantiator;
import org.ow2.bonita.definition.MultiInstantiatorDescriptor;
import org.ow2.bonita.definition.Performer;
import org.ow2.bonita.facade.exception.BonitaWrapperException;
import org.ow2.bonita.facade.exception.MultiInstantiatorInvocationException;
import org.ow2.bonita.facade.runtime.ActivityState;
import org.ow2.bonita.facade.runtime.InstanceState;
import org.ow2.bonita.pvm.Execution;
import org.ow2.bonita.pvm.activity.ActivityExecution;
import org.ow2.bonita.pvm.activity.ExternalActivity;
import org.ow2.bonita.pvm.internal.env.Authentication;
import org.ow2.bonita.pvm.internal.model.NodeImpl;
import org.ow2.bonita.pvm.internal.model.TransitionImpl;
import org.ow2.bonita.pvm.internal.model.VariableDefinitionImpl;
import org.ow2.bonita.pvm.model.Condition;
import org.ow2.bonita.pvm.model.Node;
import org.ow2.bonita.pvm.model.OpenExecution;
import org.ow2.bonita.pvm.model.Transition;
import org.ow2.bonita.runtime.ClassDataLoader;
import org.ow2.bonita.runtime.TransitionStatus;
import org.ow2.bonita.runtime.XpdlExecution;
import org.ow2.bonita.runtime.XpdlInstance;
import org.ow2.bonita.runtime.TransitionStatus.TransitionState;
import org.ow2.bonita.services.Recorder;
import org.ow2.bonita.services.info.ActivityInstanceCurrentInfo;
import org.ow2.bonita.services.util.ServiceEnvTool;
import org.ow2.bonita.util.BonitaConstants;
import org.ow2.bonita.util.BonitaRuntimeException;
import org.ow2.bonita.util.EngineEnvTool;
import org.ow2.bonita.util.Misc;

/**
 * @author Marc Blachon, Guillaume Porcher, Charles Souillard, Miguel Valdes, Pierre Vigneras, Pascal Verdage
 */
/**
 * Activity life cycle:
 * 1- when an instance is created, activity state is {@link ActivityState#INITIAL}
 * 2- when the execution arrives on the node, the activity becomes {@link ActivityState#READY}
 *  the activity state is recorded (before start)
 * 3- if the activity is Manual, a task is created.
 * - when the start task is started, the activity state is recorded (after start).
 * 4- the activity becomes {@link ActivityState#EXECUTING}. The business logic is executed.
 * - the activity state is recorded (before stopped)
 * 5- if the activity is Manual, wait for the task to finish. (TODO: change the activity state ?)
 * - when the task is finished, the activity state is recorded (after stopped).
 * 6- the activity becomes {@link ActivityState#FINISHED}.
 */
public abstract class AbstractActivity implements ExternalActivity {

  /**
   *
   */
  private static final long serialVersionUID = -2731157748250833266L;


  public static enum SplitType {
    AND, XOR
  }

  public static enum JoinType {
    AND, XOR
  }

  /** LOG */
  private static final Logger LOG = Logger.getLogger(AbstractActivity.class.getName());
  protected long dbid;

  protected String activityId;
  protected SplitType splitType;
  protected JoinType joinType;

  protected ActivityType activityType;
  protected List variableDefinitions;
  protected Performer performer;

  protected Set deadlines;

  protected List javaHooks;
  // multi instantiation
  protected ClassInfo multiInstantiationClass;
  protected String multiInstantiationVariable;

  // iterations
  protected List  iterationDescriptors;


  public static final String BODY_FINISHED = "bodyFinished";
  public static final String ACT_INSTANCE_FINISHED = "instFinished";


  protected AbstractActivity() {
  }

  protected AbstractActivity(final String activityName, final JoinType joinType,
      final SplitType splitType,
      final ActivityType activityType,
      final Performer performer) {

    Misc.checkArgsNotNull(activityType);
    this.activityId = activityName;
    this.joinType = joinType;
    this.splitType = splitType;
    this.activityType = activityType;
    this.performer = performer;

    if (performer != null) {
      if (!ActivityType.task.equals(activityType)) {
        throw new BonitaRuntimeException("Activity is automatic and a performer is specified: incorrect.");
      }
    } else {
      if (ActivityType.task.equals(activityType)) {
        throw new BonitaRuntimeException("startMode or finishMode is Manual and no performer is specified: incorrect.");
      }
    }
  }

  public void execute(final ActivityExecution execution) {
    XpdlExecution xpdlExecution = (XpdlExecution) execution;
    if (xpdlExecution.getNode().isExecutionAsync()) {
      Authentication.setUserId(BonitaConstants.SYSTEM_USER);
    }
    // If instance is ended, don't execute next node.
    if (xpdlExecution.getXpdlInstance().getInstanceState().equals(InstanceState.FINISHED)) {
      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("XPDLInstance ended : " + xpdlExecution.getXpdlInstance());
      }
      xpdlExecution.end();
      final XpdlExecution parent = xpdlExecution.getParent();
      if (parent != null) {
        parent.removeExecution(xpdlExecution);
      }
      return;
    }
    // Execute node.
    boolean joinOK = true;
    joinOK = this.executeJoin(xpdlExecution);
    if (joinOK) {
      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("Join for activity " + this + " is OK.");
      }
      if (this.joinType.equals(JoinType.XOR)) {
        AbstractActivity.cancelJoinXORIncomingTransitions(xpdlExecution);
      }
      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("Creating a new iteration on activity : " + this);
      }
      this.createNewIteration(xpdlExecution);

      final String nodeName = execution.getNode().getName();

      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("Executing node: " + nodeName + ", class = " + this.getClass().getSimpleName());
      }

      if (this.multiInstantiationClass != null) {
        if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
          AbstractActivity.LOG.fine("MultiInstantiation not null on activity " + this);
        }
        MultiInstantiatorDescriptor actInstDescr = null;

        final MultiInstantiator actInstantiator =
          ClassDataLoader.getInstance(MultiInstantiator.class,
              xpdlExecution.getXpdlInstance().getPackageDefinitionUUID(), this.multiInstantiationClass);
        try {
          actInstDescr = EngineEnvTool.getHookExecutor()
            .executeMultiInstantiator(xpdlExecution, this.activityId, actInstantiator);
          if (actInstDescr == null) {
            throw new BonitaRuntimeException("MultiInstantiator execution returned null in activity " + this.activityId);
          }
        } catch (final Exception e) {
          throw new BonitaWrapperException(
              new MultiInstantiatorInvocationException(this.multiInstantiationClass.toString(), e)
          );
        }

        xpdlExecution.setWaitingForActivityInstanceNb(actInstDescr.getJoinNumber());
        int childId = 0;
        for (final Object value : actInstDescr.getVariableValues()) {
          XpdlExecution childExec = this.createChildExecution(xpdlExecution, childId);
          childExec = (XpdlExecution) childExec.createScope(xpdlExecution.getNode());
          // TODO check if values are compatibles with variable type
          childExec.setVariable(this.multiInstantiationVariable, value);
          childExec.setActivityInstanceId(Integer.toString(childId));
          this.executeActivityInstance(childExec);
          childId++;
        }
      } else {
        xpdlExecution = (XpdlExecution) xpdlExecution.createScope(xpdlExecution.getNode());
        this.executeActivityInstance(xpdlExecution);
      }
    } else {
      xpdlExecution.end();
      final XpdlExecution parent = xpdlExecution.getParent();
      if (parent != null) {
        parent.removeExecution(xpdlExecution);
      }
    }
  }

  /**
   * @param execution
   */
  private static void cancelJoinXORIncomingTransitions(final XpdlExecution execution) {
    final NodeImpl currentNode = execution.getNode();
    final XpdlInstance instance = execution.getXpdlInstance();
    AbstractActivity.cancelJoinXORIncomingTransitions(instance, currentNode, currentNode.getName());
    for (final Transition t : currentNode.getIncomingTransitions()) {
      instance.setTransitionState(t, TransitionState.ABORTED);
    }
  }

  private static void cancelJoinXORIncomingTransitions(final XpdlInstance instance, final NodeImpl currentNode, final String initialNode) {
    final List incomingTransitions = currentNode.getIncomingTransitions();
    final String currentNodeName = currentNode.getName();
    if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
      AbstractActivity.LOG.fine("Canceling other branches of the join XOR : " + currentNodeName);
    }
    for (final Transition incomingTransition : incomingTransitions) {
      final NodeImpl sourceNode = (NodeImpl) incomingTransition.getSource();
      final String sourceNodeName = sourceNode.getName();
      if (!sourceNodeName.equals(initialNode)
          && instance.getTransitionStatus(incomingTransition).getState().equals(TransitionState.READY)) {
        // disable transition
        instance.setTransitionState(incomingTransition, TransitionState.ABORTED);
        // check if source node is still enabled
        // it is still enabled if it has an enabled outgoing transition (in the same cycle if in a cycle)
        boolean enable = false;
        for (final Transition tr : sourceNode.getOutgoingTransitions()) {
          if (instance.getTransitionStatus(tr).getState().equals(TransitionState.READY)) {
            final AbstractActivity currentActivity = (AbstractActivity) currentNode.getBehaviour();
            final List itDescs = currentActivity.getIterationDescriptors();
            if (itDescs != null && !itDescs.isEmpty()) {
              for (final IterationDescriptor itDesc : itDescs) {
                if (itDesc.containsNode(tr.getDestination())) {
                  // stay in same cycle => do not disable node
                  enable = true;
                }
              }
            } else {
              // no cycles -> do not disable node
              enable = true;
            }
          }
        }
        if (!enable) {
          // abort sourceNode recursively
          if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
            AbstractActivity.LOG.fine(sourceNodeName + " has no more outgoing transitions enabled.");
          }
          final List execToAbortList = instance.getExecOnNode(sourceNodeName);
          for (final XpdlExecution execToAbort : execToAbortList) {
            if (execToAbort.isActive()) {
              execToAbort.abort();
            }
          }
          AbstractActivity.cancelJoinXORIncomingTransitions(instance, sourceNode, initialNode);
        }
      }
    }
  }


  protected void executeActivityInstance(final XpdlExecution xpdlExecution) {
    xpdlExecution.setCurrentActivityInstanceUUID(
        ServiceEnvTool.getUUIDGenerator().
        getActivityInstanceUUID(xpdlExecution.getXpdlInstance().getUUID(), this.activityId));

    final Recorder recorder = ServiceEnvTool.getRecorder();
    final XpdlInstance xpdlInstance = xpdlExecution.getXpdlInstance();
    final ActivityInstanceCurrentInfo activityInstanceCurrentInfo = new ActivityInstanceCurrentInfo(
        xpdlInstance.getPackageDefinitionUUID(),
        xpdlInstance.getProcessDefinitionUUID(),
        xpdlInstance.getUUID(),
        xpdlExecution.getCurrentActivityInstanceUUID(),
        this.getActivityType(),
        this.getActivityId(),
        xpdlExecution.getIterationId(),
        xpdlExecution.getActivityInstanceId(),
        xpdlExecution.getScopeVariables());
    recorder.recordEnterActivity(activityInstanceCurrentInfo);


    final boolean canContinue = this.executeBody(xpdlExecution);
    if (canContinue) {
      this.end(xpdlExecution);
    } else {
      xpdlExecution.waitForSignal();
    }
  }

  protected void end(final XpdlExecution xpdlExecution) {
    final ActivityInstanceCurrentInfo activityInstanceCurrentInfo = new ActivityInstanceCurrentInfo(
        xpdlExecution.getXpdlInstance().getPackageDefinitionUUID(),
        xpdlExecution.getXpdlInstance().getProcessDefinitionUUID(),
        xpdlExecution.getXpdlInstance().getUUID(),
        xpdlExecution.getCurrentActivityInstanceUUID(),
        this.getActivityType(),
        this.getActivityId(),
        xpdlExecution.getIterationId(),
        xpdlExecution.getActivityInstanceId(),
        xpdlExecution.getScopeVariables());

    ServiceEnvTool.getRecorder().recordBodyEnded(activityInstanceCurrentInfo);

    if (!XpdlExecution.MAIN_INSTANCE_NAME.equals(xpdlExecution.getActivityInstanceId())) {
      final XpdlExecution activityInstanceExecution = (XpdlExecution) xpdlExecution.destroyScope(xpdlExecution.getNode());
      activityInstanceExecution.end();
      final XpdlExecution parent = activityInstanceExecution.getParent();
      parent.removeExecution(activityInstanceExecution);
      this.signal(parent, AbstractActivity.ACT_INSTANCE_FINISHED, null);
    } else {
      this.executeSplit(xpdlExecution, true);
    }
  }

  public void signal(final ActivityExecution execution, final String signal, final Map parameters) {
    final XpdlExecution xpdlExecution = (XpdlExecution) execution;
    if (AbstractActivity.BODY_FINISHED.equals(signal)) {
      this.end(xpdlExecution);
    } else if (AbstractActivity.ACT_INSTANCE_FINISHED.equals(signal)) {
      xpdlExecution.setWaitingForActivityInstanceNb(xpdlExecution.getWaitingForActivityInstanceNb() - 1);
      if (xpdlExecution.getWaitingForActivityInstanceNb() == 0) {
        if (xpdlExecution.getExecutions() != null) {
          for (final OpenExecution execToAbort : new ArrayList(xpdlExecution.getExecutions())) {
            ((XpdlExecution) execToAbort).abort();
          }
        }
        this.executeSplit(xpdlExecution, false);
      }
    } else if (signal != null && this.deadlines != null) {
      for (final String deadline : this.deadlines) {
        if (deadline.equals(signal)) {
          Authentication.setUserId(BonitaConstants.SYSTEM_USER);
          // By default, a deadline does not propagate execution
          xpdlExecution.waitForSignal();
          final String activityId = xpdlExecution.getNode().getName();
          final JavaHook javaHook = new JavaHook(signal, JavaHook.Type.onDeadline, true);
          EngineEnvTool.getHookExecutor()
            .executeHook(xpdlExecution, activityId, javaHook);
          return;
        }
      }
    }
  }

  protected void executeSplit(final Execution execution, final boolean removeScope) {
    XpdlExecution xpdlExecution = (XpdlExecution) execution;
    final NodeImpl currentNode = xpdlExecution.getNode();
    if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
      AbstractActivity.LOG.fine("node = " + currentNode.getName() + " - splitType = "
          + this.splitType + " - execution = " + execution.getName());
    }
    final List transitions = currentNode.getOutgoingTransitions();
    if (transitions == null) {
      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("node = " + currentNode.getName() + " - splitType = "
            + this.splitType + " - execution = " + execution.getName() + " no transition available. Ending execution");
      }
      xpdlExecution.end();
      final XpdlExecution parent = xpdlExecution.getParent();
      if (parent != null) {
        parent.removeExecution(xpdlExecution);
      }
    } else {
      final List transitionsToTake = new ArrayList();
      for (final Transition t : transitions) {
        if (this.evaluateTransition((TransitionImpl) t, xpdlExecution)) {
          if (
            xpdlExecution
              .getXpdlInstance()
              .getTransitionStatus(t)
              .getState().equals(TransitionState.READY)
          ) {
            xpdlExecution.getXpdlInstance().setTransitionState(t, TransitionState.TAKEN);
            transitionsToTake.add(t);
          }
        }
      }
      // remove not propagated variables
      if (removeScope) {
        xpdlExecution = (XpdlExecution) xpdlExecution.destroyScope(currentNode);
      }
      xpdlExecution.setCurrentActivityInstanceUUID(null);
      if (transitionsToTake.size() == 0) {
        xpdlExecution.end();
        final XpdlExecution parent = xpdlExecution.getParent();
        if (parent != null) {
          parent.removeExecution(xpdlExecution);
        }
      } else {
        // check we are leaving a cycle
        if (this.iterationDescriptors != null && !this.iterationDescriptors.isEmpty()) {
          for (final IterationDescriptor itD : this.iterationDescriptors) {
            boolean isLeaving = false;
            for (final Transition t : transitionsToTake) {
              if (!itD.containsNode(t.getDestination())) {
                isLeaving = true;
              }
            }
            if (isLeaving) {
              // abort execution of other nodes.
              if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
                AbstractActivity.LOG.fine(this.activityId + " is leaving a cycle, aborting other nodes in cycle.");
              }
              for (final NodeInIterationDescriptor nodeToAbortDescr : itD.getCycleNodes()) {
                final NodeImpl nodeToAbort = nodeToAbortDescr.getNode();
                if (!nodeToAbort.equals(currentNode)) {
                  final List execToAbortList = xpdlExecution.getXpdlInstance().getExecOnNode(nodeToAbort.getName());
                  for (final XpdlExecution execToAbort : execToAbortList) {
                    if (execToAbort.isActive()) {
                      execToAbort.abort();
                    }
                  }
                }
              }
            }
          }
        }
        if (transitionsToTake.size() == 1  || this.splitType.equals(SplitType.XOR)) {
          // We are in a Split/AND and only one transition is true,
          // or we are in a Split/XOR, so we take the first one that is true.
          final Transition t = transitionsToTake.get(0);
          if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
            AbstractActivity.LOG.fine("Taking transition " + t);
          }
          xpdlExecution.take(t);
        } else {
          // We are in a Split/AND and more than one transition is true.
          // check we are not leaving a cycle and staying in the cycle at the same time
          if (this.iterationDescriptors != null && !this.iterationDescriptors.isEmpty()) {
            for (final IterationDescriptor itD : this.iterationDescriptors) {
              boolean isLeaving = false;
              boolean isStaying = false;
              for (final Transition t : transitionsToTake) {
                if (!itD.containsNode(t.getDestination())) {
                  isLeaving = true;
                } else {
                  isStaying = true;
                }
              }
              if (isStaying && isLeaving) {
                throw new BonitaWrapperException(new BonitaRuntimeException("Exception in iterations: an execution is leaving a cycle while the other is still in the cycle."));
              }
            }
          }
          final List children = new ArrayList();
          for (int i = 0; i < transitionsToTake.size(); i++) {
            final XpdlExecution childExecution = this.createChildExecution(xpdlExecution, i);
            final Transition t = transitionsToTake.get(i);
            childExecution.setNode((NodeImpl)t.getDestination());
            children.add(childExecution);
          }
          for (int i = 0; i < transitionsToTake.size(); i++) {
            final XpdlExecution childExecution = children.get(i);
            childExecution.setNode(currentNode);
            final Transition t = transitionsToTake.get(i);
            if (!childExecution.isFinished()) {
              if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
                AbstractActivity.LOG.fine("Execution " + childExecution.getName() + " is taking transition " + t);
              }
              childExecution.take(t);
            }
          }
        }
      }
    }
  }

  private boolean evaluateTransition(final TransitionImpl t, final XpdlExecution xpdlExecution) {
    // testing the guard condition
    final Condition condition = t.getCondition();
    final ConditionDefinition condDef = (ConditionDefinition) condition;
    boolean conditionOK = true;
    if (condDef != null) {
      conditionOK = condDef.evaluate(xpdlExecution);
      if (!conditionOK) {
        if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
          AbstractActivity.LOG.fine("Unable to take transition: " + t.getName());
        }
        // TODO : cancel nodes on this branch : may be investigate for cleaning of executions ?
      }
    }
    return conditionOK;
  }

  protected XpdlExecution createChildExecution(final XpdlExecution parentExecution, final int childId) {
    final String executionName = parentExecution.getName() + "/" + childId;
    final XpdlExecution childExecution = (XpdlExecution) parentExecution.createExecution(executionName);
    if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
      AbstractActivity.LOG.fine("Creating child execution with name " + childExecution.getName());
    }
    return childExecution;
  }

  protected boolean executeJoin(final XpdlExecution execution) {
    final Transition previousTransition = execution.getPreviousTransition();
    final String fromName = previousTransition.getSource().getName();
    final TransitionStatus fromTransition = execution.getXpdlInstance().getTransitionStatus(previousTransition);
    if (fromTransition.getState().equals(TransitionState.ARRIVED)) {
      throw new BonitaRuntimeException("transition " + fromName + "->" + this.activityId + " is already arrived in this Join.");
    }
    if (fromTransition.getState().equals(TransitionState.TAKEN)) {
      fromTransition.setState(TransitionState.ARRIVED);
    }
    return AbstractActivity.isJoinOk(execution.getXpdlInstance(), execution.getNode());
  }

  private static boolean isJoinOk(final XpdlInstance instance, final NodeImpl node) {
    if (!node.hasIncomingTransitions()) {
      return true;
    }
    if (((AbstractActivity) node.getBehaviour()).getJoinType().equals(JoinType.XOR)) {
      // join XOR
      for (final Transition transition : node.getIncomingTransitions()) {
        final TransitionStatus ts = instance.getTransitionStatus(transition);
        if (ts.getState().equals(TransitionState.ARRIVED)) {
          return true;
        }
      }
      return false;
    } else {
      // join AND
      for (final Transition transition : node.getIncomingTransitions()) {
        final TransitionStatus ts = instance.getTransitionStatus(transition);
        if (!ts.getState().equals(TransitionState.ARRIVED)) {
          return false;
        }
      }
      return true;
    }
  }

  /**
   * Describes how a node is involved in a cycle (simple node, entry point or exit point).
   * @author Guillaume Porcher
   *
   */
  public static class NodeInIterationDescriptor {
    private NodeImpl node;
    private boolean isEntryNode;
    private boolean isExitNode;

    protected NodeInIterationDescriptor() { }

    public NodeInIterationDescriptor(final NodeImpl node, final boolean isEntryNode, final boolean isExitNode) {
      this.node = node;
      this.isEntryNode = isEntryNode;
      this.isExitNode = isExitNode;
    }
    public NodeImpl getNode() {
      return this.node;
    }
    public boolean isEntryNode() {
      return this.isEntryNode;
    }
    public boolean isExitNode() {
      return this.isExitNode;
    }
  }

  /**
   * Describes a cycle.
   *
   * @author Guillaume Porcher
   *
   */
  public static class IterationDescriptor {
    /**
     * List of cycle nodes (descriptors)
     */
    private Set cycleNodes;

    protected IterationDescriptor() { }
    public IterationDescriptor(
        final Set cycleNodes) {
      this.cycleNodes = cycleNodes;
    }

    public Set getCycleNodes() {
      return this.cycleNodes;
    }

    /**
     *
     * @param node
     * @return true if the node is in his iteration
     */
    public boolean containsNode(final Node node) {
      return this.getNodeInIterationDescriptor(node) != null;
    }

    /**
     *
     * @param node
     * @return the node descriptor which describes the behavior of the node in this iteration.
     */
    public NodeInIterationDescriptor getNodeInIterationDescriptor(final Node node) {
      for (final NodeInIterationDescriptor nodeDesc : this.cycleNodes) {
        if (nodeDesc.getNode().equals(node)) {
          return nodeDesc;
        }
      }
      return null;
    }
  }

  public List getIterationDescriptors() {
    return this.iterationDescriptors;
  }

  public void setIterationDescriptors(final List iteration) {
    this.iterationDescriptors = iteration;
  }

  private void createNewIteration(final XpdlExecution execution) {
    if (this.iterationDescriptors != null && !this.iterationDescriptors.isEmpty()) {
      final String iterationUUID = Misc.getUniqueId("it");
      execution.setIterationId(iterationUUID);
      final XpdlInstance instance = execution.getXpdlInstance();
      for (final IterationDescriptor it : this.iterationDescriptors) {
        final NodeInIterationDescriptor nodeDescr = it.getNodeInIterationDescriptor(execution.getNode());
        if (nodeDescr != null && nodeDescr.isEntryNode()) {
          for (final NodeInIterationDescriptor joinNodeDescr : it.getCycleNodes()) {
            final NodeImpl joinNode = joinNodeDescr.getNode();
            for (final Transition tr : joinNode.getIncomingTransitions()) {
              if (it.containsNode(tr.getSource())) {
                instance.setTransitionState(tr, TransitionState.READY);
              }
            }
            if (AbstractActivity.isJoinOk(instance, joinNode)) {
              throw new BonitaRuntimeException("Error in iteration: join " + joinNode.getName() + " has not been reinitialized");
            }
          }
        }
      }
    }
  }

  private boolean executeBody(final XpdlExecution xpdlExecution) {
    if (this.bodyStartAutomatically()) {
      final ActivityInstanceCurrentInfo activityInstanceCurrentInfo = new ActivityInstanceCurrentInfo(
          xpdlExecution.getXpdlInstance().getPackageDefinitionUUID(),
          xpdlExecution.getXpdlInstance().getProcessDefinitionUUID(),
          xpdlExecution.getXpdlInstance().getUUID(),
          xpdlExecution.getCurrentActivityInstanceUUID(),
          this.getActivityType(),
          this.getActivityId(),
          xpdlExecution.getIterationId(),
          xpdlExecution.getActivityInstanceId(),
          xpdlExecution.getScopeVariables());

      ServiceEnvTool.getRecorder().recordBodyStarted(activityInstanceCurrentInfo);
    }
    return this.executeBusinessLogic(xpdlExecution);
  }

  //public abstract ActivityBody getBody(XpdlExecution xpdlExecution);

  /**
   * Return true if the execution can continue
   */
  protected abstract boolean executeBusinessLogic(Execution execution);
  protected abstract boolean bodyStartAutomatically();
  public List getVariableDefinitions() {
    return this.variableDefinitions;
  }

  public void setVariableDefinitions(
      final List variableDefinitions) {
    this.variableDefinitions = variableDefinitions;
  }


  public ActivityType getActivityType() {
    return this.activityType;
  }


  public Performer getPerformer() {
    return this.performer;
  }

  public JoinType getJoinType() {
    return this.joinType;
  }


  public void setJoinType(final JoinType joinType) {
    this.joinType = joinType;
  }

  public SplitType getSplitType() {
    return this.splitType;
  }

  public Set getDeadlineHooks() {
    return this.deadlines;
  }

  public void setDeadlineHooks(final Set deadlineHooks) {
    this.deadlines = deadlineHooks;
  }

  public void setJavaHooks(final List javaHooks) {
    this.javaHooks = javaHooks;
  }


  public List getJavaHooks() {
    return this.javaHooks;
  }


  public String getActivityId() {
    return this.activityId;
  }


  public void setMultiInstantiation(final String variableId, final ClassInfo instantiator) {
    this.multiInstantiationVariable = variableId;
    this.multiInstantiationClass = instantiator;
  }

  @Override
  public String toString() {
    final StringBuffer buffer = new StringBuffer();
    buffer.append(this.getClass().getName());
    buffer.append(": activtyId: " + this.activityId);
    return buffer.toString();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy