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 }