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 javax.faces.application;
20  
21  import java.io.IOException;
22  import java.io.ObjectInputStream;
23  import java.io.ObjectOutputStream;
24  import java.io.Serializable;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  /**
32   *<p>
33   * <code>FacesMessage</code> represents a single validation (or other) message, which is typically associated with a
34   * particular component in the view. A {@link FacesMessage} instance may be created based on a specific messageId. The
35   * specification defines the set of messageIds for which there must be {@link FacesMessage} instances.
36   * </p>
37   * 
38   * The implementation must take the following steps when creating FacesMessage instances given a messageId: 
39   * <ul>
40   * <li>Call
41   * {@link Application#getMessageBundle()}. If <code>non-null</code>, locate the named <code>ResourceBundle</code>, using
42   * the <code>Locale</code> from the current {@link javax.faces.component.UIViewRoot} and see if it has a value for 
43   * the argument
44   * <code>messageId</code>. If it does, treat the value as the <code>summary</code> of the {@link FacesMessage}. If it
45   * does not, or if {@link Application#getMessageBundle()} returned null, look in the ResourceBundle named by the value
46   * of the constant {@link #FACES_MESSAGES} and see if it has a value for the argument messageId. If it does, treat the
47   * value as the summary of the <code>FacesMessage</code>. If it does not, there is no initialization information for the
48   * <code>FacesMessage</code> instance.</li>
49   * <li>In all cases, if a <code>ResourceBundle</code> hit is found for the
50   * <code>{messageId}</code>, look for further hits under the key <code>{messageId}_detail</code>. Use this value, if
51   * present, as the <code>detail</code> for the returned <code>FacesMessage</code>.</li> 
52   * <li>Make sure to perform any
53   * parameter substitution required for the <code>summary</code> and <code>detail</code> of the <code>FacesMessage</code>
54   * .</li> 
55   * </ul>
56   * 
57   */
58  public class FacesMessage implements Serializable
59  {
60      private static final long serialVersionUID = 4851488727794169661L;
61  
62      /**
63       * <code>ResourceBundle</code> identifier for messages whose message identifiers are defined in the JavaServer Faces
64       * specification.
65       */
66      public static final String FACES_MESSAGES = "javax.faces.Messages";
67  
68      /**
69       * Message severity level indicating an informational message rather than an error.
70       */
71      public static final FacesMessage.Severity SEVERITY_INFO = new Severity("INFO", 0);
72  
73      /**
74       * Message severity level indicating that an error might have occurred.
75       */
76      public static final FacesMessage.Severity SEVERITY_WARN = new Severity("WARN", 1);
77  
78      /**
79       * Message severity level indicating that an error has occurred.
80       */
81      public static final FacesMessage.Severity SEVERITY_ERROR = new Severity("ERROR", 2);
82  
83      /**
84       * Message severity level indicating that a serious error has occurred.
85       */
86      public static final FacesMessage.Severity SEVERITY_FATAL = new Severity("FATAL", 3);
87  
88      /**
89       * Immutable <code>Lis</code> of valid {@link FacesMessage.Severity}instances, in ascending order of their ordinal
90       * value.
91       */
92      public static final List VALUES;
93  
94      /**
95       * Immutable <code>Map</code> of valid {@link FacesMessage.Severity}instances, keyed by name.
96       */
97      public static final Map VALUES_MAP;
98  
99      static
100     {
101         Map<String, FacesMessage.Severity> map = new HashMap<String, Severity>(7);
102         map.put(SEVERITY_INFO.toString(), SEVERITY_INFO);
103         map.put(SEVERITY_WARN.toString(), SEVERITY_WARN);
104         map.put(SEVERITY_ERROR.toString(), SEVERITY_ERROR);
105         map.put(SEVERITY_FATAL.toString(), SEVERITY_FATAL);
106         VALUES_MAP = Collections.unmodifiableMap(map);
107 
108         List<FacesMessage.Severity> severityList = new ArrayList<Severity>(map.values());
109         Collections.sort(severityList); // the JSF spec requires it to be sorted
110         VALUES = Collections.unmodifiableList(severityList);
111     }
112 
113     private transient FacesMessage.Severity _severity;  // transient, b/c FacesMessage.Severity is not Serializable
114     private String _summary;
115     private String _detail;
116     private boolean _rendered;
117 
118     /**
119      *Construct a new {@link FacesMessage} with no initial values. The severity is set to Severity.INFO.
120      */
121     public FacesMessage()
122     {
123         _severity = SEVERITY_INFO;
124         _rendered = false;
125     }
126 
127     /**
128      * Construct a new {@link FacesMessage} with just a summary. The detail is null, the severity is set to
129      * <code>Severity.INFO</code>.
130      */
131     public FacesMessage(String summary)
132     {
133         _summary = summary;
134         _severity = SEVERITY_INFO;
135         _rendered = false;
136     }
137 
138     /**
139      * Construct a new {@link FacesMessage} with the specified initial values. The severity is set to Severity.INFO.
140      * 
141      * @param summary
142      *            - Localized summary message text
143      * @param detail
144      *            - Localized detail message text
145      */
146     public FacesMessage(String summary, String detail)
147     {
148         _summary = summary;
149         _detail = detail;
150         _severity = SEVERITY_INFO;
151         _rendered = false;
152     }
153 
154     /**
155      * Construct a new {@link FacesMessage}with the specified initial values.
156      * 
157      * @param severity
158      *            - the severity
159      * @param summary
160      *            - Localized summary message text
161      * @param detail
162      *            - Localized detail message text
163      */
164     public FacesMessage(FacesMessage.Severity severity, String summary, String detail)
165     {
166         if (severity == null)
167         {
168             throw new NullPointerException("severity");
169         }
170         _severity = severity;
171         _summary = summary;
172         _detail = detail;
173         _rendered = false;
174     }
175 
176     /**
177      * 
178      * @return
179      */
180     public FacesMessage.Severity getSeverity()
181     {
182         return _severity;
183     }
184 
185     /**
186      * Return the severity level.
187      */
188     public void setSeverity(FacesMessage.Severity severity)
189     {
190         if (severity == null)
191         {
192             throw new NullPointerException("severity");
193         }
194         _severity = severity;
195     }
196 
197     /**
198      * Return the localized summary text.
199      */
200     public String getSummary()
201     {
202         return _summary;
203     }
204 
205     /**
206      * Set the localized summary text.
207      * 
208      * @param summary
209      *            - The new localized summary text
210      */
211     public void setSummary(String summary)
212     {
213         _summary = summary;
214     }
215 
216     /**
217      * 
218      * @return
219      */
220     public String getDetail()
221     {
222         if (_detail == null)
223         {
224             // Javadoc:
225             // If no localized detail text has been defined for this message, return the localized summary text instead
226             return _summary;
227         }
228         return _detail;
229     }
230 
231     /**
232      * Set the localized detail text.
233      * 
234      * @param detail
235      *            - The new localized detail text
236      */
237     public void setDetail(String detail)
238     {
239         _detail = detail;
240     }
241 
242     public boolean isRendered()
243     {
244         return _rendered;
245     }
246 
247     public void rendered()
248     {
249         this._rendered = true;
250     }
251 
252     private void writeObject(ObjectOutputStream out) throws IOException
253     {
254         out.defaultWriteObject();  // write summary, detail, rendered
255         out.writeInt(_severity._ordinal);  // FacesMessage.Severity is not Serializable, write ordinal only
256     }
257 
258     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
259     {
260         in.defaultReadObject();  // read summary, detail, rendered
261 
262         // FacesMessage.Severity is not Serializable, read ordinal and get related FacesMessage.Severity
263         int severityOrdinal = in.readInt();
264         _severity = (Severity) VALUES.get(severityOrdinal);
265     }
266 
267     public static class Severity implements Comparable
268     {
269         private String _name;
270         private int _ordinal;
271 
272         private Severity(String name, int ordinal)
273         {
274             _name = name;
275             _ordinal = ordinal;
276         }
277 
278         public int getOrdinal()
279         {
280             return _ordinal;
281         }
282 
283         @Override
284         public String toString()
285         {
286             return _name;
287         }
288 
289         public int compareTo(Object o)
290         {
291             return getOrdinal() - ((Severity)o).getOrdinal();
292         }
293     }
294 
295 }