1 /**
2 * Copyright 2005-2012 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.krms.framework.engine.expression;
17
18 import org.kuali.rice.core.api.mo.common.Coded;
19 import org.kuali.rice.core.api.util.jaxb.EnumStringAdapter;
20 import org.kuali.rice.krms.api.KrmsApiServiceLocator;
21 import org.kuali.rice.krms.api.engine.expression.ComparisonOperatorService;
22
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26
27 /**
28 * Operators enumeration for comparing objects. EQUALS NOT_EQUALS GREATER_THAN GREATER_THAN_EQUAL LESS_THAN LESS_THAN_EQUAL.
29 * Uses registered {@link EngineComparatorExtension} for the given objects or the {@link DefaultComparisonOperator}.
30 *
31 * @author Kuali Rice Team (rice.collab@kuali.org)
32 */
33 public enum ComparisonOperator implements Coded {
34
35 /**
36 * use this flag with the static factory to get a {@link ComparisonOperator} EQUALS
37 */
38 EQUALS("="),
39
40 /**
41 * use this flag with the static factory to get a {@link ComparisonOperator} NOT_EQUALS
42 */
43 NOT_EQUALS("!="),
44
45 /**
46 * use this flag with the static factory to get a {@link ComparisonOperator} GREATER_THAN
47 */
48 GREATER_THAN(">"),
49
50 /**
51 * use this flag with the static factory to get a {@link ComparisonOperator} GREATER_THAN_EQUAL
52 */
53 GREATER_THAN_EQUAL(">="),
54
55 /**
56 * use this flag with the static factory to get a {@link ComparisonOperator} LESS_THAN
57 */
58 LESS_THAN("<"),
59
60 /**
61 * use this flag with the static factory to get a {@link ComparisonOperator} LESS_THAN_EQUAL
62 */
63 LESS_THAN_EQUAL("<=");
64
65 private final String code;
66
67 /**
68 * Create a ComparisonOperator from the given code
69 * @param code code the ComparisonOperator should be of.
70 */
71 private ComparisonOperator(String code) {
72 this.code = code;
73 }
74
75 /**
76 *
77 * @return code representing the type of operator
78 */
79 @Override
80 public String getCode() {
81 return code;
82 }
83
84 /**
85 * Create a ComparisonOperator from the given code
86 * @param code for type of ComparisonOperator to create
87 * @return a ComparisonOperator created with the given code.
88 * @throws IllegalArgumentException if the given code does not exist
89 */
90 public static ComparisonOperator fromCode(String code) {
91 if (code == null) {
92 return null;
93 }
94 for (ComparisonOperator comparisonOperator : values()) {
95 if (comparisonOperator.code.equals(code)) {
96 return comparisonOperator;
97 }
98 }
99 throw new IllegalArgumentException("Failed to locate the ComparisionOperator with the given code: " + code);
100 }
101
102 /**
103 * Compare the given objects
104 * @param lhs left hand side object
105 * @param rhs right hand side object
106 * @return boolean value of comparison results based on the type of operator.
107 */
108 public boolean compare(Object lhs, Object rhs) {
109 EngineComparatorExtension extension = determineComparatorOperator(lhs, rhs);
110
111 int result = extension.compare(lhs, rhs);
112
113 if (this == EQUALS) {
114 return result == 0;
115 } else if (this == NOT_EQUALS) {
116 return result != 0;
117 } else if (this == GREATER_THAN) {
118 return result > 0;
119 } else if (this == GREATER_THAN_EQUAL) {
120 return result >= 0;
121 } else if (this == LESS_THAN) {
122 return result < 0;
123 } else if (this == LESS_THAN_EQUAL) {
124 return result <= 0;
125 }
126 throw new IllegalStateException("Invalid comparison operator detected: " + this);
127 }
128
129 /**
130 * Return registered {@link EngineComparatorExtension} for the given objects or the {@link DefaultComparisonOperator}.
131 * @param lhs left hand side object
132 * @param rhs right hand side object
133 * @return EngineComparatorExtension
134 */
135 // TODO EGHM move to utility class, or service if new possible breakage is okay. AgendaEditorController has similar code with different extension
136 private EngineComparatorExtension determineComparatorOperator(Object lhs, Object rhs) {
137 EngineComparatorExtension extension = null;
138 try {
139 // If instance is of a registered type, use configured ComparisonOperator
140 // KrmsAttributeDefinitionService service = KRMSServiceLocatorInternal.getService("comparisonOperatorRegistration"); // lotta moves
141 ComparisonOperatorService service = KrmsApiServiceLocator.getComparisonOperatorService();
142 if (service.canCompare(lhs, rhs)) {
143 extension = service.findComparatorExtension(lhs, rhs); // maybe better to get result from service?
144 }
145 } catch (Exception e) {
146 e.printStackTrace(); // TODO EGHM log
147 }
148 if (extension == null) {
149 // It's tempting to have findStringCoercionExtension return this default, but if the Service lookup fails we
150 // will be broken in a new way. Would that be okay? - EGHM
151 extension = new DefaultComparisonOperator();
152 }
153 return extension;
154 }
155
156 /**
157 * Operator codes, unmodifiable Collection
158 */
159 public static final Collection<String> OPERATOR_CODES =
160 Collections.unmodifiableCollection(Arrays.asList(EQUALS.getCode(), NOT_EQUALS.getCode(), GREATER_THAN.getCode(),
161 GREATER_THAN_EQUAL.getCode(), LESS_THAN.getCode(), LESS_THAN_EQUAL.getCode()));
162
163 /**
164 * Operator names, unmodifiable Collection
165 */
166 public static final Collection<String> OPERATOR_NAMES =
167 Collections.unmodifiableCollection(Arrays.asList(EQUALS.name(), NOT_EQUALS.name(), GREATER_THAN.name(),
168 GREATER_THAN_EQUAL.name(), LESS_THAN.name(), LESS_THAN_EQUAL.name()));
169
170 /**
171 *
172 * @return type code
173 */
174 @Override
175 public String toString(){
176 return code;
177 }
178
179 static final class Adapter extends EnumStringAdapter<ComparisonOperator> {
180
181 @Override
182 protected Class<ComparisonOperator> getEnumClass() {
183 return ComparisonOperator.class;
184 }
185 }
186 }