1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package fr.inrae.agroclim.indicators.model;
18
19 import java.io.Serializable;
20 import java.nio.file.Path;
21 import java.nio.file.Paths;
22 import java.time.LocalDateTime;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import fr.inrae.agroclim.indicators.exception.IndicatorsException;
29 import fr.inrae.agroclim.indicators.model.criteria.ComparisonCriteria;
30 import fr.inrae.agroclim.indicators.model.criteria.CompositeCriteria;
31 import fr.inrae.agroclim.indicators.model.criteria.FormulaCriteria;
32 import fr.inrae.agroclim.indicators.model.criteria.LogicalOperator;
33 import fr.inrae.agroclim.indicators.model.criteria.NoCriteria;
34 import fr.inrae.agroclim.indicators.model.criteria.RelationalOperator;
35 import fr.inrae.agroclim.indicators.model.criteria.SimpleCriteria;
36 import fr.inrae.agroclim.indicators.model.data.Variable;
37 import fr.inrae.agroclim.indicators.model.data.climate.ClimateFileLoader;
38 import fr.inrae.agroclim.indicators.model.data.climate.ClimateLoaderProxy;
39 import fr.inrae.agroclim.indicators.model.data.phenology.PhenologyCalculator;
40 import fr.inrae.agroclim.indicators.model.data.phenology.PhenologyFileLoader;
41 import fr.inrae.agroclim.indicators.model.data.phenology.PhenologyLoaderProxy;
42 import fr.inrae.agroclim.indicators.model.data.soil.SoilLoaderProxy;
43 import fr.inrae.agroclim.indicators.model.function.aggregation.AggregationFunction;
44 import fr.inrae.agroclim.indicators.model.function.aggregation.JEXLFunction;
45 import fr.inrae.agroclim.indicators.model.function.normalization.Exponential;
46 import fr.inrae.agroclim.indicators.model.function.normalization.Linear;
47 import fr.inrae.agroclim.indicators.model.function.normalization.MultiLinear;
48 import fr.inrae.agroclim.indicators.model.function.normalization.Normal;
49 import fr.inrae.agroclim.indicators.model.function.normalization.NormalizationFunction;
50 import fr.inrae.agroclim.indicators.model.function.normalization.Sigmoid;
51 import fr.inrae.agroclim.indicators.model.indicator.Average;
52 import fr.inrae.agroclim.indicators.model.indicator.AverageOfDiff;
53 import fr.inrae.agroclim.indicators.model.indicator.CompositeIndicator;
54 import fr.inrae.agroclim.indicators.model.indicator.DayOfYear;
55 import fr.inrae.agroclim.indicators.model.indicator.DiffOfSum;
56 import fr.inrae.agroclim.indicators.model.indicator.Formula;
57 import fr.inrae.agroclim.indicators.model.indicator.Indicator;
58 import fr.inrae.agroclim.indicators.model.indicator.Max;
59 import fr.inrae.agroclim.indicators.model.indicator.MaxWaveLength;
60 import fr.inrae.agroclim.indicators.model.indicator.Min;
61 import fr.inrae.agroclim.indicators.model.indicator.NumberOfDays;
62 import fr.inrae.agroclim.indicators.model.indicator.NumberOfWaves;
63 import fr.inrae.agroclim.indicators.model.indicator.PhaseLength;
64 import fr.inrae.agroclim.indicators.model.indicator.PotentialSowingDaysFrequency;
65 import fr.inrae.agroclim.indicators.model.indicator.Quotient;
66 import fr.inrae.agroclim.indicators.model.indicator.SimpleIndicator;
67 import fr.inrae.agroclim.indicators.model.indicator.Sum;
68 import fr.inrae.agroclim.indicators.model.indicator.Tamm;
69 import jakarta.xml.bind.annotation.XmlAccessType;
70 import jakarta.xml.bind.annotation.XmlAccessorType;
71 import jakarta.xml.bind.annotation.XmlAttribute;
72 import jakarta.xml.bind.annotation.XmlElement;
73 import jakarta.xml.bind.annotation.XmlElementWrapper;
74 import jakarta.xml.bind.annotation.XmlRootElement;
75 import jakarta.xml.bind.annotation.XmlTransient;
76 import jakarta.xml.bind.annotation.XmlType;
77 import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
78 import lombok.EqualsAndHashCode;
79 import lombok.Getter;
80 import lombok.Setter;
81 import lombok.ToString;
82 import lombok.extern.log4j.Log4j2;
83
84
85
86
87
88
89
90
91
92 @XmlRootElement
93 @XmlAccessorType(XmlAccessType.FIELD)
94 @XmlType(propOrder = {"climateLoader", "notes", "phenologyLoader", "soilLoader",
95 "soilPhenologyCalculator", "name", "type", "timescale", "evaluation"})
96 @EqualsAndHashCode(
97 callSuper = false,
98 of = {"climateLoader", "evaluation", "filePath", "knowledge", "name",
99 "phenologyLoader", "soilLoader", "soilPhenologyCalculator"})
100 @Log4j2
101 @ToString
102 public final class EvaluationSettings implements Cloneable, Serializable {
103
104
105
106
107 public static final Class<?>[] CLASSES_FOR_JAXB = new Class<?>[] {
108 EvaluationSettings.class, EvaluationType.class, Knowledge.class, Note.class,
109 PhaseLength.class, Variable.class, TimeScale.class,
110
111 ClimateLoaderProxy.class, ClimateFileLoader.class,
112
113 PhenologyLoaderProxy.class, PhenologyFileLoader.class,
114
115
116 Average.class, AverageOfDiff.class, CompositeIndicator.class,
117 DayOfYear.class, DiffOfSum.class, Formula.class, Indicator.class, Max.class, MaxWaveLength.class, Min.class,
118 Normal.class, NumberOfDays.class, NumberOfWaves.class,
119 PotentialSowingDaysFrequency.class, Quotient.class,
120 SimpleIndicator.class, Sum.class, Tamm.class,
121
122 ComparisonCriteria.class, CompositeCriteria.class, ExpressionParameter.class, FormulaCriteria.class,
123 LogicalOperator.class, NoCriteria.class, Parameter.class, RelationalOperator.class, SimpleCriteria.class,
124
125 AggregationFunction.class, Exponential.class, JEXLFunction.class,
126 Linear.class, MultiLinear.class, NormalizationFunction.class, Sigmoid.class
127 };
128
129
130
131
132 private static final long serialVersionUID = 3308126437081517192L;
133
134
135
136
137 @XmlElement(name = "climate")
138 @Getter
139 private ClimateLoaderProxy climateLoader;
140
141
142
143
144 @XmlElement(name = "compositeIndicator")
145 @Getter
146 @Setter
147 private CompositeIndicator evaluation;
148
149
150
151
152 @XmlTransient
153 @Getter
154 private String filePath;
155
156
157
158
159 @Getter
160 private transient Knowledge knowledge;
161
162
163
164
165 @XmlElement
166 @Getter
167 @Setter
168 private String name;
169
170
171
172
173 @XmlElement(name = "phenology")
174 @Getter
175 @Setter
176 private PhenologyLoaderProxy phenologyLoader;
177
178
179
180
181 @XmlElement(name = "soil")
182 @Getter
183 @Setter
184 private SoilLoaderProxy soilLoader;
185
186
187
188
189
190 @XmlElement(name = "soilPhenologyCalculator")
191 @Getter
192 @Setter
193 private PhenologyCalculator soilPhenologyCalculator;
194
195
196
197
198 @Getter
199 @Setter
200 @XmlAttribute
201 private TimeScale timescale = TimeScale.DAILY;
202
203
204
205
206 @Getter
207 @Setter
208 @XmlAttribute(name = "timestamp", required = false)
209 @XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
210 private LocalDateTime timestamp;
211
212
213
214
215 @Getter
216 @Setter
217 @XmlElement(name = "type")
218 private EvaluationType type = EvaluationType.WITH_AGGREGATION;
219
220
221
222
223 @Getter
224 @Setter
225 @XmlAttribute(required = false)
226 private String version = "";
227
228
229
230 @XmlElementWrapper(name = "notes")
231 @XmlElement(name = "note")
232 @Getter
233 @Setter
234 private List<Note> notes;
235
236
237
238
239 public EvaluationSettings() {
240 evaluation = new Evaluation();
241 }
242
243 @Override
244 public EvaluationSettings clone() throws CloneNotSupportedException {
245 final EvaluationSettings clone = new EvaluationSettings();
246 if (climateLoader != null) {
247 clone.climateLoader = climateLoader.clone();
248 }
249 if (evaluation != null) {
250 clone.evaluation = evaluation.clone();
251 }
252 clone.filePath = filePath;
253 if (knowledge != null) {
254 clone.knowledge = knowledge.clone();
255 }
256 clone.name = name;
257 if (phenologyLoader != null) {
258 clone.phenologyLoader = phenologyLoader.clone();
259 }
260 if (soilLoader != null) {
261 clone.soilLoader = soilLoader.clone();
262 }
263 return clone;
264 }
265
266
267
268
269 public Map<String, String> getConfigurationErrors() {
270 final Map<String, String> errors = new HashMap<>();
271 if (getClimateLoader() == null) {
272 errors.put("evaluationSettings.climate",
273 "error.evaluation.climate.null");
274 } else if (getClimateLoader().getConfigurationErrors() != null) {
275 errors.putAll(getClimateLoader().getConfigurationErrors());
276 }
277 if (getSoilLoader() != null
278 && getSoilLoader().getConfigurationErrors() != null) {
279 errors.putAll(getSoilLoader().getConfigurationErrors());
280 }
281 if (getPhenologyLoader() == null) {
282 errors.put("evaluationSettings.phenology", "error.evaluation.phenology.null");
283 } else if (getPhenologyLoader().getConfigurationErrors() != null) {
284 errors.putAll(getPhenologyLoader().getConfigurationErrors());
285 }
286 return errors;
287 }
288
289
290
291
292
293 public void initializeKnowledge() throws IndicatorsException {
294 knowledge = Knowledge.load(timescale);
295 }
296
297
298
299
300 public void setClimate(final ClimateLoaderProxy value) {
301 this.climateLoader = value;
302 }
303
304
305
306
307
308
309 public void setFilePath(final String path) {
310 if (!Objects.equals(filePath, path)) {
311 this.filePath = path;
312 final Path baseDir = Paths.get(path).getParent();
313 if (climateLoader != null && climateLoader.getFile() != null) {
314 climateLoader.getFile().setBaseDirectory(baseDir);
315 }
316 if (phenologyLoader != null && phenologyLoader.getFile() != null) {
317 phenologyLoader.getFile().setBaseDirectory(baseDir);
318 }
319 }
320 }
321 }