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.math.BigDecimal;
021: import java.math.BigInteger;
022:
023: import org.apache.el.util.MessageFactory;
024:
025: /**
026: * A helper class of Arithmetic defined by the EL Specification
027: * @author Jacob Hookom [jacob@hookom.net]
028: * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: markt $
029: */
030: public abstract class ELArithmetic {
031:
032: public final static class BigDecimalDelegate extends ELArithmetic {
033:
034: protected Number add(Number num0, Number num1) {
035: return ((BigDecimal) num0).add((BigDecimal) num1);
036: }
037:
038: protected Number coerce(Number num) {
039: if (num instanceof BigDecimal)
040: return num;
041: if (num instanceof BigInteger)
042: return new BigDecimal((BigInteger) num);
043: return new BigDecimal(num.doubleValue());
044: }
045:
046: protected Number coerce(String str) {
047: return new BigDecimal(str);
048: }
049:
050: protected Number divide(Number num0, Number num1) {
051: return ((BigDecimal) num0).divide((BigDecimal) num1,
052: BigDecimal.ROUND_HALF_UP);
053: }
054:
055: protected Number subtract(Number num0, Number num1) {
056: return ((BigDecimal) num0).subtract((BigDecimal) num1);
057: }
058:
059: protected Number mod(Number num0, Number num1) {
060: return new Double(num0.doubleValue() % num1.doubleValue());
061: }
062:
063: protected Number multiply(Number num0, Number num1) {
064: return ((BigDecimal) num0).multiply((BigDecimal) num1);
065: }
066:
067: public boolean matches(Object obj0, Object obj1) {
068: return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
069: }
070: }
071:
072: public final static class BigIntegerDelegate extends ELArithmetic {
073:
074: protected Number add(Number num0, Number num1) {
075: return ((BigInteger) num0).add((BigInteger) num1);
076: }
077:
078: protected Number coerce(Number num) {
079: if (num instanceof BigInteger)
080: return num;
081: return new BigInteger(num.toString());
082: }
083:
084: protected Number coerce(String str) {
085: return new BigInteger(str);
086: }
087:
088: protected Number divide(Number num0, Number num1) {
089: return (new BigDecimal((BigInteger) num0)).divide(
090: new BigDecimal((BigInteger) num1),
091: BigDecimal.ROUND_HALF_UP);
092: }
093:
094: protected Number multiply(Number num0, Number num1) {
095: return ((BigInteger) num0).multiply((BigInteger) num1);
096: }
097:
098: protected Number mod(Number num0, Number num1) {
099: return ((BigInteger) num0).mod((BigInteger) num1);
100: }
101:
102: protected Number subtract(Number num0, Number num1) {
103: return ((BigInteger) num0).subtract((BigInteger) num1);
104: }
105:
106: public boolean matches(Object obj0, Object obj1) {
107: return (obj0 instanceof BigInteger || obj1 instanceof BigInteger);
108: }
109: }
110:
111: public final static class DoubleDelegate extends ELArithmetic {
112:
113: protected Number add(Number num0, Number num1) {
114: // could only be one of these
115: if (num0 instanceof BigDecimal) {
116: return ((BigDecimal) num0).add(new BigDecimal(num1
117: .doubleValue()));
118: } else if (num1 instanceof BigDecimal) {
119: return ((new BigDecimal(num0.doubleValue())
120: .add((BigDecimal) num1)));
121: }
122: return new Double(num0.doubleValue() + num1.doubleValue());
123: }
124:
125: protected Number coerce(Number num) {
126: if (num instanceof Double)
127: return num;
128: if (num instanceof BigInteger)
129: return new BigDecimal((BigInteger) num);
130: return new Double(num.doubleValue());
131: }
132:
133: protected Number coerce(String str) {
134: return new Double(str);
135: }
136:
137: protected Number divide(Number num0, Number num1) {
138: return new Double(num0.doubleValue() / num1.doubleValue());
139: }
140:
141: protected Number mod(Number num0, Number num1) {
142: return new Double(num0.doubleValue() % num1.doubleValue());
143: }
144:
145: protected Number subtract(Number num0, Number num1) {
146: // could only be one of these
147: if (num0 instanceof BigDecimal) {
148: return ((BigDecimal) num0).subtract(new BigDecimal(num1
149: .doubleValue()));
150: } else if (num1 instanceof BigDecimal) {
151: return ((new BigDecimal(num0.doubleValue())
152: .subtract((BigDecimal) num1)));
153: }
154: return new Double(num0.doubleValue() - num1.doubleValue());
155: }
156:
157: protected Number multiply(Number num0, Number num1) {
158: // could only be one of these
159: if (num0 instanceof BigDecimal) {
160: return ((BigDecimal) num0).multiply(new BigDecimal(num1
161: .doubleValue()));
162: } else if (num1 instanceof BigDecimal) {
163: return ((new BigDecimal(num0.doubleValue())
164: .multiply((BigDecimal) num1)));
165: }
166: return new Double(num0.doubleValue() * num1.doubleValue());
167: }
168:
169: public boolean matches(Object obj0, Object obj1) {
170: return (obj0 instanceof Double
171: || obj1 instanceof Double
172: || obj0 instanceof Float
173: || obj1 instanceof Float
174: || (obj0 != null && (Double.TYPE == obj0.getClass() || Float.TYPE == obj0
175: .getClass()))
176: || (obj1 != null && (Double.TYPE == obj1.getClass() || Float.TYPE == obj1
177: .getClass()))
178: || (obj0 instanceof String && ELSupport
179: .isStringFloat((String) obj0)) || (obj1 instanceof String && ELSupport
180: .isStringFloat((String) obj1)));
181: }
182: }
183:
184: public final static class LongDelegate extends ELArithmetic {
185:
186: protected Number add(Number num0, Number num1) {
187: return new Long(num0.longValue() + num1.longValue());
188: }
189:
190: protected Number coerce(Number num) {
191: if (num instanceof Long)
192: return num;
193: return new Long(num.longValue());
194: }
195:
196: protected Number coerce(String str) {
197: return new Long(str);
198: }
199:
200: protected Number divide(Number num0, Number num1) {
201: return new Long(num0.longValue() / num1.longValue());
202: }
203:
204: protected Number mod(Number num0, Number num1) {
205: return new Long(num0.longValue() % num1.longValue());
206: }
207:
208: protected Number subtract(Number num0, Number num1) {
209: return new Long(num0.longValue() - num1.longValue());
210: }
211:
212: protected Number multiply(Number num0, Number num1) {
213: return new Long(num0.longValue() * num1.longValue());
214: }
215:
216: public boolean matches(Object obj0, Object obj1) {
217: return (obj0 instanceof Long || obj1 instanceof Long);
218: }
219: }
220:
221: public final static BigDecimalDelegate BIGDECIMAL = new BigDecimalDelegate();
222:
223: public final static BigIntegerDelegate BIGINTEGER = new BigIntegerDelegate();
224:
225: public final static DoubleDelegate DOUBLE = new DoubleDelegate();
226:
227: public final static LongDelegate LONG = new LongDelegate();
228:
229: private final static Long ZERO = new Long(0);
230:
231: public final static Number add(final Object obj0, final Object obj1) {
232: if (obj0 == null && obj1 == null) {
233: return new Long(0);
234: }
235:
236: final ELArithmetic delegate;
237: if (BIGDECIMAL.matches(obj0, obj1))
238: delegate = BIGDECIMAL;
239: else if (DOUBLE.matches(obj0, obj1))
240: delegate = DOUBLE;
241: else if (BIGINTEGER.matches(obj0, obj1))
242: delegate = BIGINTEGER;
243: else
244: delegate = LONG;
245:
246: Number num0 = delegate.coerce(obj0);
247: Number num1 = delegate.coerce(obj1);
248:
249: return delegate.add(num0, num1);
250: }
251:
252: public final static Number mod(final Object obj0, final Object obj1) {
253: if (obj0 == null && obj1 == null) {
254: return new Long(0);
255: }
256:
257: final ELArithmetic delegate;
258: if (BIGDECIMAL.matches(obj0, obj1))
259: delegate = BIGDECIMAL;
260: else if (DOUBLE.matches(obj0, obj1))
261: delegate = DOUBLE;
262: else if (BIGINTEGER.matches(obj0, obj1))
263: delegate = BIGINTEGER;
264: else
265: delegate = LONG;
266:
267: Number num0 = delegate.coerce(obj0);
268: Number num1 = delegate.coerce(obj1);
269:
270: return delegate.mod(num0, num1);
271: }
272:
273: public final static Number subtract(final Object obj0,
274: final Object obj1) {
275: if (obj0 == null && obj1 == null) {
276: return new Long(0);
277: }
278:
279: final ELArithmetic delegate;
280: if (BIGDECIMAL.matches(obj0, obj1))
281: delegate = BIGDECIMAL;
282: else if (DOUBLE.matches(obj0, obj1))
283: delegate = DOUBLE;
284: else if (BIGINTEGER.matches(obj0, obj1))
285: delegate = BIGINTEGER;
286: else
287: delegate = LONG;
288:
289: Number num0 = delegate.coerce(obj0);
290: Number num1 = delegate.coerce(obj1);
291:
292: return delegate.subtract(num0, num1);
293: }
294:
295: public final static Number divide(final Object obj0,
296: final Object obj1) {
297: if (obj0 == null && obj1 == null) {
298: return ZERO;
299: }
300:
301: final ELArithmetic delegate;
302: if (BIGDECIMAL.matches(obj0, obj1))
303: delegate = BIGDECIMAL;
304: else if (BIGINTEGER.matches(obj0, obj1))
305: delegate = BIGDECIMAL;
306: else
307: delegate = DOUBLE;
308:
309: Number num0 = delegate.coerce(obj0);
310: Number num1 = delegate.coerce(obj1);
311:
312: return delegate.divide(num0, num1);
313: }
314:
315: public final static Number multiply(final Object obj0,
316: final Object obj1) {
317: if (obj0 == null && obj1 == null) {
318: return new Long(0);
319: }
320:
321: final ELArithmetic delegate;
322: if (BIGDECIMAL.matches(obj0, obj1))
323: delegate = BIGDECIMAL;
324: else if (DOUBLE.matches(obj0, obj1))
325: delegate = DOUBLE;
326: else if (BIGINTEGER.matches(obj0, obj1))
327: delegate = BIGINTEGER;
328: else
329: delegate = LONG;
330:
331: Number num0 = delegate.coerce(obj0);
332: Number num1 = delegate.coerce(obj1);
333:
334: return delegate.multiply(num0, num1);
335: }
336:
337: public final static boolean isNumber(final Object obj) {
338: return (obj != null && isNumberType(obj.getClass()));
339: }
340:
341: public final static boolean isNumberType(final Class type) {
342: return type == (java.lang.Long.class) || type == Long.TYPE
343: || type == (java.lang.Double.class)
344: || type == Double.TYPE
345: || type == (java.lang.Byte.class) || type == Byte.TYPE
346: || type == (java.lang.Short.class)
347: || type == Short.TYPE
348: || type == (java.lang.Integer.class)
349: || type == Integer.TYPE
350: || type == (java.lang.Float.class)
351: || type == Float.TYPE
352: || type == (java.math.BigInteger.class)
353: || type == (java.math.BigDecimal.class);
354: }
355:
356: /**
357: *
358: */
359: protected ELArithmetic() {
360: super ();
361: }
362:
363: protected abstract Number add(final Number num0, final Number num1);
364:
365: protected abstract Number multiply(final Number num0,
366: final Number num1);
367:
368: protected abstract Number subtract(final Number num0,
369: final Number num1);
370:
371: protected abstract Number mod(final Number num0, final Number num1);
372:
373: protected abstract Number coerce(final Number num);
374:
375: protected final Number coerce(final Object obj) {
376:
377: if (isNumber(obj)) {
378: return coerce((Number) obj);
379: }
380: if (obj instanceof String) {
381: return coerce((String) obj);
382: }
383: if (obj == null || "".equals(obj)) {
384: return coerce(ZERO);
385: }
386:
387: Class objType = obj.getClass();
388: if (Character.class.equals(objType)
389: || Character.TYPE == objType) {
390: return coerce(new Short((short) ((Character) obj)
391: .charValue()));
392: }
393:
394: throw new IllegalArgumentException(MessageFactory.get(
395: "el.convert", obj, objType));
396: }
397:
398: protected abstract Number coerce(final String str);
399:
400: protected abstract Number divide(final Number num0,
401: final Number num1);
402:
403: protected abstract boolean matches(final Object obj0,
404: final Object obj1);
405:
406: }
|