ComparisonCriteria.java
/*
* Copyright (C) 2020 INRAE AgroClim
*
* This file is part of Indicators.
*
* Indicators is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Indicators is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Indicators. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.inrae.agroclim.indicators.model.criteria;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import fr.inrae.agroclim.indicators.exception.IndicatorsException;
import fr.inrae.agroclim.indicators.exception.type.ComputationErrorType;
import fr.inrae.agroclim.indicators.model.Parameter;
import fr.inrae.agroclim.indicators.model.data.DailyData;
import fr.inrae.agroclim.indicators.model.data.Resource;
import fr.inrae.agroclim.indicators.model.data.Variable;
import fr.inrae.agroclim.indicators.util.Doublet;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;
/**
* Criteria to compare two variables.
*
* Last changed : $Date$
*
* @author omaury
* @author $Author$
* @version $Revision$
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"leftVariable", "relationalOperator", "rightVariable"})
@EqualsAndHashCode(
callSuper = true,
of = {"leftVariable", "relationalOperator", "rightVariable"}
)
@ToString
public final class ComparisonCriteria extends Criteria {
/**
* UID for Serializable.
*/
private static final long serialVersionUID = 874604079323338994L;
/**
* Variable name (property of ClimaticDailyData) for left operand.
*/
@XmlElement(name = "leftVariable", required = true)
@Getter
@Setter
private Variable leftVariable;
/**
* The relational operator to compare leftVariable and rightVariable.
*/
@XmlElement(name = "relationalOperator", required = true)
@Setter
@NonNull
private RelationalOperator relationalOperator;
/**
* Variable name (property of ClimaticDailyData) for right operand.
*/
@XmlElement(name = "rightVariable", required = true)
@Getter
@Setter
private Variable rightVariable;
@Override
public ComparisonCriteria clone() {
final ComparisonCriteria clone = new ComparisonCriteria();
clone.leftVariable = leftVariable;
clone.relationalOperator = relationalOperator;
clone.rightVariable = rightVariable;
if (getParameters() != null) {
clone.setParameters(getParameters());
}
return clone;
}
@Override
public boolean eval(final DailyData dailydata) throws IndicatorsException {
if (relationalOperator == null) {
throw new IndicatorsException(ComputationErrorType.WRONG_DEFINITION,
"The relational operator must be set!");
}
if (dailydata == null) {
return false;
}
final Double left = dailydata.getValue(leftVariable);
final Double right = dailydata.getValue(rightVariable);
return relationalOperator.eval(left, right);
}
@Override
public List<Doublet<Parameter, Number>> getParameterDefaults() {
// no substitution
return List.of();
}
@Override
public List<Parameter> getParameters() {
// no substitution
return List.of();
}
@Override
public Map<String, Double> getParametersValues() {
// no substitution
return Map.of();
}
@Override
public Set<Variable> getVariables() {
final Set<Variable> variables = new HashSet<>();
variables.add(leftVariable);
variables.add(rightVariable);
return variables;
}
/**
* @param res ClimaticResource
* @return climaticResource contains "variable"
*/
@Override
public boolean isComputable(final Resource<? extends DailyData> res) {
Objects.requireNonNull(leftVariable,
"Left variable must be set for "
+ getClass().getCanonicalName());
Objects.requireNonNull(leftVariable,
"Right variable must be set for "
+ getClass().getCanonicalName());
return !res.getMissingVariables().contains(leftVariable.name())
&& !res.getMissingVariables().contains(rightVariable.name());
}
@Override
public void removeParameter(final Parameter param) {
// Do nothing for this type of criteria
}
@Override
public void setParametersValues(final Map<String, Double> values) {
// No parameters for the comparison of variables
}
@Override
public String toStringTree(final String indent) {
final StringBuilder sb = new StringBuilder();
sb.append(indent).append(" class: ")
.append(getClass().getName()).append("\n");
sb.append(indent).append(" leftVariable: ")
.append(leftVariable).append("\n");
sb.append(indent).append(" relationalOperator: ")
.append(relationalOperator).append("\n");
sb.append(indent).append(" rightVariable: ")
.append(rightVariable).append("\n");
return sb.toString();
}
}