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.data.phenology;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.Date;
22  import java.util.List;
23  import java.util.stream.Collectors;
24  
25  import fr.inrae.agroclim.indicators.model.data.Resource;
26  import fr.inrae.agroclim.indicators.model.indicator.CompositeIndicator;
27  import fr.inrae.agroclim.indicators.model.indicator.Indicator;
28  import fr.inrae.agroclim.indicators.model.indicator.IndicatorCategory;
29  import fr.inrae.agroclim.indicators.util.DateUtils;
30  import lombok.extern.log4j.Log4j2;
31  
32  /**
33   * Storage of phenological daily data.
34   *
35   * Last change $Date$
36   *
37   * @author $Author$
38   * @version $Revision$
39   */
40  @Log4j2
41  public final class PhenologicalResource extends Resource<AnnualStageData> {
42      /**
43       * UUID for Serializable.
44       */
45      private static final long serialVersionUID = 4872847709393688048L;
46      /**
47       * Separator for tag of pheno phase.
48       */
49      private static final String PHENO_PHASE_SEPARATOR = "-";
50      /**
51       * Prefix for tag of pheno phase.
52       */
53      private static final String PHENO_PHASE_PREFIX = "pheno" + PHENO_PHASE_SEPARATOR;
54  
55      /**
56       * Phases.
57       */
58      private List<CompositeIndicator> phases;
59  
60      /**
61       * Phenological stages.
62       */
63      private List<String> stages;
64  
65      /**
66       * List all AnnualStageData as dates.
67       *
68       * @param datas list of stages data
69       * @return dates of phenological stages
70       */
71      public static List<Date> asDates(final List<AnnualStageData> datas) {
72          final List<Date> dates = new ArrayList<>();
73          datas.forEach(data -> {
74              int year = data.getYear();
75              for (final Stage stage : data.getStages()) {
76                  int doy = stage.getValue();
77                  Date date = DateUtils.getDate(year, doy);
78                  dates.add(date);
79              }
80          });
81          return dates;
82      }
83  
84      @Override
85      public PhenologicalResource clone() throws CloneNotSupportedException {
86          PhenologicalResource clone = (PhenologicalResource) super.clone();
87          if (getData() != null) {
88              List<AnnualStageData> dest = new ArrayList<>();
89              for (final AnnualStageData data : getData()) {
90                  dest.add(data.clone());
91              }
92              clone.setData(dest);
93          }
94          if (getMissingVariables() != null) {
95              List<String> dest = new ArrayList<>();
96              Collections.copy(dest, getMissingVariables());
97              clone.setMissingVariables(dest);
98          }
99          if (phases != null) {
100             clone.phases = new ArrayList<>(phases);
101         }
102         if (stages != null) {
103             clone.stages = new ArrayList<>(stages);
104         }
105         if (getYears() != null) {
106             getYears().forEach(clone::addYear);
107         }
108         return clone;
109     }
110 
111     /**
112      * List all AnnualStageData as dates.
113      *
114      * @return dates of phenological stages
115      */
116     public List<Date> getDates() {
117         return asDates(getData());
118     }
119 
120     /**
121      * @return available phases
122      */
123     public List<CompositeIndicator> getPhases() {
124         return phases;
125     }
126 
127     /**
128      * List all phases starting by the stage.
129      *
130      * @param stage start stage
131      * @return all stages with starting stage
132      */
133     public List<Indicator> getPhasesByStage(final String stage) {
134         return phases.stream()
135                 // RDM9713
136                 .filter(phase -> phase.getTag().startsWith(PHENO_PHASE_PREFIX + stage + PHENO_PHASE_SEPARATOR))
137                 .collect(Collectors.toList());
138     }
139 
140     /**
141      * @return Phenological stages for GUI
142      */
143     public List<String> getStages() {
144         return stages;
145     }
146 
147     /**
148      * @param list all data for the resource
149      */
150     public void setData(final List<AnnualStageData> list) {
151         getYears().clear();
152         for (final AnnualStageData data : list) {
153             getYears().add(data.getYear());
154         }
155         getData().clear();
156         getData().addAll(list);
157     }
158 
159     /**
160      * Initialize the stages and phases used by the GUI.
161      *
162      * @param userHeader
163      *            Headers of CSV file.
164      */
165     public void setUserHeader(final String[] userHeader) {
166         LOGGER.trace("start");
167         if (userHeader == null) {
168             throw new IllegalArgumentException("userHeader must not be null!");
169         }
170         List<Indicator> stageIndicators = new ArrayList<>();
171         phases = new ArrayList<>();
172         stages = new ArrayList<>();
173 
174         for (String column : userHeader) {
175             if (column.equalsIgnoreCase(PhenologyFileLoader.YEAR_COLUMN)) {
176                 continue;
177             }
178             stages.add(column);
179             CompositeIndicator stageIndicator = new CompositeIndicator();
180             stageIndicator.setName("en", column);
181             stageIndicator.setId("pheno_" + column);
182             stageIndicator.setCategory(IndicatorCategory.PHENO_PHASES.getTag());
183             stageIndicators.add(stageIndicator);
184         }
185 
186         /*
187          * Création d'un composite phase phéno à partir de 2 stades phéno
188          * Création de toutes les combinaisons possibles
189          */
190         stageIndicators.forEach(stage -> {
191             List<Indicator> nextStages = stageIndicators.subList(
192                     stageIndicators.indexOf(stage) + 1, stages.size());
193             for (Indicator nextStage : nextStages) {
194                 CompositeIndicator phenoIndicator = new CompositeIndicator();
195                 phenoIndicator.setName("en", nextStage.getName());
196                 phenoIndicator.setId(stage.getName() + nextStage.getName());
197                 phenoIndicator.setTag(PHENO_PHASE_PREFIX + stage.getName() + PHENO_PHASE_SEPARATOR
198                         + nextStage.getName());
199                 phenoIndicator.setCategory(IndicatorCategory.PHENO_PHASES
200                         .getTag());
201                 phenoIndicator.setNormalizationFunction(null);
202                 phenoIndicator.add(stage);
203                 phases.add(phenoIndicator);
204             }
205         });
206     }
207 }