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:
021: import javax.el.ELException;
022:
023: /**
024: * Arithmetic Operations as specified in chapter 1.7.
025: *
026: * @author Christoph Beck
027: */
028: public class NumberOperations {
029: private final static Long LONG_ZERO = Long.valueOf(0L);
030:
031: private final static boolean isDotEe(String value) {
032: int length = value.length();
033: for (int i = 0; i < length; i++) {
034: switch (value.charAt(i)) {
035: case '.':
036: case 'E':
037: case 'e':
038: return true;
039: }
040: }
041: return false;
042: }
043:
044: private final static boolean isDotEe(Object value) {
045: return value instanceof String && isDotEe((String) value);
046: }
047:
048: private static final boolean isFloatOrDouble(Object value) {
049: return value instanceof Float || value instanceof Double;
050: }
051:
052: private static final boolean isFloatOrDoubleOrDotEe(Object value) {
053: return isFloatOrDouble(value) || isDotEe(value);
054: }
055:
056: private static final boolean isBigDecimalOrBigInteger(Object value) {
057: return value instanceof BigDecimal
058: || value instanceof BigInteger;
059: }
060:
061: private static final boolean isBigDecimalOrFloatOrDoubleOrDotEe(
062: Object value) {
063: return value instanceof BigDecimal
064: || isFloatOrDoubleOrDotEe(value);
065: }
066:
067: private static final BigDecimal toBigDecimal(Object value) {
068: return TypeConversions.coerceToNumber(value, BigDecimal.class);
069: }
070:
071: private static final BigInteger toBigInteger(Object value) {
072: return TypeConversions.coerceToNumber(value, BigInteger.class);
073: }
074:
075: private static final Double toDouble(Object value) {
076: return TypeConversions.coerceToNumber(value, Double.class);
077: }
078:
079: private static final Long toLong(Object value) {
080: return TypeConversions.coerceToNumber(value, Long.class);
081: }
082:
083: public static final Number add(Object o1, Object o2) {
084: if (o1 == null && o2 == null) {
085: return LONG_ZERO;
086: }
087: if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
088: return toBigDecimal(o1).add(toBigDecimal(o2));
089: }
090: if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
091: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
092: return toBigDecimal(o1).add(toBigDecimal(o2));
093: }
094: return toDouble(o1) + toDouble(o2);
095: }
096: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
097: return toBigInteger(o1).add(toBigInteger(o2));
098: }
099: return toLong(o1) + toLong(o2);
100: }
101:
102: public static final Number sub(Object o1, Object o2) {
103: if (o1 == null && o2 == null) {
104: return LONG_ZERO;
105: }
106: if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
107: return toBigDecimal(o1).subtract(toBigDecimal(o2));
108: }
109: if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
110: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
111: return toBigDecimal(o1).subtract(toBigDecimal(o2));
112: }
113: return toDouble(o1) - toDouble(o2);
114: }
115: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
116: return toBigInteger(o1).subtract(toBigInteger(o2));
117: }
118: return toLong(o1) - toLong(o2);
119: }
120:
121: public static final Number mul(Object o1, Object o2) {
122: if (o1 == null && o2 == null) {
123: return LONG_ZERO;
124: }
125: if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
126: return toBigDecimal(o1).multiply(toBigDecimal(o2));
127: }
128: if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
129: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
130: return toBigDecimal(o1).multiply(toBigDecimal(o2));
131: }
132: return toDouble(o1) * toDouble(o2);
133: }
134: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
135: return toBigInteger(o1).multiply(toBigInteger(o2));
136: }
137: return toLong(o1) * toLong(o2);
138: }
139:
140: public static final Number div(Object o1, Object o2) {
141: if (o1 == null && o2 == null) {
142: return LONG_ZERO;
143: }
144: if (isBigDecimalOrBigInteger(o1)
145: || isBigDecimalOrBigInteger(o2)) {
146: return toBigDecimal(o1).divide(toBigDecimal(o2),
147: BigDecimal.ROUND_HALF_UP);
148: }
149: return toDouble(o1) / toDouble(o2);
150: }
151:
152: public static final Number mod(Object o1, Object o2) {
153: if (o1 == null && o2 == null) {
154: return LONG_ZERO;
155: }
156: if (isBigDecimalOrFloatOrDoubleOrDotEe(o1)
157: || isBigDecimalOrFloatOrDoubleOrDotEe(o2)) {
158: return toDouble(o1) % toDouble(o2);
159: }
160: if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
161: return toBigInteger(o1).remainder(toBigInteger(o2));
162: }
163: return toLong(o1) % toLong(o2);
164: }
165:
166: public static final Number neg(Object value) {
167: if (value == null) {
168: return LONG_ZERO;
169: }
170: if (value instanceof BigDecimal) {
171: return ((BigDecimal) value).negate();
172: }
173: if (value instanceof BigInteger) {
174: return ((BigInteger) value).negate();
175: }
176: if (value instanceof Double) {
177: return Double.valueOf(-((Double) value).doubleValue());
178: }
179: if (value instanceof Float) {
180: return Float.valueOf(-((Float) value).floatValue());
181: }
182: if (value instanceof String) {
183: if (isDotEe((String) value)) {
184: return Double.valueOf(-toDouble(value).doubleValue());
185: }
186: return Long.valueOf(-toLong(value).longValue());
187: }
188: if (value instanceof Long) {
189: return Long.valueOf(-((Long) value).longValue());
190: }
191: if (value instanceof Integer) {
192: return Integer.valueOf(-((Integer) value).intValue());
193: }
194: if (value instanceof Short) {
195: return Short.valueOf((short) -((Short) value).shortValue());
196: }
197: if (value instanceof Byte) {
198: return Byte.valueOf((byte) -((Byte) value).byteValue());
199: }
200: throw new ELException(LocalMessages.get("error.negate", value
201: .getClass()));
202: }
203: }
|