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.errors;
6   
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  import java.util.Map.Entry;
12  
13  import pt.digitalis.dif.controller.http.HTTPConstants;
14  import pt.digitalis.dif.controller.interfaces.IDIFContext;
15  import pt.digitalis.dif.dem.interfaces.ICustomFormDefinition;
16  import pt.digitalis.dif.dem.interfaces.IStageInstance;
17  import pt.digitalis.dif.dem.managers.ICustomFormManager;
18  import pt.digitalis.dif.dem.managers.IParameterManager;
19  import pt.digitalis.dif.dem.objects.FeatureState;
20  import pt.digitalis.dif.dem.objects.FormFieldCustomization;
21  import pt.digitalis.dif.dem.objects.parameters.IEditableParameter;
22  import pt.digitalis.dif.dem.objects.parameters.IParameter;
23  import pt.digitalis.dif.dem.objects.parameters.types.AbstractParameter;
24  import pt.digitalis.dif.exception.objects.ParameterException;
25  import pt.digitalis.dif.ioc.DIFIoCRegistry;
26  import pt.digitalis.dif.utils.ObjectFormatter;
27  import pt.digitalis.dif.utils.extensions.ICaptcha;
28  import pt.digitalis.utils.common.StringUtils;
29  
30  /**
31   * A report object of any parameter errors that have occurred in the initialization of a stage. These will be injected
32   * into a stage attribute for evaluation by the stage as the developer sees fit.
33   * 
34   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
35   * @author Rodrigo Gon�alves <a href="mailto:rgoncalves@digitalis.pt">rgoncalves@digitalis.pt</a>
36   */
37  public class ParameterErrors {
38  
39      /** the captcha implementation */
40      private static ICaptcha captcha = null;
41  
42      /** A Map of all errors by parameter name. */
43      private final Map<String, ParameterErrorList> errors = new HashMap<String, ParameterErrorList>();
44  
45      /**
46       * Liswt of parameters that the errors must be ignored, since a form customization (or any other feature that so
47       * desires) has instructed the form to ignore these fields
48       */
49      List<String> parametersTodiscardErrors = new ArrayList<String>();
50  
51      /**
52       * keeps track of all refreshed parameter called by the refreshParameter method. this is used to know what
53       * parameters must still be initialized for declared custom parameters
54       */
55      private List<String> refreshedParameters = new ArrayList<String>();
56  
57      /** the current stage instance. */
58      private final IStageInstance stageInstance;
59  
60      /**
61       * Constructor.
62       * 
63       * @param stageInstance
64       *            the current stage
65       */
66      public ParameterErrors(IStageInstance stageInstance)
67      {
68          this.stageInstance = stageInstance;
69      }
70  
71      /**
72       * Adds a new parameter to.
73       * 
74       * @param parameterId
75       *            the parameter to add the error to
76       * @param error
77       *            the error
78       * @throws ParameterException
79       *             if the parameter does not exist
80       */
81      public void addParameterError(String parameterId, ParameterError error) throws ParameterException
82      {
83          // Must ignore errors for parameters that the form configuration has determined as invisible!
84          if (!parametersTodiscardErrors.contains(parameterId))
85          {
86              if (parameterId != null)
87                  parameterId = parameterId.toLowerCase();
88  
89              ParameterErrorList errorsForParameter = getErrorsForParameter(parameterId);
90  
91              if (errorsForParameter == null)
92              {
93                  IParameter<?> parameter = null;
94                  Object parameterValue = null;
95  
96                  if (parameterId != null && !"".equals(parameterId))
97                  {
98                      // Error for a specific parameter
99                      parameter = DIFIoCRegistry.getRegistry().getImplementation(IParameterManager.class)
100                             .getParameters(stageInstance).getParameter(parameterId);
101 
102                     if (parameter == null)
103                         // Changed so that custom stage instance parameters are picked up here...
104                         parameter = stageInstance.getParameters().getStageParameters().getParameter(parameterId);
105 
106                     if (parameter == null)
107                         throw new ParameterException("Parameter \"" + parameterId + "\" does not exist in the stage \""
108                                 + stageInstance.getID() + "\" context.", parameter);
109 
110                     try
111                     {
112                         parameterValue = parameter.getValue(stageInstance.getContext());
113                     }
114                     catch (ParameterException e)
115                     {
116                         // Nothing to do!
117                     }
118                 }
119 
120                 errorsForParameter = new ParameterErrorList(parameter, parameterValue);
121                 errors.put(parameterId, errorsForParameter);
122             }
123 
124             errorsForParameter.addError(error);
125         }
126     }
127 
128     /**
129      * Discards all errors.
130      */
131     public void discardAllErrors()
132     {
133         errors.clear();
134         stageInstance.setParameterErrors(this);
135     }
136 
137     /**
138      * Discards all errors for a specific parameter.
139      * 
140      * @param parameterId
141      *            the parameter to discard errors
142      */
143     public void discardErrors(String parameterId)
144     {
145         errors.remove(parameterId.toLowerCase());
146         stageInstance.setParameterErrors(this);
147     }
148 
149     /**
150      * Discards all errors for a specific parameter.
151      * 
152      * @param type
153      *            the parameter type of errors to discard
154      */
155     public void discardErrorsOfType(ParameterErrorType type)
156     {
157         for (Entry<String, ParameterErrorList> listEntry: errors.entrySet())
158         {
159 
160             ParameterErrorList value = listEntry.getValue();
161             List<ParameterError> previousErrorList = value.getErrorList();
162             List<ParameterError> newErrorList = new ArrayList<ParameterError>();
163 
164             for (ParameterError error: previousErrorList)
165                 if (!error.getErrorType().equals(type))
166                     newErrorList.add(error);
167 
168             value.setErrorList(newErrorList);
169             errors.put(listEntry.getKey(), value);
170         }
171 
172         stageInstance.setParameterErrors(this);
173     }
174 
175     /**
176      * Get all errors for all parameters.
177      * 
178      * @return the errors
179      */
180     public Map<String, ParameterErrorList> getAllParameterErrors()
181     {
182         return errors;
183     }
184 
185     /**
186      * Retrieves the errors for a given parameter ID.
187      * 
188      * @param parameterID
189      *            the desired parameter id
190      * @return the parameter list
191      */
192     public ParameterErrorList getErrorsForParameter(String parameterID)
193     {
194         if (parameterID == null)
195             return null;
196         else
197             return errors.get(parameterID.toLowerCase());
198     }
199 
200     /**
201      * Checks if errors exist.
202      * 
203      * @return T if there are errors
204      */
205     public boolean hasErrors()
206     {
207         for (ParameterErrorList list: errors.values())
208         {
209             if (list.getErrorList().size() > 0)
210                 return true;
211         }
212 
213         return false;
214     }
215 
216     /**
217      * Checks if errors exist.
218      * 
219      * @param formName
220      *            the form name
221      * @return T if there are errors
222      */
223     public boolean hasErrorsForForm(String formName)
224     {
225         for (ParameterErrorList list: errors.values())
226         {
227             if (list.getParameter() != null && formName.equalsIgnoreCase(list.getParameter().getFormLinked())
228                     && list.getErrorList() != null && list.getErrorList().size() > 0)
229                 return true;
230         }
231 
232         return false;
233     }
234 
235     /**
236      * Checks if errors exist. Will ignore all errors related with partial submit of a form. Required fields not
237      * submited. But validating errors in the fields that were filled.
238      * 
239      * @return T if there are errors
240      */
241     public boolean hasErrorsIgnoreParcialSubmitErrors()
242     {
243         for (ParameterErrorList list: errors.values())
244             for (ParameterError error: list.getErrorList())
245 
246                 // If a non MISSING error is found, there are non-partioal-submit errors
247                 if (!ParameterErrorType.MISSING.equals(error.getErrorType()))
248                     return true;
249 
250         return false;
251     }
252 
253     /**
254      * Refreshes the passed parameter and adds errors to the list if they are detected.
255      * 
256      * @param param
257      *            the parameter to refresh
258      * @param stageInstance
259      *            the stage of the refresh request
260      * @return the refreshed value
261      */
262     public Object refreshParameter(IParameter<?> param, IStageInstance stageInstance)
263     {
264         Object result = null;
265         this.refreshedParameters.add(param.getId().toLowerCase());
266 
267         if (stageInstance != null)
268         {
269             IDIFContext context = stageInstance.getContext();
270 
271             // Get custom form configuration if present
272             ICustomFormDefinition customFormDef = null;
273             FormFieldCustomization customFormFieldDef = null;
274             Object currentFormNameObj = context.getRequest().getParameter(HTTPConstants.FORM_SUBMIT_STAGE);
275             boolean stageContainsForm = context.getStage().equalsIgnoreCase(
276                     currentFormNameObj == null ? null : currentFormNameObj.toString());
277 
278             boolean parameterIsFromForm = false;
279 
280             String paramFormName = param.getFormLinked();
281             String formSubmitName = (String) context.getRequest().getParameter(HTTPConstants.FORM_SUBMIT_NAME);
282             String formConfigID = (String) context.getRequest().getParameter(
283                     HTTPConstants.FORM_SUBMIT__CONFIG_BUSINESS_ID);
284 
285             if (paramFormName != null && formSubmitName != null)
286                 parameterIsFromForm = paramFormName.equals(formSubmitName);
287 
288             // Form parameter that has a configuration active (as submited by the form)
289             if (parameterIsFromForm && param.isFormConfigurable())
290             {
291                 customFormDef = DIFIoCRegistry.getRegistry().getImplementation(ICustomFormManager.class)
292                         .getConfiguration(stageInstance, formConfigID);
293 
294                 if (customFormDef != null)
295                 {
296                     customFormFieldDef = customFormDef.getCustomizedParameters().get(param.getId().toLowerCase());
297 
298                     if (customFormFieldDef != null && customFormFieldDef.getMandatory() != FeatureState.DEFAULT)
299                         ((IEditableParameter) param).setRequired(customFormFieldDef.getMandatory() == FeatureState.ON);
300                 }
301             }
302 
303             ParameterErrorList list;
304 
305             // Refresh the value and collect any errors that may occur
306             list = param.refreshParameterValue(stageInstance);
307 
308             try
309             {
310                 result = param.getValue(context);
311 
312             }
313             catch (ParameterException e)
314             {
315                 ParameterError error = new ParameterError(e.getMessage(), ParameterErrorType.OTHER);
316                 list.addError(error);
317             }
318 
319             // Form parameter that has a configuration active (as submited by the form)
320             if (customFormDef != null && customFormDef.getExcludedParameters().contains(param.getId()))
321             {
322                 list.getErrorList().clear();
323                 parametersTodiscardErrors.add(param.getId());
324             }
325 
326             if (list.getErrorList().size() > 0)
327             {
328                 // If the parameter is not link to any form or is linked to form that was submitted, add errors if they
329                 // exist
330                 if (param.getFormLinked() == null || stageContainsForm && parameterIsFromForm)
331                 {
332                     errors.put(param.getId(), list);
333                 }
334                 else
335                 {
336                     // Search reported error to see which errors force reporting
337                     ParameterErrorList forcedErrors = new ParameterErrorList(list.getParameter(),
338                             list.getAttemptedValue());
339 
340                     for (ParameterError error: list.getErrorList())
341                         if (error.isForceShowError())
342                             forcedErrors.addError(error);
343 
344                     if (forcedErrors.getErrorList().size() > 0)
345                     {
346                         errors.put(param.getId(), forcedErrors);
347                     }
348                 }
349             }
350         }
351 
352         return result;
353     }
354 
355     /**
356      * Refreshes all remaining parameters and adds errors to the list if they are detected.
357      * 
358      * @param stageInstance
359      *            the stage of the refresh request
360      * @throws ParameterException
361      */
362     public void refreshParameters(IStageInstance stageInstance) throws ParameterException
363     {
364         for (IParameter<?> parameter: stageInstance.getParameters().getStageParameters().getParameters().values())
365             if (!this.refreshedParameters.contains(parameter.getId().toLowerCase()))
366                 this.refreshParameter(parameter, stageInstance);
367 
368         if (stageInstance.isFeatureEnabled(ICaptcha.CAPTCHA_PRESENT))
369         {
370             // Has captcha, must validate it for the given form is any was submited
371             Object submitStage = stageInstance.getContext().getRequest().getParameter(HTTPConstants.FORM_SUBMIT_STAGE);
372             Object submitForm = stageInstance.getContext().getRequest().getParameter(HTTPConstants.FORM_SUBMIT_NAME);
373 
374             if (submitStage != null && stageInstance.getID().equalsIgnoreCase(submitStage.toString())
375                     && submitForm != null
376                     && stageInstance.isFeatureEnabled(ICaptcha.CAPTCHA_PRESENT + ":" + submitForm.toString()))
377             {
378                 if (captcha == null)
379                     captcha = DIFIoCRegistry.getRegistry().getImplementation(ICaptcha.class);
380 
381                 if (!captcha.isCaptchaValueValid(stageInstance.getContext()))
382                 {
383 
384                     if (StringUtils.isBlank(captcha.getCaptchaSubmitedValue(stageInstance.getContext())))
385                     {
386                         if (this.getErrorsForParameter(ICaptcha.CAPTCHA_INPUT_ID).getErrorList().isEmpty())
387                             this.addParameterError(ICaptcha.CAPTCHA_INPUT_ID, new ParameterError(AbstractParameter
388                                     .getMessages().getMessages(stageInstance.getContext().getLanguage())
389                                     .get("required"), ParameterErrorType.MISSING));
390                     }
391                     else
392                         this.addParameterError(
393                                 ICaptcha.CAPTCHA_INPUT_ID,
394                                 new ParameterError(AbstractParameter.getMessages()
395                                         .getMessages(stageInstance.getContext().getLanguage()).get("captchaInvalid"),
396                                         ParameterErrorType.OTHER));
397                 }
398             }
399         }
400     }
401 
402     /**
403      * @see java.lang.Object#toString()
404      */
405     @Override
406     public String toString()
407     {
408         ObjectFormatter formatter = new ObjectFormatter();
409         formatter.addItem("Errors", errors);
410 
411         return formatter.getFormatedObject();
412     }
413 }