1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package fr.inrae.agroclim.indicators.model.indicator;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import fr.inrae.agroclim.indicators.exception.IndicatorsException;
27 import fr.inrae.agroclim.indicators.exception.type.ComputationErrorType;
28 import fr.inrae.agroclim.indicators.model.Knowledge;
29 import fr.inrae.agroclim.indicators.model.Parameter;
30 import fr.inrae.agroclim.indicators.model.data.DailyData;
31 import fr.inrae.agroclim.indicators.model.data.Resource;
32 import fr.inrae.agroclim.indicators.model.data.Variable;
33 import fr.inrae.agroclim.indicators.model.indicator.listener.IndicatorEvent;
34 import fr.inrae.agroclim.indicators.model.indicator.listener.IndicatorListener;
35 import fr.inrae.agroclim.indicators.util.Doublet;
36 import jakarta.xml.bind.annotation.XmlAccessType;
37 import jakarta.xml.bind.annotation.XmlAccessorType;
38 import jakarta.xml.bind.annotation.XmlRootElement;
39 import jakarta.xml.bind.annotation.XmlType;
40 import lombok.Getter;
41 import lombok.Setter;
42
43
44
45
46
47
48
49
50
51 @XmlRootElement
52 @XmlAccessorType(XmlAccessType.FIELD)
53 @XmlType(propOrder = {"dividend", "divisor"})
54 public final class Quotient extends SimpleIndicator implements Detailable, IndicatorListener {
55
56
57
58
59 private static final long serialVersionUID = 6030595237342422014L;
60
61
62
63
64 @Getter
65 @Setter
66 private SimpleIndicator dividend;
67
68
69
70
71 @Getter
72 @Setter
73 private SimpleIndicator divisor;
74
75
76
77
78 public Quotient() {
79 super();
80 }
81
82 @Override
83 public Quotient clone() throws CloneNotSupportedException {
84 final Quotient clone = (Quotient) super.clone();
85 if (dividend != null) {
86 clone.dividend = (SimpleIndicator) dividend.clone();
87 }
88 if (divisor != null) {
89 clone.divisor = (SimpleIndicator) divisor.clone();
90 }
91 return clone;
92 }
93
94 @Override
95 public double computeSingleValue(final Resource<? extends DailyData> data) throws IndicatorsException {
96 if (dividend == null) {
97 throw new IndicatorsException(ComputationErrorType.QUOTIENT_DIVIDEND_NULL);
98 }
99 if (divisor == null) {
100 throw new IndicatorsException(ComputationErrorType.QUOTIENT_DIVISOR_NULL);
101 }
102 final double dividendValue;
103 try {
104 dividendValue = dividend.compute(data);
105 } catch (final IndicatorsException e) {
106 throw new IndicatorsException(ComputationErrorType.QUOTIENT_DIVIDEND_EXCEPTION, e, dividend.getId());
107 }
108 final double divisorValue;
109 try {
110 divisorValue = divisor.compute(data);
111 } catch (final IndicatorsException e) {
112 throw new IndicatorsException(ComputationErrorType.QUOTIENT_DIVISOR_EXCEPTION, e, divisor.getId());
113 }
114 if (divisorValue == 0.0) {
115 throw new IndicatorsException(ComputationErrorType.QUOTIENT_DIVISOR_ZERO, divisor.getId());
116 }
117 return dividendValue / divisorValue;
118 }
119
120 @Override
121 public List<Doublet<Parameter, Number>> getParameterDefaults() {
122 final List<Doublet<Parameter, Number>> val = new ArrayList<>();
123 if (dividend != null && dividend.getParameterDefaults() != null) {
124 val.addAll(dividend.getParameterDefaults());
125 }
126 if (divisor != null && divisor.getParameterDefaults() != null) {
127 val.addAll(divisor.getParameterDefaults());
128 }
129 return val;
130 }
131
132 @Override
133 public List<Parameter> getParameters() {
134 final List<Parameter> params = new ArrayList<>();
135 if (dividend != null && dividend.getParameters() != null) {
136 params.addAll(dividend.getParameters());
137 }
138 if (divisor != null && divisor.getParameters() != null) {
139 params.addAll(divisor.getParameters());
140 }
141 return params;
142 }
143
144 @Override
145 public Map<String, Double> getParametersValues() {
146 final Map<String, Double> val = new HashMap<>();
147 if (dividend != null && dividend.getParametersValues() != null) {
148 val.putAll(dividend.getParametersValues());
149 }
150 if (divisor != null && divisor.getParametersValues() != null) {
151 val.putAll(divisor.getParametersValues());
152 }
153 return val;
154 }
155
156 @Override
157 public Set<Variable> getVariables() {
158 final Set<Variable> variables = new HashSet<>();
159 if (dividend != null) {
160 variables.addAll(dividend.getVariables());
161 }
162 if (divisor != null) {
163 variables.addAll(divisor.getVariables());
164 }
165 return variables;
166 }
167
168 @Override
169 public boolean isComputable(final Resource<? extends DailyData> data) {
170 if (dividend == null || divisor == null) {
171 return false;
172 }
173 return dividend.isComputable(data) && divisor.isComputable(data);
174 }
175
176 @Override
177 public void onIndicatorEvent(final IndicatorEvent event) {
178 if (event.getAssociatedType() != IndicatorEvent.Type.CHANGE) {
179 return;
180 }
181 final IndicatorEvent e = IndicatorEvent.Type.CHANGE.event(this);
182 fireIndicatorEvent(e);
183 }
184
185 @Override
186 public void setParametersFromKnowledge(final Knowledge knowledge) {
187 if (dividend != null) {
188 dividend.setParametersFromKnowledge(knowledge);
189 }
190 if (divisor != null) {
191 divisor.setParametersFromKnowledge(knowledge);
192 }
193 }
194
195 @Override
196 public void setParametersValues(final Map<String, Double> values) {
197 if (dividend != null) {
198 dividend.setParametersValues(values);
199 }
200 if (divisor != null) {
201 divisor.setParametersValues(values);
202 }
203 }
204
205 @Override
206 public String toStringTree(final String indent) {
207 final StringBuilder sb = new StringBuilder();
208 sb.append(toStringTreeBase(indent));
209
210 if (dividend != null) {
211 sb.append(indent).append(" dividend:\n");
212 sb.append(dividend.toStringTree(indent + " "))
213 .append("\n");
214 }
215 if (divisor != null) {
216 sb.append(indent).append(" divisor:\n");
217 sb.append(divisor.toStringTree(indent + " "))
218 .append("\n");
219 }
220
221 return sb.toString();
222 }
223
224 @Override
225 public void removeParameter(final Parameter param) {
226 if (dividend != null) {
227 this.dividend.removeParameter(param);
228 }
229 if (divisor != null) {
230 this.divisor.removeParameter(param);
231 }
232 }
233 }