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