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 */ 53 public class FacesMessage implements Serializable 54 { 55 private static final long serialVersionUID = 4851488727794169661L; 56 57 /** 58 * <code>ResourceBundle</code> identifier for messages whose message identifiers are defined in the JavaServer Faces 59 * specification. 60 */ 61 public static final String FACES_MESSAGES = "javax.faces.Messages"; 62 63 /** 64 * Message severity level indicating an informational message rather than an error. 65 */ 66 public static final FacesMessage.Severity SEVERITY_INFO = new Severity("INFO", 0); 67 68 /** 69 * Message severity level indicating that an error might have occurred. 70 */ 71 public static final FacesMessage.Severity SEVERITY_WARN = new Severity("WARN", 1); 72 73 /** 74 * Message severity level indicating that an error has occurred. 75 */ 76 public static final FacesMessage.Severity SEVERITY_ERROR = new Severity("ERROR", 2); 77 78 /** 79 * Message severity level indicating that a serious error has occurred. 80 */ 81 public static final FacesMessage.Severity SEVERITY_FATAL = new Severity("FATAL", 3); 82 83 /** 84 * Immutable <code>Lis</code> of valid {@link FacesMessage.Severity}instances, in ascending order of their ordinal 85 * value. 86 */ 87 public static final List VALUES; 88 89 /** 90 * Immutable <code>Map</code> of valid {@link FacesMessage.Severity}instances, keyed by name. 91 */ 92 public static final Map VALUES_MAP; 93 94 static 95 { 96 Map<String, FacesMessage.Severity> map = new HashMap<String, Severity>(7); 97 map.put(SEVERITY_INFO.toString(), SEVERITY_INFO); 98 map.put(SEVERITY_WARN.toString(), SEVERITY_WARN); 99 map.put(SEVERITY_ERROR.toString(), SEVERITY_ERROR); 100 map.put(SEVERITY_FATAL.toString(), SEVERITY_FATAL); 101 VALUES_MAP = Collections.unmodifiableMap(map); 102 103 List<FacesMessage.Severity> severityList = new ArrayList<Severity>(map.values()); 104 Collections.sort(severityList); // the JSF spec requires it to be sorted 105 VALUES = Collections.unmodifiableList(severityList); 106 } 107 108 private transient FacesMessage.Severity _severity; // transient, b/c FacesMessage.Severity is not Serializable 109 private String _summary; 110 private String _detail; 111 private boolean _rendered; 112 113 /** 114 *Construct a new {@link FacesMessage} with no initial values. The severity is set to Severity.INFO. 115 */ 116 public FacesMessage() 117 { 118 _severity = SEVERITY_INFO; 119 _rendered = false; 120 } 121 122 /** 123 * Construct a new {@link FacesMessage} with just a summary. The detail is null, the severity is set to 124 * <code>Severity.INFO</code>. 125 */ 126 public FacesMessage(String summary) 127 { 128 _summary = summary; 129 _severity = SEVERITY_INFO; 130 _rendered = false; 131 } 132 133 /** 134 * Construct a new {@link FacesMessage} with the specified initial values. The severity is set to Severity.INFO. 135 * 136 * @param summary 137 * - Localized summary message text 138 * @param detail 139 * - Localized detail message text 140 */ 141 public FacesMessage(String summary, String detail) 142 { 143 _summary = summary; 144 _detail = detail; 145 _severity = SEVERITY_INFO; 146 _rendered = false; 147 } 148 149 /** 150 * Construct a new {@link FacesMessage}with the specified initial values. 151 * 152 * @param severity 153 * - the severity 154 * @param summary 155 * - Localized summary message text 156 * @param detail 157 * - Localized detail message text 158 */ 159 public FacesMessage(FacesMessage.Severity severity, String summary, String detail) 160 { 161 if (severity == null) 162 { 163 throw new NullPointerException("severity"); 164 } 165 _severity = severity; 166 _summary = summary; 167 _detail = detail; 168 _rendered = false; 169 } 170 171 /** 172 * 173 * @return 174 */ 175 public FacesMessage.Severity getSeverity() 176 { 177 return _severity; 178 } 179 180 /** 181 * Return the severity level. 182 */ 183 public void setSeverity(FacesMessage.Severity severity) 184 { 185 if (severity == null) 186 { 187 throw new NullPointerException("severity"); 188 } 189 _severity = severity; 190 } 191 192 /** 193 * Return the localized summary text. 194 */ 195 public String getSummary() 196 { 197 return _summary; 198 } 199 200 /** 201 * Set the localized summary text. 202 * 203 * @param summary 204 * - The new localized summary text 205 */ 206 public void setSummary(String summary) 207 { 208 _summary = summary; 209 } 210 211 /** 212 * 213 * @return 214 */ 215 public String getDetail() 216 { 217 if (_detail == null) 218 { 219 // Javadoc: 220 // If no localized detail text has been defined for this message, return the localized summary text instead 221 return _summary; 222 } 223 return _detail; 224 } 225 226 /** 227 * Set the localized detail text. 228 * 229 * @param detail 230 * - The new localized detail text 231 */ 232 public void setDetail(String detail) 233 { 234 _detail = detail; 235 } 236 237 public boolean isRendered() 238 { 239 return _rendered; 240 } 241 242 public void rendered() 243 { 244 this._rendered = true; 245 } 246 247 private void writeObject(ObjectOutputStream out) throws IOException 248 { 249 out.defaultWriteObject(); // write summary, detail, rendered 250 out.writeInt(_severity._ordinal); // FacesMessage.Severity is not Serializable, write ordinal only 251 } 252 253 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 254 { 255 in.defaultReadObject(); // read summary, detail, rendered 256 257 // FacesMessage.Severity is not Serializable, read ordinal and get related FacesMessage.Severity 258 int severityOrdinal = in.readInt(); 259 _severity = (Severity) VALUES.get(severityOrdinal); 260 } 261 262 public static class Severity implements Comparable 263 { 264 private String _name; 265 private int _ordinal; 266 267 private Severity(String name, int ordinal) 268 { 269 _name = name; 270 _ordinal = ordinal; 271 } 272 273 public int getOrdinal() 274 { 275 return _ordinal; 276 } 277 278 @Override 279 public String toString() 280 { 281 return _name; 282 } 283 284 public int compareTo(Object o) 285 { 286 return getOrdinal() - ((Severity)o).getOrdinal(); 287 } 288 } 289 290 }