JEXLFunction.java
package fr.inrae.agroclim.indicators.model.function.aggregation;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Map;
import fr.inrae.agroclim.indicators.exception.IndicatorsException;
import fr.inrae.agroclim.indicators.model.JEXLFormula;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.EqualsAndHashCode;
/**
* JEXL implementation of the aggregation function.
*
* For the syntax allowed check
* http://commons.apache.org/proper/commons-jexl/reference/syntax.html
*
* @author jcufi
*/
@XmlRootElement
@EqualsAndHashCode(
callSuper = true
)
public final class JEXLFunction extends AggregationFunction {
/**
* UUID for Serializable.
*/
private static final long serialVersionUID = 3308126437081517191L;
/**
* org.apache.commons.jexl2.JexlEngine handler.
*/
private transient JEXLFormula formula = new JEXLFormula();
/**
* Constructor.
*/
public JEXLFunction() {
super();
}
@Override
public double aggregate(final Map<String, Double> values) throws IndicatorsException {
formula.setExpression(getExpression());
return formula.evaluate(values, Double.class);
}
@Override
public boolean isValid() {
formula.setExpression(getExpression());
return formula.isValid();
}
/**
* Context: Deserialization does not initialize formula.
*
* A final field must be initialized either by direct assignment of an initial value or in the constructor. During
* deserialization, neither of these are invoked, so initial values for transients must be set in the
* 'readObject()' private method that's invoked during deserialization. And for that to work, the transients must
* be non-final.
*
* @param ois input stream from deserialization
*/
private void readObject(final ObjectInputStream ois) throws ClassNotFoundException, IOException {
// perform the default de-serialization first
ois.defaultReadObject();
formula = new JEXLFormula();
}
@Override
public String toString() {
return "JEXLFunction [getExpression()=" + formula.getExpression() + "]";
}
}