protected void resetSentries(List<String> sentries) {
   for (String sentry : sentries) {
     List<CmmnSentryPart> parts = getSentries().get(sentry);
     for (CmmnSentryPart part : parts) {
       part.setSatisfied(false);
     }
   }
 }
  protected boolean containsIfPartAndExecutionActive(
      String sentryId, Map<String, List<CmmnSentryPart>> sentries) {
    List<? extends CmmnSentryPart> sentryParts = sentries.get(sentryId);

    for (CmmnSentryPart part : sentryParts) {
      CmmnExecution caseExecution = part.getCaseExecution();
      if (IF_PART.equals(part.getType()) && caseExecution != null && caseExecution.isActive()) {
        return true;
      }
    }

    return false;
  }
  protected void addIdIfNotSatisfied(List<String> affectedSentries, CmmnSentryPart sentryPart) {
    if (!sentryPart.isSatisfied()) {
      // if it is not already satisfied, then set the
      // current case sentry part to satisfied (=true).
      String sentryId = sentryPart.getSentryId();
      sentryPart.setSatisfied(true);

      // collect the id of affected sentry.
      if (!affectedSentries.contains(sentryId)) {
        affectedSentries.add(sentryId);
      }
    }
  }
  protected CmmnSentryPart createVariableOnPart(
      CmmnSentryDeclaration sentryDeclaration,
      CmmnVariableOnPartDeclaration variableOnPartDeclaration) {
    CmmnSentryPart sentryPart = createSentryPart(sentryDeclaration, VARIABLE_ON_PART);

    // set the variable event
    String variableEvent = variableOnPartDeclaration.getVariableEvent();
    sentryPart.setVariableEvent(variableEvent);

    // set the variable name
    String variableName = variableOnPartDeclaration.getVariableName();
    sentryPart.setVariableName(variableName);

    return sentryPart;
  }
  protected CmmnSentryPart createSentryPart(CmmnSentryDeclaration sentryDeclaration, String type) {
    CmmnSentryPart newSentryPart = newSentryPart();

    // set the type
    newSentryPart.setType(type);

    // set the case instance and case execution
    newSentryPart.setCaseInstance(getCaseInstance());
    newSentryPart.setCaseExecution(this);

    // set sentry id
    String sentryId = sentryDeclaration.getId();
    newSentryPart.setSentryId(sentryId);

    return newSentryPart;
  }
  public void fireIfOnlySentryParts() {
    // the following steps are a workaround, because setVariable()
    // does not check nor fire a sentry!!!
    Set<String> affectedSentries = new HashSet<String>();
    List<CmmnSentryPart> sentryParts = collectSentryParts(getSentries());
    for (CmmnSentryPart sentryPart : sentryParts) {
      if (isNotSatisfiedIfPartOnly(sentryPart)) {
        affectedSentries.add(sentryPart.getSentryId());
      }
    }

    // Step 7: check each not affected sentry whether it is satisfied
    List<String> satisfiedSentries = getSatisfiedSentries(new ArrayList<String>(affectedSentries));

    // Step 8: reset sentries -> satisfied == false
    resetSentries(satisfiedSentries);

    // Step 9: fire satisfied sentries
    fireSentries(satisfiedSentries);
  }
  protected CmmnSentryPart createOnPart(
      CmmnSentryDeclaration sentryDeclaration, CmmnOnPartDeclaration onPartDeclaration) {
    CmmnSentryPart sentryPart = createSentryPart(sentryDeclaration, PLAN_ITEM_ON_PART);

    // set the standard event
    String standardEvent = onPartDeclaration.getStandardEvent();
    sentryPart.setStandardEvent(standardEvent);

    // set source case execution
    CmmnActivity source = onPartDeclaration.getSource();
    ensureNotNull(
        "The source of sentry '" + sentryDeclaration.getId() + "' is null.", "source", source);

    String sourceActivityId = source.getId();
    sentryPart.setSource(sourceActivityId);

    // TODO: handle also sentryRef!!! (currently not implemented on purpose)

    return sentryPart;
  }
  protected List<String> collectAffectedSentriesWithVariableOnParts(
      String variableName, String variableEvent, List<CmmnSentryPart> sentryParts) {

    List<String> affectedSentries = new ArrayList<String>();

    for (CmmnSentryPart sentryPart : sentryParts) {

      String sentryVariableName = sentryPart.getVariableName();
      String sentryVariableEvent = sentryPart.getVariableEvent();
      CmmnExecution execution = sentryPart.getCaseExecution();
      if (VARIABLE_ON_PART.equals(sentryPart.getType())
          && sentryVariableName.equals(variableName)
          && sentryVariableEvent.equals(variableEvent)
          && !hasVariableWithSameNameInParent(execution, sentryVariableName)) {

        addIdIfNotSatisfied(affectedSentries, sentryPart);
      }
    }

    return affectedSentries;
  }
  protected List<String> collectAffectedSentries(CmmnExecution child, String transition) {
    List<? extends CmmnSentryPart> sentryParts = getCaseSentryParts();

    List<String> affectedSentries = new ArrayList<String>();

    for (CmmnSentryPart sentryPart : sentryParts) {

      // necessary for backward compatibility
      String sourceCaseExecutionId = sentryPart.getSourceCaseExecutionId();
      String sourceRef = sentryPart.getSource();
      if (child.getActivityId().equals(sourceRef) || child.getId().equals(sourceCaseExecutionId)) {

        String standardEvent = sentryPart.getStandardEvent();
        if (transition.equals(standardEvent)) {
          addIdIfNotSatisfied(affectedSentries, sentryPart);
        }
      }
    }

    return affectedSentries;
  }
  protected boolean isSentryPartsSatisfied(
      String sentryId, List<? extends CmmnSentryPart> sentryParts) {
    // if part will be evaluated in the end
    CmmnSentryPart ifPart = null;

    if (sentryParts != null && !sentryParts.isEmpty()) {
      for (CmmnSentryPart sentryPart : sentryParts) {

        if (PLAN_ITEM_ON_PART.equals(sentryPart.getType())) {

          if (!sentryPart.isSatisfied()) {
            return false;
          }

        } else if (VARIABLE_ON_PART.equals(sentryPart.getType())) {
          if (!sentryPart.isSatisfied()) {
            return false;
          }
        } else {
            /* IF_PART.equals(sentryPart.getType) == true */

          ifPart = sentryPart;

          // once the ifPart has been satisfied the whole sentry is satisfied
          if (ifPart.isSatisfied()) {
            return true;
          }
        }
      }
    }

    if (ifPart != null) {

      CmmnExecution execution = ifPart.getCaseExecution();
      ensureNotNull("Case execution of sentry '" + ifPart.getSentryId() + "': is null", execution);

      CmmnActivity activity = ifPart.getCaseExecution().getActivity();
      ensureNotNull("Case execution '" + id + "': has no current activity", "activity", activity);

      CmmnSentryDeclaration sentryDeclaration = activity.getSentry(sentryId);
      ensureNotNull(
          "Case execution '" + id + "': has no declaration for sentry '" + sentryId + "'",
          "sentryDeclaration",
          sentryDeclaration);

      CmmnIfPartDeclaration ifPartDeclaration = sentryDeclaration.getIfPart();
      ensureNotNull(
          "Sentry declaration '"
              + sentryId
              + "' has no definied ifPart, but there should be one defined for case execution '"
              + id
              + "'.",
          "ifPartDeclaration",
          ifPartDeclaration);

      Expression condition = ifPartDeclaration.getCondition();
      ensureNotNull(
          "A condition was expected for ifPart of Sentry declaration '"
              + sentryId
              + "' for case execution '"
              + id
              + "'.",
          "condition",
          condition);

      Object result = condition.getValue(this);
      ensureInstanceOf("condition expression returns non-Boolean", "result", result, Boolean.class);

      Boolean booleanResult = (Boolean) result;
      ifPart.setSatisfied(booleanResult);
      return booleanResult;
    }

    // if all onParts are satisfied and there is no
    // ifPart then the whole sentry is satisfied.
    return true;
  }
 protected void resetSentryParts(List<CmmnSentryPart> parts) {
   for (CmmnSentryPart part : parts) {
     part.setSatisfied(false);
   }
 }
 protected boolean isNotSatisfiedIfPartOnly(CmmnSentryPart sentryPart) {
   return IF_PART.equals(sentryPart.getType())
       && getSentries().get(sentryPart.getSentryId()).size() == 1
       && !sentryPart.isSatisfied();
 }