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