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