View Javadoc
1   /**
2    * This file is part of Indicators.
3    *
4    * Indicators is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * Indicators is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with Indicators. If not, see <https://www.gnu.org/licenses/>.
16   */
17  package fr.inrae.agroclim.indicators.model.indicator;
18  
19  import java.beans.PropertyChangeEvent;
20  import java.beans.PropertyChangeListener;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Objects;
25  import java.util.Set;
26  
27  import fr.inrae.agroclim.indicators.model.Knowledge;
28  import fr.inrae.agroclim.indicators.model.Parameter;
29  import fr.inrae.agroclim.indicators.model.criteria.Criteria;
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.function.normalization.NormalizationFunction;
34  import fr.inrae.agroclim.indicators.model.indicator.listener.IndicatorEvent;
35  import fr.inrae.agroclim.indicators.util.Doublet;
36  import jakarta.xml.bind.Unmarshaller;
37  import lombok.EqualsAndHashCode;
38  import lombok.Getter;
39  import lombok.extern.log4j.Log4j2;
40  
41  /**
42   * A simple indicator with a criteria.
43   *
44   * Last change $Date$
45   *
46   * @author $Author$
47   * @version $Revision$
48   */
49  @EqualsAndHashCode(
50          callSuper = true,
51          of = {"criteria"}
52          )
53  @Log4j2
54  public abstract class SimpleIndicatorWithCriteria extends SimpleIndicator implements PropertyChangeListener {
55      /**
56       * UUID for Serializable.
57       */
58      private static final long serialVersionUID = 6030595237342422016L;
59  
60      /**
61       * Criteria.
62       */
63      @Getter
64      private Criteria criteria;
65  
66      /**
67       * Constructor.
68       */
69      protected SimpleIndicatorWithCriteria() {
70          super();
71      }
72  
73      /**
74       * Constructor with function.
75       *
76       * @param n function to normalize value
77       */
78      protected SimpleIndicatorWithCriteria(final NormalizationFunction n) {
79          super(n);
80      }
81  
82      /**
83       * Called after all the properties (except IDREF) are unmarshalled for this
84       * object, but before this object is set to the parent object.
85       *
86       * @param u JAXB unmarshaller
87       * @param parent instance of JAXB mapped class that will reference target.
88       * null when target is root element.
89       */
90      final void afterUnmarshal(final Unmarshaller u, final Object parent) {
91          if (this.getCriteria() != null) {
92              this.getCriteria().addPropertyChangeListener(this);
93          }
94      }
95  
96      @Override
97      @SuppressWarnings("checkstyle:DesignForExtension")
98      public SimpleIndicatorWithCriteria clone()
99              throws CloneNotSupportedException {
100         SimpleIndicatorWithCriteria clone;
101         clone = (SimpleIndicatorWithCriteria) super.clone();
102         if (criteria != null) {
103             clone.criteria = getCriteria().clone();
104             clone.criteria.addPropertyChangeListener(clone);
105         }
106         return clone;
107     }
108 
109     /**
110      * Get the defaults from the criteria.
111      *
112      * @return parameter for substituted attribute ⮕ value of attribute from the evaluation. Must not be null.
113      */
114     @Override
115     public List<Doublet<Parameter, Number>> getParameterDefaults() {
116         return getCriteria().getParameterDefaults();
117     }
118 
119     @Override
120     public final List<Parameter> getParameters() {
121         final List<Parameter> params = new ArrayList<>();
122         if (super.getParameters() != null) {
123             params.addAll(super.getParameters());
124         }
125         Objects.requireNonNull(getCriteria(), "Criteria must not be null in " + getId());
126         if (getCriteria().getParameters() != null) {
127             getCriteria().getParameters().forEach(param -> {
128                 if (!params.contains(param)) {
129                     params.add(param);
130                 }
131             });
132         }
133         return params;
134     }
135 
136     @Override
137     public final Map<String, Double> getParametersValues() {
138         return getCriteria().getParametersValues();
139     }
140 
141     @Override
142     public final Set<Variable> getVariables() {
143         Objects.requireNonNull(getCriteria(), "Criteria should not be null for " + getName());
144         return getCriteria().getVariables();
145     }
146 
147     @Override
148     public final boolean isComputable(final Resource<? extends DailyData> res) {
149         return getCriteria().isComputable(res);
150     }
151 
152     @Override
153     public final void propertyChange(final PropertyChangeEvent pce) {
154         LOGGER.traceEntry();
155         fireIndicatorEvent(IndicatorEvent.Type.CHANGE.event(this));
156     }
157 
158     /**
159      * @param c criteria
160      */
161     public final void setCriteria(final Criteria c) {
162         this.criteria = c;
163         if (this.getCriteria() != null) {
164             this.getCriteria().addPropertyChangeListener(this);
165         }
166     }
167 
168     @Override
169     public final void setParametersFromKnowledge(final Knowledge knowledge) {
170         LOGGER.traceEntry();
171         if (getCriteria() == null) {
172             return;
173         }
174         SimpleIndicatorWithCriteria indicator = (SimpleIndicatorWithCriteria) knowledge.getIndicator(getId());
175         if (indicator == null) {
176             return;
177         }
178         final List<Parameter> values = indicator.getCriteria().getParameters();
179         if (values != null && !values.isEmpty()) {
180             getCriteria().setParameters(values);
181         }
182         LOGGER.traceExit();
183     }
184 
185     @Override
186     public final void setParametersValues(final Map<String, Double> values) {
187         getCriteria().setParametersValues(values);
188     }
189 
190     /**
191      * To override, use super or use toStringTreeBase() and also getCriteria().toStringTree(indent + " ").
192      *
193      * @param indent intent of tree representation
194      * @return tree representation
195      */
196     @Override
197     public String toStringTree(final String indent) {
198         final StringBuilder sb = new StringBuilder();
199         sb.append(toStringTreeBase(indent));
200 
201         if (getCriteria() != null) {
202             sb.append(indent).append("  criteria:\n")
203             .append(getCriteria().toStringTree(indent + "  "))
204             .append("\n");
205         }
206         return sb.toString();
207     }
208 
209     @Override
210     public final void removeParameter(final Parameter param) {
211         if (getCriteria() != null) {
212             this.getCriteria().removeParameter(param);
213         }
214         if (super.getParameters() != null) {
215             super.getParameters().remove(param);
216         }
217     }
218 }