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.expression;
017
018import org.kuali.rice.core.api.mo.common.Coded;
019import org.kuali.rice.core.api.util.jaxb.EnumStringAdapter;
020import org.kuali.rice.krms.api.KrmsApiServiceLocator;
021import org.kuali.rice.krms.api.engine.expression.ComparisonOperatorService;
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.List;
027
028/**
029 * Operators enumeration for comparing objects.  EQUALS NOT_EQUALS GREATER_THAN GREATER_THAN_EQUAL LESS_THAN LESS_THAN_EQUAL.
030 * Uses registered {@link EngineComparatorExtension} for the given objects or the {@link DefaultComparisonOperator}.
031 *
032 * @author Kuali Rice Team (rice.collab@kuali.org)
033 */
034public enum ComparisonOperator implements Coded {
035
036    /**
037     * use this flag with the static factory to get a {@link ComparisonOperator} EQUALS
038     */
039        EQUALS("="),
040
041    /**
042     * use this flag with the static factory to get a {@link ComparisonOperator} NOT_EQUALS
043     */
044        NOT_EQUALS("!="),
045
046    /**
047     * use this flag with the static factory to get a {@link ComparisonOperator} GREATER_THAN
048     */
049        GREATER_THAN(">"),
050
051    /**
052     * use this flag with the static factory to get a {@link ComparisonOperator} GREATER_THAN_EQUAL
053     */
054        GREATER_THAN_EQUAL(">="),
055
056    /**
057     * use this flag with the static factory to get a {@link ComparisonOperator} LESS_THAN
058     */
059        LESS_THAN("<"),
060
061    /**
062     * use this flag with the static factory to get a {@link ComparisonOperator} LESS_THAN_EQUAL
063     */
064        LESS_THAN_EQUAL("<="),
065
066    /**
067     * use this flag with the static factory to get a {@link ComparisonOperator} EXISTS
068     */
069    EXISTS("!=null"),
070
071    /**
072     * use this flag with the static factory to get a {@link ComparisonOperator} DOES_NOT_EXISTS
073     */
074    DOES_NOT_EXIST("=null");
075
076        private final String code;
077
078    ComparisonOperatorService comparisonOperatorService;
079
080    /**
081     * Create a ComparisonOperator from the given code
082     * @param code code the ComparisonOperator should be of.
083     */
084        private ComparisonOperator(String code) {
085                this.code = code;
086        }
087
088    /**
089     *
090     * @return code representing the type of operator
091     */
092    @Override
093        public String getCode() {
094                return code;
095        }
096
097    /**
098     * Create a ComparisonOperator from the given code
099     * @param code for type of ComparisonOperator to create
100     * @return a ComparisonOperator created with the given code.
101     * @throws IllegalArgumentException if the given code does not exist
102     */
103        public static ComparisonOperator fromCode(String code) {
104                if (code == null) {
105                        return null;
106                }
107                for (ComparisonOperator comparisonOperator : values()) {
108                        if (comparisonOperator.code.equals(code)) {
109                                return comparisonOperator;
110                        }
111                }
112                throw new IllegalArgumentException("Failed to locate the ComparisionOperator with the given code: " + code);
113        }
114
115    /**
116     * Compare the given objects
117     * @param lhs left hand side object
118     * @param rhs right hand side object
119     * @return boolean value of comparison results based on the type of operator.
120     */
121        public boolean compare(Object lhs, Object rhs) {
122        if (comparisonOperatorService == null) {
123            setComparisonOperatorService(KrmsApiServiceLocator.getComparisonOperatorService());
124        }
125        int result = comparisonOperatorService.compare(lhs, rhs);
126
127        if (this == EQUALS) {
128            return result == 0;
129        } else if (this == NOT_EQUALS) {
130            return result != 0;
131        } else if (this == GREATER_THAN) {
132            return result > 0;
133        } else if (this == GREATER_THAN_EQUAL) {
134            return result >= 0;
135        } else if (this == LESS_THAN) {
136            return result < 0;
137        } else if (this == LESS_THAN_EQUAL) {
138            return result <= 0;
139        } else if (this == EXISTS) {
140            return rhs != null;
141        } else if (this == DOES_NOT_EXIST) {
142            return rhs == null;
143        }
144        throw new IllegalStateException("Invalid comparison operator detected: " + this);
145        }
146
147
148    /**
149     * Operator codes, unmodifiable Collection
150     */
151    public static final Collection<String> OPERATOR_CODES;
152
153    /**
154     * Operator names, unmodifiable Collection
155     */
156    public static final Collection<String> OPERATOR_NAMES;
157
158    static {
159        List<String> operatorCodes = new ArrayList<String>();
160        List<String> operatorNames = new ArrayList<String>();
161
162        for (ComparisonOperator operator : values()) {
163            operatorCodes.add(operator.getCode());
164            operatorNames.add(operator.name());
165        }
166
167        OPERATOR_CODES = Collections.unmodifiableCollection(operatorCodes);
168        OPERATOR_NAMES = Collections.unmodifiableCollection(operatorNames);
169    }
170
171    public void setComparisonOperatorService(ComparisonOperatorService comparisonOperatorService) {
172        this.comparisonOperatorService = comparisonOperatorService;
173    }
174
175    /**
176     *
177     * @return type code
178     */
179    @Override
180    public String toString(){
181        return code;
182    }
183
184    static final class Adapter extends EnumStringAdapter<ComparisonOperator> {
185
186        @Override
187        protected Class<ComparisonOperator> getEnumClass() {
188            return ComparisonOperator.class;
189        }
190    }
191}