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.HashMap;
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.MultiInstantiator;
import org.ow2.bonita.definition.MultiInstantiatorDescriptor;
import org.ow2.bonita.facade.def.element.DeadlineDefinition;
import org.ow2.bonita.facade.def.majorElement.ActivityDefinition;
import org.ow2.bonita.facade.def.majorElement.ActivityDefinition.JoinType;
import org.ow2.bonita.facade.def.majorElement.ActivityDefinition.SplitType;
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.facade.uuid.ActivityInstanceUUID;
import org.ow2.bonita.facade.uuid.ProcessInstanceUUID;
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.type.Variable;
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.InternalExecution;
import org.ow2.bonita.runtime.InternalInstance;
import org.ow2.bonita.runtime.InternalInstance.TransitionState;
import org.ow2.bonita.services.Recorder;
import org.ow2.bonita.util.BonitaConstants;
import org.ow2.bonita.util.BonitaRuntimeException;
import org.ow2.bonita.util.CopyTool;
import org.ow2.bonita.util.EnvTool;
import org.ow2.bonita.util.ExceptionManager;
import org.ow2.bonita.util.Misc;
import org.ow2.bonita.util.ProcessUtil;

/**
 * @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;

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

  protected ActivityDefinition activityDef;

  // iterations
  protected List  iterationDescriptors;


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


  protected AbstractActivity() {
  }

  protected AbstractActivity(final ActivityDefinition activityDef) {
    Misc.checkArgsNotNull(activityDef);
    this.activityDef = activityDef;

    if (activityDef.getPerformers() != null && !activityDef.getPerformers().isEmpty()) {
      if (activityDef.isAutomatic()) {
        String message = ExceptionManager.getInstance().getFullMessage("be_AA_1");
        throw new BonitaRuntimeException(message);
      }
    } else {
      if (!activityDef.isAutomatic()) {
        String message = ExceptionManager.getInstance().getFullMessage("be_AA_2");
        throw new BonitaRuntimeException(message);
      }
    }
  }

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

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

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

      if (activityDef.getMultiInstantiationDefinition() != 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,
              internalExecution.getInstance().getProcessDefinitionUUID(), activityDef.getMultiInstantiationDefinition());
        try {
          actInstDescr = EnvTool.getHookExecutor()
          .executeMultiInstantiator(internalExecution, activityDef.getName(), actInstantiator);
          if (actInstDescr == null) {
            String message = ExceptionManager.getInstance().getFullMessage("be_AA_3", activityDef.getName());
            throw new BonitaRuntimeException(message);
          }
        } catch (final Exception e) {
          throw new BonitaWrapperException(
              new MultiInstantiatorInvocationException("be_AA_4", activityDef.getMultiInstantiationDefinition().getClassName().toString(), e)
          );
        }

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

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

  private static void cancelJoinXORIncomingTransitions(final InternalInstance 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.getTransitionState(incomingTransition).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.getTransitionState(tr).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 InternalExecution execToAbort : execToAbortList) {
            if (execToAbort.isActive()) {
              execToAbort.abort();
            }
          }
          AbstractActivity.cancelJoinXORIncomingTransitions(instance, sourceNode, initialNode);
        }
      }
    }
  }

  protected ActivityInstanceUUID getActivityInstanceUUID(final ProcessInstanceUUID instanceUUID) {
    final long activityNb = EnvTool.getRepository().getNextActivityInstanceNb(instanceUUID, activityDef.getName());
    ActivityInstanceUUID activityInstanceUUID = new ActivityInstanceUUID(instanceUUID, activityDef.getName(), new Long(activityNb).toString());
    return activityInstanceUUID;
  }

  protected void executeActivityInstance(final InternalExecution internalExecution, final Variable multiInstanceVar) {
    ProcessInstanceUUID instanceUUID = internalExecution.getInstance().getUUID();

    ActivityInstanceUUID activityInstanceUUID = getActivityInstanceUUID(instanceUUID);
    internalExecution.setCurrentActivityInstanceUUID(activityInstanceUUID);

    ActivityDefinition activityDefinition = EnvTool.getJournalQueriers().getActivity(activityInstanceUUID.getActivityDefinitionUUID());
    
    final Recorder recorder = EnvTool.getRecorder();  
    
    Map initialVariables = ProcessUtil.createVariables(activityDefinition.getDataFields());
    if (multiInstanceVar != null && initialVariables == null) {
    	initialVariables = new HashMap();
    } else if (multiInstanceVar != null) {
    	initialVariables.put(multiInstanceVar.getKey(), multiInstanceVar);
    }
    
    recorder.recordEnterActivity(this.activityDef, internalExecution.getCurrentActivityInstanceUUID(), internalExecution.getIterationId(),
            internalExecution.getActivityInstanceId(), initialVariables);
    
    final boolean canContinue = this.executeBody(internalExecution);
    if (canContinue) {
      this.end(internalExecution);
    } else {
      internalExecution.waitForSignal();
    }
  }

  protected void end(final InternalExecution internalExecution) {
    EnvTool.getRecorder().recordBodyEnded(internalExecution.getCurrentActivityInstanceUUID());

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

  public void signal(final ActivityExecution execution, final String signal, final Map parameters) {
    final InternalExecution internalExecution = (InternalExecution) execution;
    if (AbstractActivity.BODY_FINISHED.equals(signal)) {
      this.end(internalExecution);
    } else if (AbstractActivity.ACT_INSTANCE_FINISHED.equals(signal)) {
      internalExecution.setWaitingForActivityInstanceNb(internalExecution.getWaitingForActivityInstanceNb() - 1);
      if (internalExecution.getWaitingForActivityInstanceNb() == 0) {
        if (internalExecution.getExecutions() != null) {
          for (final OpenExecution execToAbort : new ArrayList(internalExecution.getExecutions())) {
            ((InternalExecution) execToAbort).abort();
          }
        }
        this.executeSplit(internalExecution, false);
      }
    } else if (signal != null && activityDef.getDeadlines() != null) {
      for (final DeadlineDefinition deadline : activityDef.getDeadlines()) {
        if (deadline.getClassName().equals(signal)) {
          Authentication.setUserId(BonitaConstants.SYSTEM_USER);
          // By default, a deadline does not propagate execution
          internalExecution.waitForSignal();
          final String activityId = internalExecution.getNode().getName();
          EnvTool.getHookExecutor().executeConnector(internalExecution, activityId, deadline);
          return;
        }
      }
    }
  }

  protected void executeSplit(final Execution execution, final boolean removeScope) {
    InternalExecution internalExecution = (InternalExecution) execution;
    final NodeImpl currentNode = internalExecution.getNode();
    if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
      AbstractActivity.LOG.fine("node = " + currentNode.getName() + " - splitType = "
          + activityDef.getSplitType() + " - execution = " + execution.getName());
    }
    final List transitions = currentNode.getOutgoingTransitions();
    if (transitions == null) {
      if (AbstractActivity.LOG.isLoggable(Level.FINE)) {
        AbstractActivity.LOG.fine("node = " + currentNode.getName() + " - splitType = "
            + activityDef.getSplitType() + " - execution = " + execution.getName() + " no transition available. Ending execution");
      }
      internalExecution.end();
      final InternalExecution parent = internalExecution.getParent();
      if (parent != null) {
        parent.removeExecution(internalExecution);
      }
    } else {
      final List transitionsToTake = new ArrayList();
      for (final Transition t : transitions) {
        if (this.evaluateTransition((TransitionImpl) t, internalExecution)) {
          if (
              internalExecution
              .getInstance()
              .getTransitionState(t)
              .equals(TransitionState.READY)
          ) {
            internalExecution.getInstance().setTransitionState(t, TransitionState.TAKEN);
            transitionsToTake.add(t);
          }
        }
      }
      // remove not propagated variables
      if (removeScope) {
        internalExecution = (InternalExecution) internalExecution.destroyScope(currentNode);
      }
      internalExecution.setCurrentActivityInstanceUUID(null);
      if (transitionsToTake.size() == 0) {
        internalExecution.end();
        final InternalExecution parent = internalExecution.getParent();
        if (parent != null) {
          parent.removeExecution(internalExecution);
        }
      } 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(activityDef.getName() + " 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 = internalExecution.getInstance().getExecOnNode(nodeToAbort.getName());
                  for (final InternalExecution execToAbort : execToAbortList) {
                    if (execToAbort.isActive()) {
                      execToAbort.abort();
                    }
                  }
                }
              }
            }
          }
        }
        if (transitionsToTake.size() == 1  || activityDef.getSplitType().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);
          }
          internalExecution.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) {
                String message = ExceptionManager.getInstance().getFullMessage("be_AA_5");
                throw new BonitaWrapperException(new BonitaRuntimeException(message));
              }
            }
          }
          final List children = new ArrayList();
          for (int i = 0; i < transitionsToTake.size(); i++) {
            final InternalExecution childExecution = this.createChildExecution(internalExecution, i);
            final Transition t = transitionsToTake.get(i);
            childExecution.setNode((NodeImpl)t.getDestination());
            children.add(childExecution);
          }
          for (int i = 0; i < transitionsToTake.size(); i++) {
            final InternalExecution 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 InternalExecution internalExecution) {
    // testing the guard condition
    final Condition condition = t.getCondition();
    final ConditionDefinition condDef = (ConditionDefinition) condition;
    boolean conditionOK = true;
    if (condDef != null) {
      conditionOK = condDef.evaluate(internalExecution);
      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 InternalExecution createChildExecution(final InternalExecution parentExecution, final int childId) {
    final String executionName = parentExecution.getName() + "/" + childId;
    final InternalExecution childExecution = (InternalExecution) 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 InternalExecution execution) {
    final Transition previousTransition = execution.getPreviousTransition();
    final String fromName = previousTransition.getSource().getName();
    final TransitionState fromTransitionState = execution.getInstance().getTransitionState(previousTransition);
    if (fromTransitionState.equals(TransitionState.ARRIVED)) {
      String message = ExceptionManager.getInstance().getFullMessage(
          "be_AA_6", fromName, activityDef.getName());
      throw new BonitaRuntimeException(message);
    }
    if (fromTransitionState.equals(TransitionState.TAKEN)) {
      execution.getInstance().setTransitionState(previousTransition, TransitionState.ARRIVED);
    }
    return AbstractActivity.isJoinOk(execution.getInstance(), execution.getNode());
  }

  private static boolean isJoinOk(final InternalInstance instance, final NodeImpl node) {
    if (!node.hasIncomingTransitions()) {
      return true;
    }
    if (((AbstractActivity) node.getBehaviour()).getActivityDefiniton().getJoinType().equals(JoinType.XOR)) {
      // join XOR
      for (final Transition transition : node.getIncomingTransitions()) {
        final TransitionState ts = instance.getTransitionState(transition);
        if (ts.equals(TransitionState.ARRIVED)) {
          return true;
        }
      }
      return false;
    } else {
      // join AND
      for (final Transition transition : node.getIncomingTransitions()) {
        if (!instance.getTransitionState(transition).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 InternalExecution execution) {
    if (this.iterationDescriptors != null && !this.iterationDescriptors.isEmpty()) {
      final String iterationUUID = Misc.getUniqueId("it");
      execution.setIterationId(iterationUUID);
      final InternalInstance instance = execution.getInstance();
      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)) {
              String message = ExceptionManager.getInstance().getFullMessage("be_AA_7", joinNode.getName());
              throw new BonitaRuntimeException(message);
            }
          }
        }
      }
    }
  }

  private boolean executeBody(final InternalExecution internalExecution) {
    if (this.bodyStartAutomatically()) {
      EnvTool.getRecorder().recordBodyStarted(internalExecution.getCurrentActivityInstanceUUID());
    }
    return this.executeBusinessLogic(internalExecution);
  }

  /**
   * 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;
  }
*/

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy