001 /** 002 * Copyright 2005-2012 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.krms.framework.engine; 017 018 import java.util.ArrayList; 019 import java.util.Collections; 020 import java.util.List; 021 022 import org.kuali.rice.krms.api.engine.ExecutionEnvironment; 023 import org.kuali.rice.krms.api.engine.ResultEvent; 024 import org.kuali.rice.krms.api.engine.ExecutionFlag; 025 import org.kuali.rice.krms.api.repository.LogicalOperator; 026 import org.kuali.rice.krms.framework.engine.result.BasicResult; 027 028 /** 029 * 030 * An implementation of {@link Proposition} which holds other Propositions and a {@link LogicalOperator}. 031 * 032 * NOTE - this is a patched version of CompoundProposition which fixes bugs in evaluation "OR"-ed propositions 033 * 034 * @author Kuali Rice Team (rice.collab@kuali.org) 035 */ 036 public final class CompoundProposition implements Proposition { 037 038 private static final ResultLogger LOG = ResultLogger.getInstance(); 039 040 private final LogicalOperator logicalOperator; 041 private final List<Proposition> propositions; 042 043 /** 044 * Create a CompoundProposition with the given values 045 * @param logicalOperator {@link LogicalOperator} to set logicalOperator to 046 * @param propositions to set the propositions to 047 */ 048 public CompoundProposition(LogicalOperator logicalOperator, List<Proposition> propositions) { 049 050 if (propositions == null || propositions.isEmpty()) { 051 throw new IllegalArgumentException("Propositions must be non-null and non-empty."); 052 } 053 if (logicalOperator == null) { 054 throw new IllegalArgumentException("Logical operator must be non-null."); 055 } 056 this.logicalOperator = logicalOperator; 057 this.propositions = new ArrayList<Proposition>(propositions); 058 } 059 060 @Override 061 public PropositionResult evaluate(ExecutionEnvironment environment) { 062 063 PropositionResult result = evaluateInner(environment); 064 065 // handle compound proposition result logging 066 if (LOG.isEnabled(environment)) { 067 LOG.logResult(new BasicResult(ResultEvent.PROPOSITION_EVALUATED, this, environment, result.getResult())); 068 } 069 070 return result; 071 } 072 073 /** 074 * Evaluates then {@link ExecutionEnvironment} 075 * 076 * @param environment {@link ExecutionEnvironment} to use for evaluation 077 * @return PropositionResult {@link PropositionResult} the results of the evaluation 078 * @throws IllegalStateException if the logicalOperator is invalid. 079 */ 080 081 private PropositionResult evaluateInner(ExecutionEnvironment environment) { 082 083 boolean collatedResult; 084 boolean evaluateAll = environment.getExecutionOptions().getFlag(ExecutionFlag.EVALUATE_ALL_PROPOSITIONS); 085 086 if (logicalOperator == LogicalOperator.AND) { 087 088 collatedResult = true; 089 090 for (Proposition proposition : propositions) { 091 092 PropositionResult singleResult = proposition.evaluate(environment); 093 logPropositionResult(proposition, singleResult, environment); 094 095 if (!singleResult.getResult()) { 096 collatedResult = false; 097 if(!evaluateAll) break; 098 } 099 } 100 101 return new PropositionResult(collatedResult); 102 103 } else if (logicalOperator == LogicalOperator.OR) { 104 105 collatedResult = false; 106 107 for (Proposition proposition : propositions) { 108 109 PropositionResult singleResult = proposition.evaluate(environment); 110 logPropositionResult(proposition, singleResult, environment); 111 112 if (singleResult.getResult()) { 113 collatedResult = true; 114 if(!evaluateAll) break; 115 } 116 } 117 118 return new PropositionResult(collatedResult); 119 } 120 throw new IllegalStateException("Invalid logical operator: " + logicalOperator); 121 } 122 123 /* 124 * Logs only if the proposition is not compound 125 * and have the compound proposition log its own result 126 * @param proposition {@link Proposition} to log. Compound Propositions will not log. 127 * @param propositionResult {@link PropositionResult} to log the result and execution details of 128 * @param environment {@link ExecutionEnvironment} to log 129 */ 130 131 public void logPropositionResult(Proposition proposition, PropositionResult propositionResult, ExecutionEnvironment environment) { 132 133 if(!proposition.isCompound()) { 134 LOG.logResult(new BasicResult(propositionResult.getExecutionDetails(), ResultEvent.PROPOSITION_EVALUATED, proposition, environment, propositionResult.getResult())); 135 } 136 137 } 138 139 /** 140 * Returns an unmodifiableList of {@link Proposition}s. 141 * @return an unmodifiableList of {@link Proposition}s 142 */ 143 @Override 144 public List<Proposition> getChildren() { 145 return Collections.unmodifiableList(propositions); 146 } 147 148 @Override 149 public boolean isCompound() { 150 return true; 151 } 152 153 }