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;
18  
19  import java.io.Serializable;
20  import java.util.Calendar;
21  import java.util.Date;
22  
23  import fr.inrae.agroclim.indicators.util.DateUtils;
24  import java.time.LocalDate;
25  import lombok.Getter;
26  
27  /**
28   * Class with date methods.
29   *
30   * Last changed : $Date$
31   *
32   * @author $Author$
33   * @version $Revision$
34   */
35  public abstract class HourlyData implements Cloneable, Data, Serializable {
36  
37      /**
38       * Max allowed value for day of month.
39       */
40      private static final int MAX_DAY = 31;
41  
42      /**
43       * Max allowed value for hour.
44       */
45      private static final int MAX_HOUR = 23;
46  
47      /**
48       * Max allowed value for month.
49       */
50      private static final int MAX_MONTH = 12;
51  
52      /**
53       * Max allowed value for year.
54       */
55      public static final int MAX_YEAR = 2200;
56  
57      /**
58       * Min allowed value for day.
59       */
60      private static final int MIN_DAY = 1;
61  
62      /**
63       * Min allowed value for hour.
64       */
65      private static final int MIN_HOUR = 0;
66  
67      /**
68       * Min allowed value for month.
69       */
70      private static final int MIN_MONTH = 1;
71  
72      /**
73       * Min allowed value for year.
74       */
75      public static final int MIN_YEAR = 1800;
76  
77      /**
78       * UUID for Serializable.
79       */
80      private static final long serialVersionUID = -4030595237342420098L;
81  
82      /**
83       * Computed date.
84       */
85      private Date date;
86  
87      /**
88       * Day (1-31).
89       */
90      @Getter
91      private Integer day;
92  
93      /**
94       * Hour in the day [0-23].
95       */
96      @Getter
97      private Integer hour;
98  
99      /**
100      * Month (1-12).
101      */
102     @Getter
103     private Integer month;
104 
105     /**
106      * All values used by indicators.
107      */
108     private final Double[] values = new Double[Variable.values().length];
109 
110     /**
111      * Year.
112      */
113     @Getter
114     private Integer year;
115 
116     /**
117      * Constructor.
118      */
119     protected HourlyData() {
120     }
121 
122     /**
123      * Copy constructor.
124      *
125      * @param data instance to copy
126      */
127     protected HourlyData(final HourlyData data) {
128         this.hour = data.hour;
129         this.day = data.day;
130         this.month = data.month;
131         this.year = data.year;
132         System.arraycopy(data.values, 0, this.values, 0, data.values.length);
133     }
134 
135     @Override
136     @SuppressWarnings("checkstyle:DesignForExtension")
137     protected HourlyData clone() throws CloneNotSupportedException {
138         final HourlyData clone = (HourlyData) super.clone();
139         clone.hour = hour;
140         clone.day = day;
141         clone.month = month;
142         clone.year = year;
143         System.arraycopy(values, 0, clone.values, 0, values.length);
144         return clone;
145     }
146 
147     /**
148      * Create date object with {@code day}, {@code month}, {@code year} and {@code hour} attribute.<br>
149      * If at least one of these attributes is null, then the returned date is null.
150      * @return date object
151      */
152     public Date getDate() {
153         if (date != null) {
154             return date;
155         }
156         if (day == null || month == null || year == null || hour == null) {
157             return null;
158         }
159         final Calendar cal = DateUtils.getCalendar();
160         cal.set(Calendar.DAY_OF_MONTH, day);
161         cal.set(Calendar.MONTH, month - 1);
162         cal.set(Calendar.YEAR, year);
163         cal.set(Calendar.HOUR_OF_DAY, hour);
164         cal.set(Calendar.MINUTE, 0);
165         cal.set(Calendar.SECOND, 0);
166         cal.set(Calendar.MILLISECOND, 0);
167         date = cal.getTime();
168         return date;
169     }
170 
171     /**
172      * @return day of year
173      */
174     public final int getDayOfYear() {
175         return DateUtils.getDoy(getDate());
176     }
177 
178     /**
179      * Create date object with {@code day}, {@code month}, {@code year} and {@code hour} attribute.<br>
180      * If at least one of these attributes is null, then the returned date is null.
181      * @return date object
182      */
183     public LocalDate getLocalDate() {
184         return DateUtils.asLocalDate(getDate());
185     }
186 
187     /**
188      * Get value for variable as it was set.
189      *
190      * @param variable climatic/soil variable
191      * @return value
192      */
193     public final Double getRawValue(final Variable variable) {
194         return values[variable.ordinal()];
195     }
196 
197     /**
198      * Get value for variable.
199      *
200      * @param variable climatic/soil variable
201      * @return value
202      */
203     public abstract Double getValue(Variable variable);
204 
205     /**
206      * @param value
207      *            the day of month to set
208      */
209     public final void setDay(final Integer value) {
210         if (value != null) {
211             if (value > MAX_DAY) {
212                 throw new IllegalArgumentException("Day of month must be inferior to " + MAX_DAY + " : " + value);
213             }
214             if (value < MIN_DAY) {
215                 throw new IllegalArgumentException("Day of month must be superior to " + MIN_DAY + " : " + value);
216             }
217         }
218         this.day = value;
219         this.date = null;
220     }
221 
222     /**
223      * @param value
224      *            the hour to set
225      */
226     public final void setHour(final Integer value) {
227         if (value != null) {
228             if (value > MAX_HOUR) {
229                 throw new IllegalArgumentException("Hour must be inferior to " + MAX_HOUR + " : " + value);
230             }
231             if (value < MIN_HOUR) {
232                 throw new IllegalArgumentException("Hour must be superior to " + MIN_HOUR + " : " + value);
233             }
234         }
235         this.hour = value;
236         this.date = null;
237     }
238 
239     /**
240      * @param value
241      *            the the month-of-year field from 1 to 12.
242      */
243     public final void setMonth(final Integer value) {
244         if (value != null) {
245             if (value > MAX_MONTH) {
246                 throw new IllegalArgumentException("Month must be inferior to " + MAX_MONTH + " : " + value);
247             }
248             if (value < MIN_MONTH) {
249                 throw new IllegalArgumentException("Month must be superior to " + MIN_MONTH + " : " + value);
250             }
251         }
252         this.month = value;
253         this.date = null;
254     }
255 
256     /**
257      * Set value for variable.
258      *
259      * @param variable climatic/soil variable
260      * @param value value to set
261      */
262     public final void setValue(final Variable variable, final Double value) {
263         values[variable.ordinal()] = value;
264     }
265 
266     /**
267      * @param value
268      *            the year to set
269      */
270     public final void setYear(final Integer value) {
271         if (value != null) {
272             if (value > MAX_YEAR) {
273                 throw new IllegalArgumentException("Year must be inferior to " + MAX_YEAR + " : " + value);
274             }
275             if (value < MIN_YEAR) {
276                 throw new IllegalArgumentException("Year must be superior to " + MIN_YEAR + " : " + value);
277             }
278         }
279         this.year = value;
280         this.date = null;
281     }
282 }