All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.odysseus.el.misc.NumberOperations Maven / Gradle / Ivy

There is a newer version: 2.2.7
Show newest version
/*
 * 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