View Javadoc

1   /**
2    * 2007, Digitalis Informatica. All rights reserved. Distribuicao e Gestao de Informatica, Lda. Estrada de Paco de Arcos
3    * num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999 http://www.digitalis.pt
4    */
5   package pt.digitalis.dif.dem.objects.parameters.types;
6   
7   import java.math.BigDecimal;
8   import java.util.ArrayList;
9   import java.util.Calendar;
10  import java.util.Date;
11  import java.util.List;
12  
13  import pt.digitalis.dif.controller.interfaces.IDIFContext;
14  import pt.digitalis.dif.dem.interfaces.IStageInstance;
15  import pt.digitalis.dif.dem.objects.parameters.constraints.IParameterConstraint;
16  import pt.digitalis.dif.dem.objects.parameters.errors.ParameterError;
17  import pt.digitalis.dif.dem.objects.parameters.errors.ParameterErrorList;
18  import pt.digitalis.dif.dem.objects.parameters.errors.ParameterErrorType;
19  import pt.digitalis.dif.exception.objects.ParameterException;
20  import pt.digitalis.dif.startup.DIFGeneralConfigurationParameters;
21  import pt.digitalis.utils.common.DateUtils;
22  import pt.digitalis.utils.common.StringUtils;
23  
24  /**
25   * /** This class will define a numeric Parameter.
26   * <p>
27   * It will hold information relative to the Parameter value, ID key and validation constraints.
28   * 
29   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
30   * @author Rodrigo Gon�alves <a href="mailto:rgoncalves@digitalis.pt">rgoncalves@digitalis.pt</a>
31   * @created Nov 23, 2007
32   */
33  public class DateParameter extends AbstractParameter<Date> {
34  
35      /** The list of supported classes to define in the concrete implementations */
36      @SuppressWarnings("serial")
37      final static private List<String> supportedClasses = new ArrayList<String>() {
38  
39          {
40              add(Date.class.getCanonicalName());
41          }
42      };
43  
44      /**
45       * @see pt.digitalis.dif.dem.objects.parameters.types.AbstractParameter#automaticConstraints()
46       */
47      @Override
48      protected String automaticConstraints()
49      {
50          return "date";
51      }
52  
53      /**
54       * @see pt.digitalis.dif.dem.objects.parameters.types.AbstractParameter#convertObjectToString(java.lang.Object)
55       */
56      @Override
57      protected String convertObjectToString(Object obj)
58      {
59          if (obj instanceof Date)
60              return DateUtils.simpleDateToString((Date) obj);
61          else
62              return super.convertObjectToString(obj);
63      }
64  
65      /**
66       * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getSupportedClasses()
67       */
68      public List<String> getSupportedClasses()
69      {
70          return supportedClasses;
71      }
72  
73      /**
74       * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getValueAsBigDecimal(pt.digitalis.dif.controller.interfaces.IDIFContext)
75       */
76      public BigDecimal getValueAsBigDecimal(IDIFContext context) throws ParameterException
77      {
78          return BigDecimal.valueOf(getValue(context).getTime());
79      }
80  
81      /**
82       * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getValueAsBoolean(IDIFContext)
83       */
84      public boolean getValueAsBoolean(IDIFContext context)
85      {
86          return false;
87      }
88  
89      /**
90       * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getValueAsDate(IDIFContext)
91       */
92      public Date getValueAsDate(IDIFContext context) throws ParameterException
93      {
94          return getValue(context);
95      }
96  
97      /**
98       * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getValueAsDouble(IDIFContext)
99       */
100     public Double getValueAsDouble(IDIFContext context) throws ParameterException
101     {
102         return Double.valueOf(getValue(context).getTime());
103     }
104 
105     /**
106      * @see pt.digitalis.dif.dem.objects.parameters.IParameter#getValueAsLong(IDIFContext)
107      */
108     public Long getValueAsLong(IDIFContext context) throws ParameterException
109     {
110         return getValue(context).getTime();
111     }
112 
113     /**
114      * @see pt.digitalis.dif.dem.objects.parameters.types.AbstractParameter#getValueAsString(IDIFContext)
115      */
116     @Override
117     public String getValueAsString(IDIFContext context) throws ParameterException
118     {
119 
120         Date currentDate = getValue(context);
121 
122         if (currentDate == null)
123             return null;
124         else
125             return DateUtils.simpleDateToString(currentDate);
126     }
127 
128     /**
129      * @see pt.digitalis.dif.dem.objects.parameters.IParameter#isNumeric()
130      */
131     public boolean isNumeric()
132     {
133         return false;
134     }
135 
136     /**
137      * @see pt.digitalis.dif.dem.objects.parameters.IParameter#setValueFromString(java.lang.String,
138      *      pt.digitalis.dif.dem.interfaces.IStageInstance, boolean)
139      */
140     public ParameterErrorList setValueFromString(String value, IStageInstance stageInstance,
141             boolean initializationInProgress)
142     {
143 
144         ParameterErrorList list = new ParameterErrorList(this, value);
145         ParameterError error;
146         IParameterConstraint constraint = getConstraints().get("date");
147         IDIFContext context;
148 
149         if (stageInstance == null)
150             context = null;
151         else
152             context = stageInstance.getContext();
153 
154         // If the date constraint does not validate...
155         if (!constraint.validateConstraint(value, stageInstance))
156         {
157             String language;
158 
159             if (context == null)
160                 language = DIFGeneralConfigurationParameters.getInstance().getDefaultLanguage();
161             else
162                 language = context.getLanguage();
163 
164             error = new ParameterError(constraint.validationErrorMessage(language), ParameterErrorType.CONSTRAINT);
165             error.setConstraint("date", constraint);
166 
167             list.addError(error);
168         }
169         else
170         {
171             // Valid date format, see if date conversion has a format constraint to use
172             if (getConstraints().containsKey("futuredate") || getConstraints().containsKey("pastdate")
173                     || getConstraints().containsKey("absolutedate") || getConstraints().containsKey("relativedate"))
174             {
175                 String[] parts = value.split("/");
176 
177                 if (parts[2].length() < 3)
178                 {
179                     // If single digit year fill with left zero
180                     parts[2] = StringUtils.fillStringLeft(parts[2], 2, "0");
181                     Calendar currentDate = Calendar.getInstance();
182                     Integer currentCenturyPrefix = currentDate.get(Calendar.YEAR) / 100;
183                     Integer valueDateYear2Digits = Integer.parseInt(parts[2]);
184                     Integer currentDateYear2Digits = currentDate.get(Calendar.YEAR) % 100;
185                     Calendar currentCenturyTempDate = Calendar.getInstance();
186                     currentCenturyTempDate.set(currentCenturyPrefix * 100 + valueDateYear2Digits,
187                             Integer.parseInt(parts[1]), Integer.parseInt(parts[0]));
188 
189                     if (getConstraints().containsKey("pastdate"))
190                     {
191                         if (currentCenturyTempDate.before(currentDate))
192                             parts[2] = currentCenturyPrefix + parts[2];
193                         else
194                             parts[2] = (currentCenturyPrefix - 1) + parts[2];
195                     }
196                     else if (getConstraints().containsKey("futuredate"))
197                     {
198                         if (currentCenturyTempDate.after(currentDate))
199                             parts[2] = currentCenturyPrefix + parts[2];
200                         else
201                             parts[2] = (currentCenturyPrefix + 1) + parts[2];
202                     }
203                     else if (getConstraints().containsKey("relativedate"))
204                     {
205                         // Relative date => compare to current year
206                         if (Math.abs(valueDateYear2Digits - currentDateYear2Digits) <= Math.abs(currentDateYear2Digits
207                                 - valueDateYear2Digits + 100))
208                             // Closer to current century => add current century
209                             parts[2] = currentCenturyPrefix + parts[2];
210                         else
211                             // Closer to previous century => add previous century
212                             parts[2] = (currentCenturyPrefix - 1) + parts[2];
213                     }
214                     else if (getConstraints().containsKey("absolutedate"))
215                         // Absolute Date => add current century
216                         parts[2] = currentCenturyPrefix + parts[2];
217                 }
218 
219                 // Reassemble the parsed date
220                 value = parts[0] + "/" + parts[1] + "/" + parts[2];
221             }
222 
223             try
224             {
225                 if (value == null || "".equals(value))
226                     return setValue(null, stageInstance, initializationInProgress);
227                 else
228                     return setValue(DateUtils.stringToSimpleDate(value), stageInstance, initializationInProgress);
229 
230             }
231             catch (Exception e)
232             {
233                 /*
234                  * Unreachable exception: to get here DateUtils#stringToDate() would have to throw a ParseException.
235                  * This exception is raised when the beginning of the passed string can't be parsed. This would happen
236                  * if a bad date value was passed. This situation is avoided by the constraint validation mechanism. So
237                  * if a bad value is passed the code never enters the 'else' branch and as such is never possible to get
238                  * here.
239                  */
240                 error = new ParameterError("Error parsing value", ParameterErrorType.OTHER);
241                 error.setException(e);
242                 list.addError(error);
243             }
244         }
245 
246         return list;
247     }
248 }