SoilLoaderProxy.java
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package fr.inrae.agroclim.indicators.model.data.soil;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import fr.inrae.agroclim.indicators.model.TimeScale;
import fr.inrae.agroclim.indicators.model.data.DataLoadingListenerHandler;
import fr.inrae.agroclim.indicators.model.data.Resource;
import fr.inrae.agroclim.indicators.model.data.Variable;
import fr.inrae.agroclim.indicators.model.data.climate.ClimaticDailyData;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
/**
* Proxy to load soil data.
*
* Loader is chosen according to properties (XML tag).
*
* The proxy is initialized from evaluation XML file.
*
* Last changed : $Date$
*
* @author $Author$
* @version $Revision$
*/
@Log4j2
@XmlAccessorType(XmlAccessType.FIELD)
public final class SoilLoaderProxy extends DataLoadingListenerHandler implements HasSoilCalculatorParams, SoilLoader {
/**
* UID for serialization.
*/
private static final long serialVersionUID = 4796900688021151186L;
/**
* Climatic daily data used to compute soil water balance.
*/
@XmlTransient
private List<ClimaticDailyData> climaticDailyData;
/**
* CSV file.
*/
@XmlElement(name = "file")
@Getter
@Setter
private File file;
/**
* Headers of CSV file.
*/
@XmlElement(name = "header")
@Getter
@Setter
private String[] headers;
/**
* Coefficient cultural en situation non stressée durant la période initiale
* de la saison [0-1] (semis-levee selon notre hypothèse).
*/
private Double kcIni;
/**
* Coefficient cultural en situation non stressée durant la late season
* [0-1] (à partir de floraison selon nous).
*/
private Double kcLate;
/**
* Coefficient cultural en situation non stressée durant la middle season
* [0-1] (epi 1 cm - floraison selon notre hypothèse).
*/
private Double kcMid;
/**
* Loader/Calculator for soil data.
*/
@XmlTransient
private SoilLoader loader;
/**
* Proportion of easily available water in the soil.
*
* Average fraction of TAW(pour obtenir RAW).
*/
private Double p;
/**
* Réserve utile du sol (mm).
*
* Ou utilisation de swcFc, swcWp, soilDepth.
*/
private Double ru;
/**
* CSV separator.
*/
@XmlElement(name = "separator")
@Getter
@Setter
private String separator = Resource.DEFAULT_SEP;
/**
* Soil depth (cm).
*/
private Double soilDepth;
/**
* 4 stages per year to compute soil water balance (SWC and R).
*/
@XmlTransient
@Getter
private List<Date> stages;
/**
* Teneur en eau du sol à la capacité au champ (% volumique).
*/
private Double swcFc;
/**
* Teneur en eau du sol ... (% volumique).
*/
private double swcMax;
/**
* Teneur en eau du sol au point de flétrissement permanent (% volumique).
*/
private Double swcWp;
/**
* Constructor.
*/
public SoilLoaderProxy() {
super();
}
@Override
public SoilLoaderProxy clone() throws CloneNotSupportedException {
final SoilLoaderProxy clone = (SoilLoaderProxy) super.clone();
if (climaticDailyData != null) {
clone.climaticDailyData = new ArrayList<>();
Collections.copy(clone.climaticDailyData, climaticDailyData);
}
clone.file = file;
clone.headers = headers;
clone.kcIni = kcIni;
clone.kcLate = kcLate;
clone.kcMid = kcMid;
clone.loader = loader.clone();
clone.p = p;
clone.ru = ru;
clone.separator = separator;
clone.soilDepth = soilDepth;
if (stages != null) {
clone.stages = new ArrayList<>();
Collections.copy(clone.stages, stages);
}
clone.swcFc = swcFc;
clone.swcMax = swcMax;
clone.swcWp = swcWp;
return clone;
}
@Override
public Map<String, String> getConfigurationErrors() {
return getLoader().getConfigurationErrors();
}
/**
* @return loader/calculator for soil data according to configuration.
*/
public SoilLoader getLoader() {
if (loader == null) {
if (file != null) {
final SoilFileLoader soilFileLoader = new SoilFileLoader(getFile(),
getHeaders(), getSeparator());
soilFileLoader
.addDataLoadingListeners(getDataLoadingListeners());
loader = soilFileLoader;
} else {
final SoilCalculator calc = new SoilCalculator();
calc.setClimaticDailyData(climaticDailyData);
calc.setStages(stages);
calc.setKcIni(kcIni);
calc.setKcLate(kcLate);
calc.setKcMid(kcMid);
calc.setP(p);
calc.setRu(ru);
calc.setSoilDepth(soilDepth);
calc.setSwcFc(swcFc);
calc.setSwcMax(swcMax);
calc.setSwcWp(swcWp);
calc.addDataLoadingListeners(getDataLoadingListeners());
loader = calc;
}
}
return loader;
}
@Override
public Collection<String> getMissingVariables() {
throw new RuntimeException("Not implemented for soil!");
}
@Override
public Set<Variable> getProvidedVariables() {
return getLoader().getProvidedVariables();
}
@Override
public Set<Variable> getVariables() {
return getLoader().getVariables();
}
@Override
public List<SoilDailyData> load() {
return getLoader().load();
}
/**
* @param calc model for soil water balance
*/
public void setCalculator(final SoilCalculator calc) {
loader = calc;
}
/**
* @param values Climatic daily data used to compute soil water balance.
*/
public void setClimaticDailyData(final List<ClimaticDailyData> values) {
this.climaticDailyData = values;
if (loader instanceof final SoilCalculator calc) {
calc.setClimaticDailyData(values);
} else {
LOGGER.warn("No soil loader!");
}
}
@Override
public void setKcIni(final Double value) {
this.kcIni = value;
}
@Override
public void setKcLate(final Double value) {
this.kcLate = value;
}
@Override
public void setKcMid(final Double value) {
this.kcMid = value;
}
@Override
public void setP(final Double value) {
p = value;
}
@Override
public void setSoilDepth(final Double value) {
this.soilDepth = value;
}
/**
* @param values 4 stages per year to compute soil water balance (SWC and
* R).
*/
public void setStages(final List<Date> values) {
this.stages = values;
if (loader instanceof final SoilCalculator calc) {
calc.setStages(stages);
}
}
@Override
public void setSwcFc(final Double value) {
this.swcFc = value;
}
@Override
public void setSwcMax(final Double value) {
this.swcMax = value;
}
@Override
public void setSwcWp(final Double value) {
this.swcWp = value;
}
@Override
public void setTimeScale(final TimeScale timeScale) {
// do nothing
}
}