View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.commons.validator;
20  
21  import java.io.Serializable;
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  
29  import javax.el.ValueExpression;
30  import javax.faces.application.FacesMessage;
31  import javax.faces.component.StateHolder;
32  import javax.faces.context.FacesContext;
33  import javax.faces.validator.Validator;
34  
35  import org.apache.myfaces.commons.util.MessageUtils;
36  
37  /**
38   * Base validator implementation for Apache MyFaces Commons Validators.
39   *
40   * @JSFValidator
41   *   configExcluded = "true"
42   *   tagClass = "org.apache.myfaces.commons.validator.ValidatorBaseTag"
43   */
44  public abstract class ValidatorBase implements StateHolder, Validator {
45  
46      private String _summaryMessage = null;
47      private String _detailMessage = null;
48      private boolean _transient = false;
49  
50      /**
51       * alternate validation error summary message format string
52       * 
53       * @JSFProperty
54       * @return  The summary message to be displayed
55       */
56      public String getSummaryMessage()
57      {
58          if (_summaryMessage != null) return _summaryMessage;
59          ValueExpression expression = getValueExpression("summaryMessage");
60          return expression != null ? getStringValue(getFacesContext(), expression) : null;
61      }
62  
63      /**
64       *
65       * @param message   The summary message to be displayed.
66       */
67      public void setSummaryMessage(String message) {
68          _summaryMessage = message;
69      }
70  
71      /**
72       * alternate validation error detail message format string 
73       * (use 'message' and 'detailMessage' alternatively)
74       * 
75       * @JSFProperty
76       * @return  The message.
77       * @deprecated Use getDetailMessage()
78       */
79      public String getMessage() {
80          return getDetailMessage();
81      }
82  
83      /**
84       *
85       * @param message  The detail message to be displayed.
86       * @deprecated Use setDetailMessage()
87       */
88      public void setMessage(String message) {
89          setDetailMessage(message);
90      }
91  
92  
93      /**
94       * alternate validation error detail message format string 
95       * (use 'message' and 'detailMessage' alternatively)
96       *
97       * @JSFProperty
98       * @return  The detail message.
99       */
100     public String getDetailMessage() {
101         if (_detailMessage != null) return _detailMessage;
102         ValueExpression vb = getValueExpression("detailMessage");
103         return vb != null ? getStringValue(getFacesContext(), vb) : null;
104     }
105 
106     /**
107      *
108      * @param message  The detail message to be displayed.
109      */
110     public void setDetailMessage(String message) {
111         _detailMessage = message;
112     }
113 
114 
115     /**
116      * @param context
117      */
118     public Object saveState(FacesContext context) {
119         Object[] state = new Object[3];
120         state[0] = _summaryMessage;
121         state[1] = _detailMessage;
122         state[2] = saveValueExpressionMap(context);
123         return state;
124     }
125 
126     public void restoreState(FacesContext context, Object state) {
127         Object[] values = (Object[]) state;
128         _summaryMessage = (String) values[0];
129         _detailMessage = (String) values[1];
130         restoreValueExpressionMap(context, values[2]);
131     }
132 
133     public boolean isTransient() {
134         return _transient;
135     }
136 
137     public void setTransient(boolean newTransientValue) {
138         _transient = newTransientValue;
139     }
140 
141     // Utility methods
142 
143     /**
144      * @param defaultMessage The default message we would expect.
145      * @param args Arguments for parsing this message.
146      * @return FacesMessage
147      */
148     protected FacesMessage getFacesMessage(String defaultMessage, Object[] args) {
149         FacesMessage msg;
150 
151         if (getSummaryMessage() == null && getDetailMessage() == null)
152         {
153             msg = MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, defaultMessage, args);
154         } else {
155             Locale locale = MessageUtils.getCurrentLocale();
156             String summaryText = MessageUtils.substituteParams(locale, getSummaryMessage(), args);
157             String detailText = MessageUtils.substituteParams(locale, getDetailMessage(), args);
158             msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryText, detailText);
159         }
160         return msg;
161     }
162 
163     // --------------------- borrowed from UIComponentBase ------------
164 
165     private Map _valueExpressionMap = null;
166 
167     public ValueExpression getValueExpression(String name)
168     {
169         if (name == null) throw new NullPointerException("name");
170         if (_valueExpressionMap == null)
171         {
172             return null;
173         }
174         else
175         {
176             return (ValueExpression)_valueExpressionMap.get(name);
177         }
178     }
179 
180     public void setValueExpression(String name,
181                                 ValueExpression binding)
182     {
183         if (name == null) throw new NullPointerException("name");
184         if (_valueExpressionMap == null)
185         {
186             _valueExpressionMap = new HashMap();
187         }
188         _valueExpressionMap.put(name, binding);
189     }
190 
191     private Object saveValueExpressionMap(FacesContext context)
192     {
193         if (_valueExpressionMap != null)
194         {
195             int initCapacity = (_valueExpressionMap.size() * 4 + 3) / 3;
196             HashMap stateMap = new HashMap(initCapacity);
197             for (Iterator it = _valueExpressionMap.entrySet().iterator(); it.hasNext(); )
198             {
199                 Map.Entry entry = (Map.Entry)it.next();
200                 stateMap.put(entry.getKey(),
201                              saveAttachedState(context, entry.getValue()));
202             }
203             return stateMap;
204         }
205         else
206         {
207             return null;
208         }
209     }
210 
211     private void restoreValueExpressionMap(FacesContext context, Object stateObj)
212     {
213         if (stateObj != null)
214         {
215             Map stateMap = (Map)stateObj;
216             int initCapacity = (stateMap.size() * 4 + 3) / 3;
217             _valueExpressionMap = new HashMap(initCapacity);
218             for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
219             {
220                 Map.Entry entry = (Map.Entry)it.next();
221                 _valueExpressionMap.put(entry.getKey(),
222                                      restoreAttachedState(context, entry.getValue()));
223             }
224         }
225         else
226         {
227             _valueExpressionMap = null;
228         }
229     }
230 
231     /**
232      * Serializes objects which are "attached" to this component but which are
233      * not UIComponent children of it. Examples are validator and listener
234      * objects. To be precise, it returns an object which implements
235      * java.io.Serializable, and which when serialized will persist the
236      * state of the provided object.
237      * <p>
238      * If the attachedObject is a List then every object in the list is saved
239      * via a call to this method, and the returned wrapper object contains
240      * a List object.
241      * <p>
242      * If the object implements StateHolder then the object's saveState is
243      * called immediately, and a wrapper is returned which contains both
244      * this saved state and the original class name. However in the case
245      * where the StateHolder.isTransient method returns true, null is
246      * returned instead.
247      * <p>
248      * If the object implements java.io.Serializable then the object is simply
249      * returned immediately; standard java serialization will later be used
250      * to store this object.
251      * <p>
252      * In all other cases, a wrapper is returned which simply stores the type
253      * of the provided object. When deserialized, a default instance of that
254      * type will be recreated.
255      */
256     public static Object saveAttachedState(FacesContext context,
257                                            Object attachedObject)
258     {
259         if (attachedObject == null) return null;
260         if (attachedObject instanceof List)
261         {
262             List lst = new ArrayList(((List)attachedObject).size());
263             for (Iterator it = ((List)attachedObject).iterator(); it.hasNext(); )
264             {
265                 lst.add(saveAttachedState(context, it.next()));
266             }
267             return new _AttachedListStateWrapper(lst);
268         }
269         else if (attachedObject instanceof StateHolder)
270         {
271             if (((StateHolder)attachedObject).isTransient())
272             {
273                 return null;
274             }
275             else
276             {
277                 return new _AttachedStateWrapper(attachedObject.getClass(),
278                                                  ((StateHolder)attachedObject).saveState(context));
279             }
280         }
281         else if (attachedObject instanceof Serializable)
282         {
283             return attachedObject;
284         }
285         else
286         {
287             return new _AttachedStateWrapper(attachedObject.getClass(), null);
288         }
289     }
290 
291     public static Object restoreAttachedState(FacesContext context,
292                                               Object stateObj)
293             throws IllegalStateException
294     {
295         if (context == null) throw new NullPointerException("context");
296         if (stateObj == null) return null;
297         if (stateObj instanceof _AttachedListStateWrapper)
298         {
299             List lst = ((_AttachedListStateWrapper)stateObj).getWrappedStateList();
300             List restoredList = new ArrayList(lst.size());
301             for (Iterator it = lst.iterator(); it.hasNext(); )
302             {
303                 restoredList.add(restoreAttachedState(context, it.next()));
304             }
305             return restoredList;
306         }
307         else if (stateObj instanceof _AttachedStateWrapper)
308         {
309             Class clazz = ((_AttachedStateWrapper)stateObj).getClazz();
310             Object restoredObject;
311             try
312             {
313                 restoredObject = clazz.newInstance();
314             }
315             catch (InstantiationException e)
316             {
317                 throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() + " (missing no-args constructor?)", e);
318             }
319             catch (IllegalAccessException e)
320             {
321                 throw new RuntimeException(e);
322             }
323             if (restoredObject instanceof StateHolder)
324             {
325                 Object wrappedState = ((_AttachedStateWrapper)stateObj).getWrappedStateObject();
326                 ((StateHolder)restoredObject).restoreState(context, wrappedState);
327             }
328             return restoredObject;
329         }
330         else
331         {
332             return stateObj;
333         }
334     }
335 
336 
337     protected FacesContext getFacesContext()
338     {
339         return FacesContext.getCurrentInstance();
340     }
341     protected String getStringValue(FacesContext context, ValueExpression vb)
342     {
343         Object value = vb.getValue(context.getELContext());
344         if (value != null)
345         {
346             return value.toString();
347         }
348         return null;
349     }
350 }