![JAR search and dependency download from the Maven repository](/logo.png)
com.mitchellbosecke.pebble.utils.OperatorUtils Maven / Gradle / Ivy
/*******************************************************************************
* This file is part of Pebble.
*
* Copyright (c) 2014 by Mitchell Bösecke
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
package com.mitchellbosecke.pebble.utils;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Collection;
import java.util.List;
/**
*
* This class acts as a sort of wrapper around Java's built in operators. This
* is necessary because Pebble treats all user provided variables as Objects
* even if they were originally primitives.
*
* It's important that this class mimics the natural type conversion that Java
* will apply when performing operators. This can be found in section 5.6.2 of
* the Java 7 spec, under Binary Numeric Promotion.
*
* @author Mitchell
*
*/
public class OperatorUtils {
private enum Operation {
ADD, SUBTRACT, MULTIPLICATION, DIVISION, MODULUS
}
private enum Comparison {
GREATER_THAN, GREATER_THAN_EQUALS, LESS_THAN, LESS_THAN_EQUALS, EQUALS
}
public static Object add(Object op1, Object op2) {
if (op1 instanceof String || op2 instanceof String) {
return concatenateStrings(String.valueOf(op1), String.valueOf(op2));
} else if (op1 instanceof List) {
return addToList((List>) op1, op2);
}
return wideningConversionBinaryOperation(op1, op2, Operation.ADD);
}
public static Object subtract(Object op1, Object op2) {
if (op1 instanceof List) {
return subtractFromList((List>) op1, op2);
}
return wideningConversionBinaryOperation(op1, op2, Operation.SUBTRACT);
}
public static Object multiply(Object op1, Object op2) {
return wideningConversionBinaryOperation(op1, op2, Operation.MULTIPLICATION);
}
public static Object divide(Object op1, Object op2) {
return wideningConversionBinaryOperation(op1, op2, Operation.DIVISION);
}
public static Object mod(Object op1, Object op2) {
return wideningConversionBinaryOperation(op1, op2, Operation.MODULUS);
}
public static boolean equals(Object op1, Object op2) {
if (op1 != null && op1 instanceof Number && op2 != null && op2 instanceof Number) {
return wideningConversionBinaryComparison(op1, op2, Comparison.EQUALS);
} else if (op1 != null && op1 instanceof Enum> && op2 != null && op2 instanceof String) {
return compareEnum((Enum>) op1, (String) op2);
} else if (op2 != null && op2 instanceof Enum> && op1 != null && op1 instanceof String) {
return compareEnum((Enum>) op2, (String) op1);
} else {
return ((op1 == op2) || ((op1 != null) && op1.equals(op2)));
}
}
private static > boolean compareEnum(Enum enumVariable, String compareToString) {
return enumVariable.name().equals(compareToString);
}
public static boolean gt(Object op1, Object op2) {
return wideningConversionBinaryComparison(op1, op2, Comparison.GREATER_THAN);
}
public static boolean gte(Object op1, Object op2) {
return wideningConversionBinaryComparison(op1, op2, Comparison.GREATER_THAN_EQUALS);
}
public static boolean lt(Object op1, Object op2) {
return wideningConversionBinaryComparison(op1, op2, Comparison.LESS_THAN);
}
public static boolean lte(Object op1, Object op2) {
return wideningConversionBinaryComparison(op1, op2, Comparison.LESS_THAN_EQUALS);
}
public static Object unaryPlus(Object op1) {
return multiply(1, op1);
}
public static Object unaryMinus(Object op1) {
return multiply(-1, op1);
}
private static Object concatenateStrings(String op1, String op2) {
return op1 + op2;
}
/**
* This is not a documented feature but we are leaving this in for now. I'm
* unsure if there is demand for this feature.
*
* @param op1
* @param op2
* @return
*/
@Deprecated
@SuppressWarnings({ "unchecked", "rawtypes" })
private static Object addToList(List> op1, Object op2) {
if (op2 instanceof Collection) {
op1.addAll((Collection) op2);
} else {
((List