001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.el.lang;
019:
020: import java.beans.PropertyEditor;
021: import java.beans.PropertyEditorManager;
022: import java.math.BigDecimal;
023: import java.math.BigInteger;
024:
025: import javax.el.ELException;
026: import javax.el.PropertyNotFoundException;
027:
028: import org.apache.el.util.MessageFactory;
029:
030: /**
031: * A helper class that implements the EL Specification
032: *
033: * @author Jacob Hookom [jacob@hookom.net]
034: * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: remm $
035: */
036: public class ELSupport {
037:
038: private final static ELSupport REF = new ELSupport();
039:
040: private final static Long ZERO = new Long(0L);
041:
042: public final static void throwUnhandled(Object base, Object property)
043: throws ELException {
044: if (base == null) {
045: throw new PropertyNotFoundException(MessageFactory.get(
046: "error.resolver.unhandled.null", property));
047: } else {
048: throw new PropertyNotFoundException(MessageFactory.get(
049: "error.resolver.unhandled", base.getClass(),
050: property));
051: }
052: }
053:
054: /**
055: * @param obj0
056: * @param obj1
057: * @return
058: * @throws EvaluationException
059: */
060: public final static int compare(final Object obj0, final Object obj1)
061: throws ELException {
062: if (obj0 == obj1 || equals(obj0, obj1)) {
063: return 0;
064: }
065: if (isBigDecimalOp(obj0, obj1)) {
066: BigDecimal bd0 = (BigDecimal) coerceToNumber(obj0,
067: BigDecimal.class);
068: BigDecimal bd1 = (BigDecimal) coerceToNumber(obj1,
069: BigDecimal.class);
070: return bd0.compareTo(bd1);
071: }
072: if (isDoubleOp(obj0, obj1)) {
073: Double d0 = (Double) coerceToNumber(obj0, Double.class);
074: Double d1 = (Double) coerceToNumber(obj1, Double.class);
075: return d0.compareTo(d1);
076: }
077: if (isBigIntegerOp(obj0, obj1)) {
078: BigInteger bi0 = (BigInteger) coerceToNumber(obj0,
079: BigInteger.class);
080: BigInteger bi1 = (BigInteger) coerceToNumber(obj1,
081: BigInteger.class);
082: return bi0.compareTo(bi1);
083: }
084: if (isLongOp(obj0, obj1)) {
085: Long l0 = (Long) coerceToNumber(obj0, Long.class);
086: Long l1 = (Long) coerceToNumber(obj1, Long.class);
087: return l0.compareTo(l1);
088: }
089: if (obj0 instanceof String || obj1 instanceof String) {
090: return coerceToString(obj0).compareTo(coerceToString(obj1));
091: }
092: if (obj0 instanceof Comparable) {
093: return (obj1 != null) ? ((Comparable) obj0).compareTo(obj1)
094: : 1;
095: }
096: if (obj1 instanceof Comparable) {
097: return (obj0 != null) ? -((Comparable) obj1)
098: .compareTo(obj0) : -1;
099: }
100: throw new ELException(MessageFactory.get("error.compare", obj0,
101: obj1));
102: }
103:
104: /**
105: * @param obj0
106: * @param obj1
107: * @return
108: * @throws EvaluationException
109: */
110: public final static boolean equals(final Object obj0,
111: final Object obj1) throws ELException {
112: if (obj0 == obj1) {
113: return true;
114: } else if (obj0 == null || obj1 == null) {
115: return false;
116: } else if (obj0 instanceof Boolean || obj1 instanceof Boolean) {
117: return coerceToBoolean(obj0).equals(coerceToBoolean(obj1));
118: } else if (obj0.getClass().isEnum()) {
119: return obj0.equals(coerceToEnum(obj1, obj0.getClass()));
120: } else if (obj1.getClass().isEnum()) {
121: return obj1.equals(coerceToEnum(obj0, obj1.getClass()));
122: } else if (obj0 instanceof String || obj1 instanceof String) {
123: int lexCompare = coerceToString(obj0).compareTo(
124: coerceToString(obj1));
125: return (lexCompare == 0) ? true : false;
126: }
127: if (isBigDecimalOp(obj0, obj1)) {
128: BigDecimal bd0 = (BigDecimal) coerceToNumber(obj0,
129: BigDecimal.class);
130: BigDecimal bd1 = (BigDecimal) coerceToNumber(obj1,
131: BigDecimal.class);
132: return bd0.equals(bd1);
133: }
134: if (isDoubleOp(obj0, obj1)) {
135: Double d0 = (Double) coerceToNumber(obj0, Double.class);
136: Double d1 = (Double) coerceToNumber(obj1, Double.class);
137: return d0.equals(d1);
138: }
139: if (isBigIntegerOp(obj0, obj1)) {
140: BigInteger bi0 = (BigInteger) coerceToNumber(obj0,
141: BigInteger.class);
142: BigInteger bi1 = (BigInteger) coerceToNumber(obj1,
143: BigInteger.class);
144: return bi0.equals(bi1);
145: }
146: if (isLongOp(obj0, obj1)) {
147: Long l0 = (Long) coerceToNumber(obj0, Long.class);
148: Long l1 = (Long) coerceToNumber(obj1, Long.class);
149: return l0.equals(l1);
150: } else {
151: return obj0.equals(obj1);
152: }
153: }
154:
155: /**
156: * @param obj
157: * @param type
158: * @return
159: */
160: public final static Enum coerceToEnum(final Object obj, Class type) {
161: if (obj == null || "".equals(obj)) {
162: return null;
163: }
164: if (obj.getClass().isEnum()) {
165: return (Enum) obj;
166: }
167: return Enum.valueOf(type, obj.toString());
168: }
169:
170: /**
171: * @param obj
172: * @return
173: */
174: public final static Boolean coerceToBoolean(final Object obj)
175: throws IllegalArgumentException {
176: if (obj == null || "".equals(obj)) {
177: return Boolean.FALSE;
178: }
179: if (obj instanceof Boolean || obj.getClass() == Boolean.TYPE) {
180: return (Boolean) obj;
181: }
182: if (obj instanceof String) {
183: return Boolean.valueOf((String) obj);
184: }
185:
186: throw new IllegalArgumentException(MessageFactory.get(
187: "error.convert", obj, obj.getClass(), Boolean.class));
188: }
189:
190: public final static Character coerceToCharacter(final Object obj)
191: throws IllegalArgumentException {
192: if (obj == null || "".equals(obj)) {
193: return new Character((char) 0);
194: }
195: if (obj instanceof String) {
196: return new Character(((String) obj).charAt(0));
197: }
198: if (ELArithmetic.isNumber(obj)) {
199: return new Character((char) ((Number) obj).shortValue());
200: }
201: Class objType = obj.getClass();
202: if (obj instanceof Character || objType == Character.TYPE) {
203: return (Character) obj;
204: }
205:
206: throw new IllegalArgumentException(MessageFactory.get(
207: "error.convert", obj, objType, Character.class));
208: }
209:
210: public final static Number coerceToNumber(final Object obj) {
211: if (obj == null) {
212: return ZERO;
213: } else if (obj instanceof Number) {
214: return (Number) obj;
215: } else {
216: String str = coerceToString(obj);
217: if (isStringFloat(str)) {
218: return toFloat(str);
219: } else {
220: return toNumber(str);
221: }
222: }
223: }
224:
225: protected final static Number coerceToNumber(final Number number,
226: final Class type) throws IllegalArgumentException {
227: if (Long.TYPE == type || Long.class.equals(type)) {
228: return new Long(number.longValue());
229: }
230: if (Double.TYPE == type || Double.class.equals(type)) {
231: return new Double(number.doubleValue());
232: }
233: if (Integer.TYPE == type || Integer.class.equals(type)) {
234: return new Integer(number.intValue());
235: }
236: if (BigInteger.class.equals(type)) {
237: if (number instanceof BigDecimal) {
238: return ((BigDecimal) number).toBigInteger();
239: }
240: return BigInteger.valueOf(number.longValue());
241: }
242: if (BigDecimal.class.equals(type)) {
243: if (number instanceof BigInteger) {
244: return new BigDecimal((BigInteger) number);
245: }
246: return new BigDecimal(number.doubleValue());
247: }
248: if (Byte.TYPE == type || Byte.class.equals(type)) {
249: return new Byte(number.byteValue());
250: }
251: if (Short.TYPE == type || Short.class.equals(type)) {
252: return new Short(number.shortValue());
253: }
254: if (Float.TYPE == type || Float.class.equals(type)) {
255: return new Float(number.floatValue());
256: }
257:
258: throw new IllegalArgumentException(MessageFactory.get(
259: "error.convert", number, number.getClass(), type));
260: }
261:
262: public final static Number coerceToNumber(final Object obj,
263: final Class type) throws IllegalArgumentException {
264: if (obj == null || "".equals(obj)) {
265: return coerceToNumber(ZERO, type);
266: }
267: if (obj instanceof String) {
268: return coerceToNumber((String) obj, type);
269: }
270: if (ELArithmetic.isNumber(obj)) {
271: return coerceToNumber((Number) obj, type);
272: }
273:
274: Class objType = obj.getClass();
275: if (Character.class.equals(objType)
276: || Character.TYPE == objType) {
277: return coerceToNumber(new Short((short) ((Character) obj)
278: .charValue()), type);
279: }
280:
281: throw new IllegalArgumentException(MessageFactory.get(
282: "error.convert", obj, objType, type));
283: }
284:
285: protected final static Number coerceToNumber(final String val,
286: final Class type) throws IllegalArgumentException {
287: if (Long.TYPE == type || Long.class.equals(type)) {
288: return Long.valueOf(val);
289: }
290: if (Integer.TYPE == type || Integer.class.equals(type)) {
291: return Integer.valueOf(val);
292: }
293: if (Double.TYPE == type || Double.class.equals(type)) {
294: return Double.valueOf(val);
295: }
296: if (BigInteger.class.equals(type)) {
297: return new BigInteger(val);
298: }
299: if (BigDecimal.class.equals(type)) {
300: return new BigDecimal(val);
301: }
302: if (Byte.TYPE == type || Byte.class.equals(type)) {
303: return Byte.valueOf(val);
304: }
305: if (Short.TYPE == type || Short.class.equals(type)) {
306: return Short.valueOf(val);
307: }
308: if (Float.TYPE == type || Float.class.equals(type)) {
309: return Float.valueOf(val);
310: }
311:
312: throw new IllegalArgumentException(MessageFactory.get(
313: "error.convert", val, String.class, type));
314: }
315:
316: /**
317: * @param obj
318: * @return
319: */
320: public final static String coerceToString(final Object obj) {
321: if (obj == null) {
322: return "";
323: } else if (obj instanceof String) {
324: return (String) obj;
325: } else if (obj instanceof Enum) {
326: return ((Enum) obj).name();
327: } else {
328: return obj.toString();
329: }
330: }
331:
332: public final static void checkType(final Object obj,
333: final Class type) throws IllegalArgumentException {
334: if (String.class.equals(type)) {
335: coerceToString(obj);
336: }
337: if (ELArithmetic.isNumberType(type)) {
338: coerceToNumber(obj, type);
339: }
340: if (Character.class.equals(type) || Character.TYPE == type) {
341: coerceToCharacter(obj);
342: }
343: if (Boolean.class.equals(type) || Boolean.TYPE == type) {
344: coerceToBoolean(obj);
345: }
346: if (type.isEnum()) {
347: coerceToEnum(obj, type);
348: }
349: }
350:
351: public final static Object coerceToType(final Object obj,
352: final Class type) throws IllegalArgumentException {
353: if (type == null || Object.class.equals(type)) {
354: return obj;
355: }
356: if (String.class.equals(type)) {
357: return coerceToString(obj);
358: }
359: if (ELArithmetic.isNumberType(type)) {
360: return coerceToNumber(obj, type);
361: }
362: if (Character.class.equals(type) || Character.TYPE == type) {
363: return coerceToCharacter(obj);
364: }
365: if (Boolean.class.equals(type) || Boolean.TYPE == type) {
366: return coerceToBoolean(obj);
367: }
368: if (obj != null && type.isAssignableFrom(obj.getClass())) {
369: return obj;
370: }
371: if (type.isEnum()) {
372: return coerceToEnum(obj, type);
373: }
374:
375: // new to spec
376: if (obj == null)
377: return null;
378: if (obj instanceof String) {
379: if ("".equals(obj))
380: return null;
381: PropertyEditor editor = PropertyEditorManager
382: .findEditor(type);
383: if (editor != null) {
384: editor.setAsText((String) obj);
385: return editor.getValue();
386: }
387: }
388: throw new IllegalArgumentException(MessageFactory.get(
389: "error.convert", obj, obj.getClass(), type));
390: }
391:
392: /**
393: * @param obj
394: * @return
395: */
396: public final static boolean containsNulls(final Object[] obj) {
397: for (int i = 0; i < obj.length; i++) {
398: if (obj[0] == null) {
399: return true;
400: }
401: }
402: return false;
403: }
404:
405: public final static boolean isBigDecimalOp(final Object obj0,
406: final Object obj1) {
407: return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
408: }
409:
410: public final static boolean isBigIntegerOp(final Object obj0,
411: final Object obj1) {
412: return (obj0 instanceof BigInteger || obj1 instanceof BigInteger);
413: }
414:
415: public final static boolean isDoubleOp(final Object obj0,
416: final Object obj1) {
417: return (obj0 instanceof Double
418: || obj1 instanceof Double
419: || obj0 instanceof Float
420: || obj1 instanceof Float
421: || (obj0 != null && (Double.TYPE == obj0.getClass() || Float.TYPE == obj0
422: .getClass())) || (obj1 != null && (Double.TYPE == obj1
423: .getClass() || Float.TYPE == obj1.getClass())));
424: }
425:
426: public final static boolean isDoubleStringOp(final Object obj0,
427: final Object obj1) {
428: return (isDoubleOp(obj0, obj1)
429: || (obj0 instanceof String && isStringFloat((String) obj0)) || (obj1 instanceof String && isStringFloat((String) obj1)));
430: }
431:
432: public final static boolean isLongOp(final Object obj0,
433: final Object obj1) {
434: return (obj0 instanceof Long
435: || obj1 instanceof Long
436: || obj0 instanceof Integer
437: || obj1 instanceof Integer
438: || obj0 instanceof Character
439: || obj1 instanceof Character
440: || obj0 instanceof Short
441: || obj1 instanceof Short
442: || obj0 instanceof Byte
443: || obj1 instanceof Byte
444: || (obj0 != null && (Long.TYPE == obj0.getClass()
445: || Integer.TYPE == obj0.getClass()
446: || Character.TYPE == obj0.getClass()
447: || Short.TYPE == obj0.getClass() || Byte.TYPE == obj0
448: .getClass())) || (obj0 != null && (Long.TYPE == obj0
449: .getClass()
450: || Integer.TYPE == obj0.getClass()
451: || Character.TYPE == obj0.getClass()
452: || Short.TYPE == obj0.getClass() || Byte.TYPE == obj0
453: .getClass())));
454: }
455:
456: public final static boolean isStringFloat(final String str) {
457: int len = str.length();
458: if (len > 1) {
459: char c = 0;
460: for (int i = 0; i < len; i++) {
461: switch (c = str.charAt(i)) {
462: case 'E':
463: return true;
464: case 'e':
465: return true;
466: case '.':
467: return true;
468: }
469: }
470: }
471: return false;
472: }
473:
474: public final static Number toFloat(final String value) {
475: try {
476: if (Double.parseDouble(value) > Double.MAX_VALUE) {
477: return new BigDecimal(value);
478: } else {
479: return new Double(value);
480: }
481: } catch (NumberFormatException e0) {
482: return new BigDecimal(value);
483: }
484: }
485:
486: public final static Number toNumber(final String value) {
487: try {
488: return new Integer(Integer.parseInt(value));
489: } catch (NumberFormatException e0) {
490: try {
491: return new Long(Long.parseLong(value));
492: } catch (NumberFormatException e1) {
493: return new BigInteger(value);
494: }
495: }
496: }
497:
498: /**
499: *
500: */
501: public ELSupport() {
502: super();
503: }
504:
505: }
|