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

org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionDestroyScope Maven / Gradle / Ivy

There is a newer version: 7.21.0
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.camunda.bpm.engine.impl.pvm.runtime.operation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.camunda.bpm.engine.ProcessEngineException;
import org.camunda.bpm.engine.impl.ProcessEngineLogger;
import org.camunda.bpm.engine.impl.pvm.PvmActivity;
import org.camunda.bpm.engine.impl.pvm.PvmLogger;
import org.camunda.bpm.engine.impl.pvm.PvmTransition;
import org.camunda.bpm.engine.impl.pvm.runtime.LegacyBehavior;
import org.camunda.bpm.engine.impl.pvm.runtime.OutgoingExecution;
import org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl;


/**
 * @author Tom Baeyens
 * @author Daniel Meyer
 * @author Thorben Lindhauer
 */
public class PvmAtomicOperationTransitionDestroyScope implements PvmAtomicOperation {

  private final static PvmLogger LOG = ProcessEngineLogger.PVM_LOGGER;

  public boolean isAsync(PvmExecutionImpl instance) {
    return false;
  }

  public boolean isAsyncCapable() {
    return false;
  }

  public void execute(PvmExecutionImpl execution) {

    // calculate the propagating execution
    PvmExecutionImpl propagatingExecution = execution;

    PvmActivity activity = execution.getActivity();
    List transitionsToTake = execution.getTransitionsToTake();
    execution.setTransitionsToTake(null);

    // check whether the current scope needs to be destroyed
    if (execution.isScope() && activity.isScope()) {

      if (!LegacyBehavior.destroySecondNonScope(execution)) {
        if (execution.isConcurrent()) {
          // legacy behavior
          LegacyBehavior.destroyConcurrentScope(execution);
        }
        else {
          propagatingExecution = execution.getParent();
          LOG.debugDestroyScope(execution, propagatingExecution);
          execution.destroy();
          propagatingExecution.setActivity(execution.getActivity());
          propagatingExecution.setTransition(execution.getTransition());
          propagatingExecution.setActive(true);
          execution.remove();
        }
      }

    } else {
      // activity is not scope => nothing to do
      propagatingExecution = execution;
    }

    // take the specified transitions
    if (transitionsToTake.isEmpty()) {
      throw new ProcessEngineException(execution.toString() + ": No outgoing transitions from "
          + "activity " + activity);
    }
    else if (transitionsToTake.size() == 1) {
      propagatingExecution.setTransition(transitionsToTake.get(0));
      propagatingExecution.take();
    }
    else {
      propagatingExecution.inactivate();

      List outgoingExecutions = new ArrayList();

      for (int i = 0; i < transitionsToTake.size(); i++) {
        PvmTransition transition = transitionsToTake.get(i);

        PvmExecutionImpl scopeExecution = propagatingExecution.isScope() ?
            propagatingExecution : propagatingExecution.getParent();

        // reuse concurrent, propagating execution for first transition
        PvmExecutionImpl concurrentExecution = null;
        if (i == 0) {
          concurrentExecution = propagatingExecution;
        }
        else {
          concurrentExecution = scopeExecution.createConcurrentExecution();

          if (i == 1 && !propagatingExecution.isConcurrent()) {
            outgoingExecutions.remove(0);
            // get a hold of the concurrent execution that replaced the scope propagating execution
            PvmExecutionImpl replacingExecution = null;
            for (PvmExecutionImpl concurrentChild : scopeExecution.getNonEventScopeExecutions())  {
              if (!(concurrentChild == propagatingExecution)) {
                replacingExecution = concurrentChild;
                break;
              }
            }

            outgoingExecutions.add(new OutgoingExecution(replacingExecution, transitionsToTake.get(0)));
          }
        }

        outgoingExecutions.add(new OutgoingExecution(concurrentExecution, transition));
      }

      // start executions in reverse order (order will be reversed again in command context with the effect that they are
      // actually be started in correct order :) )
      Collections.reverse(outgoingExecutions);

      for (OutgoingExecution outgoingExecution : outgoingExecutions) {
        outgoingExecution.take();
      }
    }

  }

  public String getCanonicalName() {
    return "transition-destroy-scope";
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy