001/**
002 * Copyright 2005-2015 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
018/**
019 * <p>Enumeration for simple collection operators used by {@link CollectionOfComparablesTermBasedProposition}.  The
020 * operators encapsulate logic for how to collate results and when to short circuit as a collection is being
021 * processed.  Correct usage is best summarized by this code block:</p>
022 * <pre>
023 * for (Comparable<T> item : comparableItems) {
024 *     collatedResult = collectionOper.reduce(compare(item, compareValue), collatedResult);
025 *     if (collectionOper.shortCircuit(collatedResult)) break;
026 * }
027 * </pre>
028 * 
029 * @author Kuali Rice Team (rice.collab@kuali.org)
030 *
031 */
032public enum CollectionOperator {
033
034        ONE_OR_MORE(false) {
035                @Override
036                public boolean reduce(boolean elementResult, boolean collatedResult) {
037                        return elementResult || collatedResult;
038                }
039                
040                @Override
041                public boolean shortCircuit(boolean collatedResult) {
042                        return collatedResult;
043                }
044        },
045        
046        ALL(true) {
047                @Override
048                public boolean reduce(boolean elementResult, boolean collatedResult) {
049                        return elementResult && collatedResult;
050                }
051
052                @Override
053                public boolean shortCircuit(boolean collatedResult) {
054                        return !collatedResult;
055                }
056        },
057        
058        NONE(true) {
059                @Override
060                public boolean reduce(boolean elementResult, boolean collatedResult) {
061                        return !elementResult && collatedResult;
062                }
063
064                @Override
065                public boolean shortCircuit(boolean collatedResult) {
066                        return !collatedResult;
067                }
068        };
069        
070        private final boolean initialCollationResult;
071        
072        private CollectionOperator(boolean initialCollationResult) {
073                this.initialCollationResult = initialCollationResult;
074        }
075        
076        /**
077         * This method takes the collated result thus far and the result for the next element,
078         * and produces the next collated result.
079         * 
080         * @return the new collated result
081         */
082        public abstract boolean reduce(boolean elementResult, boolean collatedResult);
083        
084        /**
085         * This method lets the engine know if it can short circuit its iteration through the list based on the 
086         * collated result.  The condition when short circuiting can be done varies with the operator.
087         * 
088         * @param collatedResult
089         * @return true if short circuiting can be done to optimize processing
090         */
091        public abstract boolean shortCircuit(boolean collatedResult);
092        
093        /**
094         * when the result for the first item in the collection is calculated, there isn't yet a collated result 
095         * to use in the {@link #reduce(boolean, boolean)} method.  Different operators require different
096         * initial values to function correctly, so this property holds the correct initial collated value for the 
097         * given operator instance.
098         */
099        public boolean getInitialCollatedResult() {
100                return initialCollationResult;
101        }
102        
103}