de.odysseus.el.misc.NumberOperations Maven / Gradle / Ivy
/*
* Copyright 2006-2009 Odysseus Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.odysseus.el.misc;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.el.ELException;
/**
* Arithmetic Operations as specified in chapter 1.7.
*
* @author Christoph Beck
*/
public class NumberOperations {
private final static Long LONG_ZERO = Long.valueOf(0L);
private final static boolean isDotEe(String value) {
int length = value.length();
for (int i = 0; i < length; i++) {
switch (value.charAt(i)) {
case '.':
case 'E':
case 'e': return true;
}
}
return false;
}
private final static boolean isDotEe(Object value) {
return value instanceof String && isDotEe((String)value);
}
private static final boolean isFloatOrDouble(Object value) {
return value instanceof Float || value instanceof Double;
}
private static final boolean isFloatOrDoubleOrDotEe(Object value) {
return isFloatOrDouble(value) || isDotEe(value);
}
private static final boolean isBigDecimalOrBigInteger(Object value) {
return value instanceof BigDecimal || value instanceof BigInteger;
}
private static final boolean isBigDecimalOrFloatOrDoubleOrDotEe(Object value) {
return value instanceof BigDecimal || isFloatOrDoubleOrDotEe(value);
}
public static final Number add(TypeConverter converter, Object o1, Object o2) {
if (o1 == null && o2 == null) {
return LONG_ZERO;
}
if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
return converter.convert(o1, BigDecimal.class).add(converter.convert(o2, BigDecimal.class));
}
if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigDecimal.class).add(converter.convert(o2, BigDecimal.class));
}
return converter.convert(o1, Double.class) + converter.convert(o2, Double.class);
}
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigInteger.class).add(converter.convert(o2, BigInteger.class));
}
return converter.convert(o1, Long.class) + converter.convert(o2, Long.class);
}
public static final Number sub(TypeConverter converter, Object o1, Object o2) {
if (o1 == null && o2 == null) {
return LONG_ZERO;
}
if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
return converter.convert(o1, BigDecimal.class).subtract(converter.convert(o2, BigDecimal.class));
}
if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigDecimal.class).subtract(converter.convert(o2, BigDecimal.class));
}
return converter.convert(o1, Double.class) - converter.convert(o2, Double.class);
}
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigInteger.class).subtract(converter.convert(o2, BigInteger.class));
}
return converter.convert(o1, Long.class) - converter.convert(o2, Long.class);
}
public static final Number mul(TypeConverter converter, Object o1, Object o2) {
if (o1 == null && o2 == null) {
return LONG_ZERO;
}
if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) {
return converter.convert(o1, BigDecimal.class).multiply(converter.convert(o2, BigDecimal.class));
}
if (isFloatOrDoubleOrDotEe(o1) || isFloatOrDoubleOrDotEe(o2)) {
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigDecimal.class).multiply(converter.convert(o2, BigDecimal.class));
}
return converter.convert(o1, Double.class) * converter.convert(o2, Double.class);
}
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigInteger.class).multiply(converter.convert(o2, BigInteger.class));
}
return converter.convert(o1, Long.class) * converter.convert(o2, Long.class);
}
public static final Number div(TypeConverter converter, Object o1, Object o2) {
if (o1 == null && o2 == null) {
return LONG_ZERO;
}
if (isBigDecimalOrBigInteger(o1) || isBigDecimalOrBigInteger(o2)) {
return converter.convert(o1, BigDecimal.class).divide(converter.convert(o2, BigDecimal.class), BigDecimal.ROUND_HALF_UP);
}
return converter.convert(o1, Double.class) / converter.convert(o2, Double.class);
}
public static final Number mod(TypeConverter converter, Object o1, Object o2) {
if (o1 == null && o2 == null) {
return LONG_ZERO;
}
if (isBigDecimalOrFloatOrDoubleOrDotEe(o1) || isBigDecimalOrFloatOrDoubleOrDotEe(o2)) {
return converter.convert(o1, Double.class) % converter.convert(o2, Double.class);
}
if (o1 instanceof BigInteger || o2 instanceof BigInteger) {
return converter.convert(o1, BigInteger.class).remainder(converter.convert(o2, BigInteger.class));
}
return converter.convert(o1, Long.class) % converter.convert(o2, Long.class);
}
public static final Number neg(TypeConverter converter, Object value) {
if (value == null) {
return LONG_ZERO;
}
if (value instanceof BigDecimal) {
return ((BigDecimal)value).negate();
}
if (value instanceof BigInteger) {
return ((BigInteger)value).negate();
}
if (value instanceof Double) {
return Double.valueOf(-((Double)value).doubleValue());
}
if (value instanceof Float) {
return Float.valueOf(-((Float)value).floatValue());
}
if (value instanceof String) {
if (isDotEe((String)value)) {
return Double.valueOf(-converter.convert(value, Double.class).doubleValue());
}
return Long.valueOf(-converter.convert(value, Long.class).longValue());
}
if (value instanceof Long) {
return Long.valueOf(-((Long)value).longValue());
}
if (value instanceof Integer) {
return Integer.valueOf(-((Integer)value).intValue());
}
if (value instanceof Short) {
return Short.valueOf((short)-((Short)value).shortValue());
}
if (value instanceof Byte) {
return Byte.valueOf((byte)-((Byte)value).byteValue());
}
throw new ELException(LocalMessages.get("error.negate", value.getClass()));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy