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 }