View Javadoc

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 }