001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.krms.framework.engine; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.List; 021 022import org.kuali.rice.krms.api.engine.ExecutionEnvironment; 023import org.kuali.rice.krms.api.engine.ResultEvent; 024import org.kuali.rice.krms.api.engine.ExecutionFlag; 025import org.kuali.rice.krms.api.repository.LogicalOperator; 026import 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 * @author Kuali Rice Team (rice.collab@kuali.org) 033 */ 034public final class CompoundProposition implements Proposition { 035 036 private static final ResultLogger LOG = ResultLogger.getInstance(); 037 038 private final LogicalOperator logicalOperator; 039 private final List<Proposition> propositions; 040 041 /** 042 * Create a CompoundProposition with the given values 043 * @param logicalOperator {@link LogicalOperator} to set logicalOperator to 044 * @param propositions to set the propositions to 045 */ 046 public CompoundProposition(LogicalOperator logicalOperator, List<Proposition> propositions) { 047 048 if (propositions == null || propositions.isEmpty()) { 049 throw new IllegalArgumentException("Propositions must be non-null and non-empty."); 050 } 051 if (logicalOperator == null) { 052 throw new IllegalArgumentException("Logical operator must be non-null."); 053 } 054 this.logicalOperator = logicalOperator; 055 this.propositions = new ArrayList<Proposition>(propositions); 056 } 057 058 @Override 059 public PropositionResult evaluate(ExecutionEnvironment environment) { 060 061 PropositionResult result = evaluateInner(environment); 062 063 // handle compound proposition result logging 064 if (LOG.isEnabled(environment)) { 065 LOG.logResult(new BasicResult(ResultEvent.PROPOSITION_EVALUATED, this, environment, result.getResult())); 066 } 067 068 return result; 069 } 070 071 /** 072 * Evaluates then {@link ExecutionEnvironment} 073 * 074 * @param environment {@link ExecutionEnvironment} to use for evaluation 075 * @return PropositionResult {@link PropositionResult} the results of the evaluation 076 * @throws IllegalStateException if the logicalOperator is invalid. 077 */ 078 079 private PropositionResult evaluateInner(ExecutionEnvironment environment) { 080 081 boolean collatedResult; 082 boolean evaluateAll = environment.getExecutionOptions().getFlag(ExecutionFlag.EVALUATE_ALL_PROPOSITIONS); 083 084 if (logicalOperator == LogicalOperator.AND) { 085 086 collatedResult = true; 087 088 for (Proposition proposition : propositions) { 089 090 PropositionResult singleResult = proposition.evaluate(environment); 091 logPropositionResult(proposition, singleResult, environment); 092 093 if (!singleResult.getResult()) { 094 collatedResult = false; 095 if(!evaluateAll) break; 096 } 097 } 098 099 return new PropositionResult(collatedResult); 100 101 } else if (logicalOperator == LogicalOperator.OR) { 102 103 collatedResult = false; 104 105 for (Proposition proposition : propositions) { 106 107 PropositionResult singleResult = proposition.evaluate(environment); 108 logPropositionResult(proposition, singleResult, environment); 109 110 if (singleResult.getResult()) { 111 collatedResult = true; 112 if(!evaluateAll) break; 113 } 114 } 115 116 return new PropositionResult(collatedResult); 117 } 118 throw new IllegalStateException("Invalid logical operator: " + logicalOperator); 119 } 120 121 /* 122 * Logs only if the proposition is not compound 123 * and have the compound proposition log its own result 124 * @param proposition {@link Proposition} to log. Compound Propositions will not log. 125 * @param propositionResult {@link PropositionResult} to log the result and execution details of 126 * @param environment {@link ExecutionEnvironment} to log 127 */ 128 129 public void logPropositionResult(Proposition proposition, PropositionResult propositionResult, ExecutionEnvironment environment) { 130 131 if(!proposition.isCompound()) { 132 LOG.logResult(new BasicResult(propositionResult.getExecutionDetails(), ResultEvent.PROPOSITION_EVALUATED, proposition, environment, propositionResult.getResult())); 133 } 134 135 } 136 137 /** 138 * Returns an unmodifiableList of {@link Proposition}s. 139 * @return an unmodifiableList of {@link Proposition}s 140 */ 141 @Override 142 public List<Proposition> getChildren() { 143 return Collections.unmodifiableList(propositions); 144 } 145 146 @Override 147 public boolean isCompound() { 148 return true; 149 } 150 151}