001: /*
002: * Copyright 2006, 2007 Odysseus Software GmbH
003: *
004: * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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: */
016: package de.odysseus.el.misc;
017:
018: import java.math.BigDecimal;
019: import java.math.BigInteger;
020: import java.util.Collection;
021: import java.util.HashSet;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import javax.el.ELException;
026:
027: public class BooleanOperations {
028: private final static Set<Class<? extends Number>> SIMPLE_INTEGER_TYPES = new HashSet<Class<? extends Number>>();
029: private final static Set<Class<? extends Number>> SIMPLE_FLOAT_TYPES = new HashSet<Class<? extends Number>>();
030:
031: static {
032: SIMPLE_INTEGER_TYPES.add(Byte.class);
033: SIMPLE_INTEGER_TYPES.add(Short.class);
034: SIMPLE_INTEGER_TYPES.add(Integer.class);
035: SIMPLE_INTEGER_TYPES.add(Long.class);
036: SIMPLE_FLOAT_TYPES.add(Float.class);
037: SIMPLE_FLOAT_TYPES.add(Double.class);
038: }
039:
040: private static final BigDecimal toBigDecimal(Object value) {
041: return TypeConversions.coerceToNumber(value, BigDecimal.class);
042: }
043:
044: private static final BigInteger toBigInteger(Object value) {
045: return TypeConversions.coerceToNumber(value, BigInteger.class);
046: }
047:
048: private static final long toLong(Object value) {
049: return TypeConversions.coerceToNumber(value, Long.class)
050: .longValue();
051: }
052:
053: private static final double toDouble(Object value) {
054: return TypeConversions.coerceToNumber(value, Double.class)
055: .doubleValue();
056: }
057:
058: private static final String toString(Object value) {
059: return TypeConversions.coerceToString(value);
060: }
061:
062: private static final boolean toBoolean(Object value) {
063: return TypeConversions.coerceToBoolean(value).booleanValue();
064: }
065:
066: @SuppressWarnings("unchecked")
067: private static final Enum toEnum(Object value,
068: Class<? extends Enum> type) {
069: return TypeConversions.coerceToEnum(value, type);
070: }
071:
072: @SuppressWarnings("unchecked")
073: private static final boolean lt0(Object o1, Object o2) {
074: Class<?> t1 = o1.getClass();
075: Class<?> t2 = o2.getClass();
076: if (BigDecimal.class.isAssignableFrom(t1)
077: || BigDecimal.class.isAssignableFrom(t2)) {
078: return toBigDecimal(o1).compareTo(toBigDecimal(o2)) < 0;
079: }
080: if (SIMPLE_FLOAT_TYPES.contains(t1)
081: || SIMPLE_FLOAT_TYPES.contains(t2)) {
082: return toDouble(o1) < toDouble(o2);
083: }
084: if (BigInteger.class.isAssignableFrom(t1)
085: || BigInteger.class.isAssignableFrom(t2)) {
086: return toBigInteger(o1).compareTo(toBigInteger(o2)) < 0;
087: }
088: if (SIMPLE_INTEGER_TYPES.contains(t1)
089: || SIMPLE_INTEGER_TYPES.contains(t2)) {
090: return toLong(o1) < toLong(o2);
091: }
092: if (t1 == String.class || t2 == String.class) {
093: return toString(o1).compareTo(toString(o2)) < 0;
094: }
095: if (o1 instanceof Comparable) {
096: return ((Comparable) o1).compareTo(o2) < 0;
097: }
098: if (o2 instanceof Comparable) {
099: return ((Comparable) o2).compareTo(o1) > 0;
100: }
101: throw new ELException(LocalMessages.get("error.compare.types",
102: o1.getClass(), o2.getClass()));
103: }
104:
105: @SuppressWarnings("unchecked")
106: private static final boolean gt0(Object o1, Object o2) {
107: Class<?> t1 = o1.getClass();
108: Class<?> t2 = o2.getClass();
109: if (BigDecimal.class.isAssignableFrom(t1)
110: || BigDecimal.class.isAssignableFrom(t2)) {
111: return toBigDecimal(o1).compareTo(toBigDecimal(o2)) > 0;
112: }
113: if (SIMPLE_FLOAT_TYPES.contains(t1)
114: || SIMPLE_FLOAT_TYPES.contains(t2)) {
115: return toDouble(o1) > toDouble(o2);
116: }
117: if (BigInteger.class.isAssignableFrom(t1)
118: || BigInteger.class.isAssignableFrom(t2)) {
119: return toBigInteger(o1).compareTo(toBigInteger(o2)) > 0;
120: }
121: if (SIMPLE_INTEGER_TYPES.contains(t1)
122: || SIMPLE_INTEGER_TYPES.contains(t2)) {
123: return toLong(o1) > toLong(o2);
124: }
125: if (t1 == String.class || t2 == String.class) {
126: return toString(o1).compareTo(toString(o2)) > 0;
127: }
128: if (o1 instanceof Comparable) {
129: return ((Comparable) o1).compareTo(o2) > 0;
130: }
131: if (o2 instanceof Comparable) {
132: return ((Comparable) o2).compareTo(o1) < 0;
133: }
134: throw new ELException(LocalMessages.get("error.compare.types",
135: o1.getClass(), o2.getClass()));
136: }
137:
138: public static final boolean lt(Object o1, Object o2) {
139: if (o1 == o2) {
140: return false;
141: }
142: if (o1 == null || o2 == null) {
143: return false;
144: }
145: return lt0(o1, o2);
146: }
147:
148: public static final boolean gt(Object o1, Object o2) {
149: if (o1 == o2) {
150: return false;
151: }
152: if (o1 == null || o2 == null) {
153: return false;
154: }
155: return gt0(o1, o2);
156: }
157:
158: public static final boolean ge(Object o1, Object o2) {
159: if (o1 == o2) {
160: return true;
161: }
162: if (o1 == null || o2 == null) {
163: return false;
164: }
165: return !lt0(o1, o2);
166: }
167:
168: public static final boolean le(Object o1, Object o2) {
169: if (o1 == o2) {
170: return true;
171: }
172: if (o1 == null || o2 == null) {
173: return false;
174: }
175: return !gt0(o1, o2);
176: }
177:
178: public static final boolean eq(Object o1, Object o2) {
179: if (o1 == o2) {
180: return true;
181: }
182: if (o1 == null || o2 == null) {
183: return false;
184: }
185: Class<?> t1 = o1.getClass();
186: Class<?> t2 = o2.getClass();
187: if (BigDecimal.class.isAssignableFrom(t1)
188: || BigDecimal.class.isAssignableFrom(t2)) {
189: return toBigDecimal(o1).equals(toBigDecimal(o2));
190: }
191: if (SIMPLE_FLOAT_TYPES.contains(t1)
192: || SIMPLE_FLOAT_TYPES.contains(t2)) {
193: return toDouble(o1) == toDouble(o2);
194: }
195: if (BigInteger.class.isAssignableFrom(t1)
196: || BigInteger.class.isAssignableFrom(t2)) {
197: return toBigInteger(o1).equals(toBigInteger(o2));
198: }
199: if (SIMPLE_INTEGER_TYPES.contains(t1)
200: || SIMPLE_INTEGER_TYPES.contains(t2)) {
201: return toLong(o1) == toLong(o2);
202: }
203: if (t1 == Boolean.class || t2 == Boolean.class) {
204: return toBoolean(o1) == toBoolean(o2);
205: }
206: if (o1 instanceof Enum) {
207: return o1 == toEnum(o2, ((Enum) o1).getClass());
208: }
209: if (o2 instanceof Enum) {
210: return toEnum(o1, ((Enum) o2).getClass()) == o2;
211: }
212: if (t1 == String.class || t2 == String.class) {
213: return toString(o1).equals(toString(o2));
214: }
215: return o1.equals(o2);
216: }
217:
218: public static final boolean ne(Object o1, Object o2) {
219: return !eq(o1, o2);
220: }
221:
222: public static final boolean and(Object o1, Object o2) {
223: return toBoolean(o1) && toBoolean(o2);
224: }
225:
226: public static final boolean or(Object o1, Object o2) {
227: return toBoolean(o1) || toBoolean(o2);
228: }
229:
230: public static final boolean not(Object o) {
231: return !toBoolean(o);
232: }
233:
234: public static final boolean empty(Object o) {
235: if (o == null || "".equals(o)) {
236: return true;
237: }
238: if (o instanceof Object[]) {
239: return ((Object[]) o).length == 0;
240: }
241: if (o instanceof Map) {
242: return ((Map) o).isEmpty();
243: }
244: if (o instanceof Collection) {
245: return ((Collection) o).isEmpty();
246: }
247: return false;
248: }
249: }
|