Package org.camunda.bpm.engine.impl.bpmn.helper

Source Code of org.camunda.bpm.engine.impl.bpmn.helper.ScopeUtil

/* 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.camunda.bpm.engine.impl.bpmn.helper;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.camunda.bpm.engine.impl.context.Context;
import org.camunda.bpm.engine.impl.persistence.entity.CompensateEventSubscriptionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.EventSubscriptionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.pvm.PvmProcessDefinition;
import org.camunda.bpm.engine.impl.pvm.PvmScope;
import org.camunda.bpm.engine.impl.pvm.delegate.ActivityBehavior;
import org.camunda.bpm.engine.impl.pvm.delegate.ActivityExecution;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl;


/**
* @author Daniel Meyer
* @author Nico Rehwaldt
*/
public class ScopeUtil {

  /**
   * Find the next scope execution in the parent execution hierarchy
   * That method works different than {@link #findScopeExecutionForScope(org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity, org.camunda.bpm.engine.impl.pvm.PvmScope)}
   * which returns the most outer scope execution.
   *
   * @param execution the execution from which to start the search
   * @return the next scope execution in the parent execution hierarchy
   */
  public static ActivityExecution findScopeExecution(ActivityExecution execution) {

    while(!execution.isScope()) {
      execution = execution.getParent();
    }

    if(execution.isConcurrent()) {
      execution = execution.getParent();
    }

    return execution;

  }
  /**
   * returns the top-most execution sitting in an activity part of the scope defined by 'scopeActivitiy'.
   */
  public static ExecutionEntity findScopeExecutionForScope(ExecutionEntity execution, PvmScope scopeActivity) {

    // TODO: this feels hacky!

    if (scopeActivity instanceof PvmProcessDefinition) {
      return execution.getProcessInstance();

    } else {

      ActivityImpl currentActivity = execution.getActivity();
      ExecutionEntity candiadateExecution = null;
      ExecutionEntity originalExecution = execution;

      while (execution != null) {
        currentActivity = execution.getActivity();
        if (scopeActivity.getActivities().contains(currentActivity) /* does not search rec*/
                || scopeActivity.equals(currentActivity)) {
          // found a candidate execution; lets still check whether we find an
          // execution which is also sitting in an activity part of this scope
          // higher up the hierarchy
          candiadateExecution = execution;
        } else if (currentActivity!= null
                && currentActivity.contains((ActivityImpl)scopeActivity) /*searches rec*/) {
          // now we're too "high", the candidate execution is the one.
          break;
        }

        execution = execution.getParent();
      }

      // if activity is scope, we need to get the parent at least:
      if(originalExecution == candiadateExecution
              && originalExecution.getActivity().isScope()
              && !originalExecution.getActivity().equals(scopeActivity)) {
        candiadateExecution = originalExecution.getParent();
      }

      return candiadateExecution;
    }
  }

  public static ActivityImpl findInParentScopesByBehaviorType(ActivityImpl activity, Class<? extends ActivityBehavior> behaviorType) {
    while (activity != null) {
      for (ActivityImpl childActivity : activity.getActivities()) {
        if(behaviorType.isAssignableFrom(childActivity.getActivityBehavior().getClass())) {
          return childActivity;
        }
      }
      activity = activity.getParentActivity();
    }
    return null;
  }

  /**
   * we create a separate execution for each compensation handler invocation.
   */
  public static void throwCompensationEvent(List<CompensateEventSubscriptionEntity> eventSubscriptions, ActivityExecution execution, boolean async) {

    // first spawn the compensating executions
    for (EventSubscriptionEntity eventSubscription : eventSubscriptions) {
      ExecutionEntity compensatingExecution = null;
      // check whether compensating execution is already created
      // (which is the case when compensating an embedded subprocess,
      // where the compensating execution is created when leaving the subprocess
      // and holds snapshot data).
      if(eventSubscription.getConfiguration() !=null) {
        compensatingExecution = Context.getCommandContext()
          .getExecutionManager()
          .findExecutionById(eventSubscription.getConfiguration());
        // move the compensating execution under this execution:
        compensatingExecution.setParent((PvmExecutionImpl) execution);
        compensatingExecution.setEventScope(false);
      } else {
        compensatingExecution = (ExecutionEntity) execution.createExecution();
        eventSubscription.setConfiguration(compensatingExecution.getId());
      }
      compensatingExecution.setConcurrent(true);
    }

    // signal compensation events in reverse order of their 'created' timestamp
    Collections.sort(eventSubscriptions, new Comparator<EventSubscriptionEntity>() {
      public int compare(EventSubscriptionEntity o1, EventSubscriptionEntity o2) {
        return o2.getCreated().compareTo(o1.getCreated());
      }
    });

    for (CompensateEventSubscriptionEntity compensateEventSubscriptionEntity : eventSubscriptions) {
      compensateEventSubscriptionEntity.eventReceived(null, async);
    }
  }

  /**
   * creates an event scope for the given execution:
   *
   * create a new event scope execution under the parent of the given
   * execution and move all event subscriptions to that execution.
   *
   * this allows us to "remember" the event subscriptions after finishing a
   * scope
   */
  public static void createEventScopeExecution(ExecutionEntity execution) {

    ExecutionEntity eventScope = ScopeUtil.findScopeExecutionForScope(execution, execution.getActivity().getParent());

    List<CompensateEventSubscriptionEntity> eventSubscriptions = execution.getCompensateEventSubscriptions();

    if(eventSubscriptions.size() > 0) {

      ExecutionEntity eventScopeExecution = eventScope.createExecution();
      eventScopeExecution.setActivity(execution.getActivity());
      eventScopeExecution.enterActivityInstance();
      eventScopeExecution.setActive(false);
      eventScopeExecution.setConcurrent(false);
      eventScopeExecution.setEventScope(true);

      execution.setConcurrent(false);

      // copy local variables to eventScopeExecution by value. This way,
      // the eventScopeExecution references a 'snapshot' of the local variables
      Map<String, Object> variables = execution.getVariablesLocal();
      for (Entry<String, Object> variable : variables.entrySet()) {
        eventScopeExecution.setVariableLocal(variable.getKey(), variable.getValue());
      }

      // set event subscriptions to the event scope execution:
      for (CompensateEventSubscriptionEntity eventSubscriptionEntity : eventSubscriptions) {
        eventSubscriptionEntity = eventSubscriptionEntity.moveUnder(eventScopeExecution);
      }

      CompensateEventSubscriptionEntity eventSubscription = CompensateEventSubscriptionEntity.createAndInsert(eventScope);
      eventSubscription.setActivity(execution.getActivity());
      eventSubscription.setConfiguration(eventScopeExecution.getId());

    }
  }

}
TOP

Related Classes of org.camunda.bpm.engine.impl.bpmn.helper.ScopeUtil

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.