@Override
  public EvaluationResult combine(
      EvaluationContext evaluationContext,
      List<CombiningElement<Rule>> elements,
      List<CombinerParameter> combinerParameters)
      throws EvaluationException {
    boolean atLeastOneDeny = false;
    boolean potentialPermit = false;

    EvaluationResult evaluationResultCombined = new EvaluationResult(Decision.DENY);
    EvaluationResult evaluationResultIndeterminate = null;

    Iterator<CombiningElement<Rule>> iterElements = elements.iterator();
    while (iterElements.hasNext()) {
      CombiningElement<Rule> combiningElement = iterElements.next();
      EvaluationResult evaluationResultElement = combiningElement.evaluate(evaluationContext);

      assert evaluationResultElement != null;
      switch (evaluationResultElement.getDecision()) {
        case DENY:
          atLeastOneDeny = true;
          evaluationResultCombined.merge(evaluationResultElement);
          break;
        case INDETERMINATE:
        case INDETERMINATE_DENYPERMIT:
        case INDETERMINATE_DENY:
        case INDETERMINATE_PERMIT:
          if (evaluationResultIndeterminate == null) {
            evaluationResultIndeterminate = evaluationResultElement;
          } else {
            evaluationResultIndeterminate.merge(evaluationResultElement);
          }
          if (combiningElement.getEvaluatable().getRuleEffect() == RuleEffect.PERMIT) {
            potentialPermit = true;
          }
          break;
        case NOTAPPLICABLE:
          break;
        case PERMIT:
          return evaluationResultElement;
        default:
          throw new EvaluationException(
              "Illegal Decision: \"" + evaluationResultElement.getDecision().toString());
      }
    }

    if (potentialPermit) {
      return evaluationResultIndeterminate;
    } else if (atLeastOneDeny) {
      return evaluationResultCombined;
    } else if (evaluationResultIndeterminate != null) {
      return evaluationResultIndeterminate;
    } else {
      return new EvaluationResult(Decision.NOTAPPLICABLE);
    }
  }
  @Override
  public EvaluationResult combine(
      EvaluationContext evaluationContext,
      List<CombiningElement<PolicySetChild>> elements,
      List<CombinerParameter> combinerParameters)
      throws EvaluationException {
    Iterator<CombiningElement<PolicySetChild>> iterElements = elements.iterator();
    PolicySetChild policySetChildApplicable = null;
    while (iterElements.hasNext()) {
      CombiningElement<PolicySetChild> combiningElement = iterElements.next();
      MatchResult matchResultElement = combiningElement.getEvaluatable().match(evaluationContext);

      switch (matchResultElement.getMatchCode()) {
        case INDETERMINATE:
          return new EvaluationResult(Decision.INDETERMINATE, matchResultElement.getStatus());
        case MATCH:
          if (policySetChildApplicable == null) {
            policySetChildApplicable = combiningElement.getEvaluatable();
          } else {
            return new EvaluationResult(
                Decision.INDETERMINATE,
                new StdStatus(
                    StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "More than one applicable policy"));
          }
          break;
        case NOMATCH:
          break;
        default:
          throw new EvaluationException(
              "Illegal Decision: \"" + matchResultElement.getMatchCode().toString());
      }
    }

    if (policySetChildApplicable != null) {
      return policySetChildApplicable.evaluate(evaluationContext);
    } else {
      return new EvaluationResult(Decision.NOTAPPLICABLE);
    }
  }