001: package nl.knowlogy.validation.jsf.renderkit.html;
002:
003: import java.io.IOException;
004: import java.util.Iterator;
005: import java.util.Map;
006:
007: import javax.faces.application.FacesMessage;
008: import javax.faces.component.UIComponent;
009: import javax.faces.component.UIMessage;
010: import javax.faces.component.UIViewRoot;
011: import javax.faces.context.FacesContext;
012: import javax.faces.context.ResponseWriter;
013:
014: import nl.knowlogy.validation.Message;
015: import nl.knowlogy.validation.MessageType;
016: import nl.knowlogy.validation.jsf.component.html.HtmlRenderer;
017: import nl.knowlogy.validation.jsf.component.html.ValidationHtmlMessage;
018: import nl.knowlogy.validation.jsf.renderkit.HtmlRendererUtils;
019: import nl.knowlogy.validation.jsf.utils.HTML;
020: import nl.knowlogy.validation.jsf.utils.JSFAttr;
021: import nl.knowlogy.validation.jsf.utils.JsfUtils;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: /**
027: */
028: public abstract class ValidationHtmlMessageRendererBase extends
029: HtmlRenderer {
030: private static final Log log = LogFactory
031: .getLog(ValidationHtmlMessageRendererBase.class);
032:
033: protected abstract String getSummary(FacesContext facesContext,
034: UIComponent message, FacesMessage facesMessage,
035: String msgClientId);
036:
037: protected abstract String getDetail(FacesContext facesContext,
038: UIComponent message, FacesMessage facesMessage,
039: String msgClientId);
040:
041: protected void renderMessage(FacesContext facesContext,
042: UIComponent message) throws IOException {
043: renderMessage(facesContext, message, false);
044: }
045:
046: /**
047: * @param facesContext
048: * @param validationHtmlMessage
049: * @param alwaysRenderSpan
050: * if true will render a span even if there is no message
051: */
052: protected void renderMessage(FacesContext facesContext,
053: UIComponent validationHtmlMessage, boolean alwaysRenderSpan)
054: throws IOException {
055: String forAttr = getFor(validationHtmlMessage);
056: if (forAttr == null) {
057: log.error("Attribute 'for' of UIMessage must not be null");
058: return;
059: }
060:
061: UIComponent forComponent = validationHtmlMessage
062: .findComponent(forAttr);
063: if (forComponent == null) {
064: log
065: .error("Could not render Message. Unable to find component '"
066: + forAttr
067: + "' (calling findComponent on component '"
068: + validationHtmlMessage
069: .getClientId(facesContext)
070: + "'). If the provided id was correct, wrap the message and its component into an h:panelGroup or h:panelGrid.");
071: return;
072: }
073:
074: String clientId = forComponent.getClientId(facesContext);
075:
076: Iterator messageIterator = facesContext.getMessages(clientId);
077: Iterator validationMessageIterator = ((ValidationHtmlMessage) validationHtmlMessage)
078: .getValidationMessages(facesContext).iterator();
079: if (!messageIterator.hasNext()
080: && !validationMessageIterator.hasNext()) {
081: // No associated message, nothing to render
082: if (alwaysRenderSpan) {
083: // show span anyways in case there's a client side update, ie:
084: // ajax
085: ResponseWriter writer = facesContext
086: .getResponseWriter();
087: writer.startElement(HTML.SPAN_ELEM,
088: validationHtmlMessage);
089: writer.writeAttribute(HTML.ID_ATTR,
090: validationHtmlMessage.getId(), null);
091: writer.endElement(HTML.SPAN_ELEM);
092: }
093: } else {
094:
095: // get first message
096: FacesMessage facesMessage;
097: if (messageIterator.hasNext()) {
098: facesMessage = (FacesMessage) messageIterator.next();
099: } else {
100: Message message = (Message) validationMessageIterator
101: .next();
102: facesMessage = convertMessage(message);
103: }
104:
105: // and render it
106: renderSingleFacesMessage(facesContext,
107: validationHtmlMessage, facesMessage, clientId);
108: }
109: }
110:
111: private FacesMessage convertMessage(Message message) {
112: FacesMessage.Severity serverity;
113: if (MessageType.ERROR.equals(message.getMessageType())) {
114: serverity = FacesMessage.SEVERITY_ERROR;
115: } else if (MessageType.INFO.equals(message.getMessageType())) {
116: serverity = FacesMessage.SEVERITY_INFO;
117: } else {
118: serverity = FacesMessage.SEVERITY_WARN;
119: }
120:
121: return new FacesMessage(serverity, message.getMessage(), null);
122: }
123:
124: protected void renderSingleFacesMessage(FacesContext facesContext,
125: UIComponent message, FacesMessage facesMessage,
126: String messageClientId) throws IOException {
127: // determine style and style class
128: String[] styleAndClass = ValidationHtmlMessageRendererBase
129: .getStyleAndStyleClass(message, facesMessage
130: .getSeverity());
131: String style = styleAndClass[0];
132: String styleClass = styleAndClass[1];
133:
134: String summary = getSummary(facesContext, message,
135: facesMessage, messageClientId);
136: String detail = getDetail(facesContext, message, facesMessage,
137: messageClientId);
138:
139: String title = getTitle(message);
140: boolean tooltip = isTooltip(message);
141:
142: if (title == null && tooltip) {
143: title = summary;
144: }
145:
146: ResponseWriter writer = facesContext.getResponseWriter();
147:
148: boolean span = false;
149:
150: if (message.getId() != null
151: && !message.getId().startsWith(
152: UIViewRoot.UNIQUE_ID_PREFIX)) {
153: span = true;
154:
155: writer.startElement(HTML.SPAN_ELEM, message);
156:
157: HtmlRendererUtils.writeIdIfNecessary(writer, message,
158: facesContext);
159:
160: HtmlRendererUtils
161: .renderHTMLAttributes(
162: writer,
163: message,
164: HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
165: } else {
166: span = HtmlRendererUtils
167: .renderHTMLAttributesWithOptionalStartElement(
168: writer,
169: message,
170: HTML.SPAN_ELEM,
171: HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
172: }
173:
174: span |= HtmlRendererUtils
175: .renderHTMLAttributeWithOptionalStartElement(writer,
176: message, HTML.SPAN_ELEM, HTML.TITLE_ATTR,
177: title, span);
178: span |= HtmlRendererUtils
179: .renderHTMLAttributeWithOptionalStartElement(writer,
180: message, HTML.SPAN_ELEM, HTML.STYLE_ATTR,
181: style, span);
182: span |= HtmlRendererUtils
183: .renderHTMLAttributeWithOptionalStartElement(writer,
184: message, HTML.SPAN_ELEM, HTML.STYLE_CLASS_ATTR,
185: styleClass, span);
186:
187: boolean showSummary = isShowSummary(message)
188: && (summary != null);
189: boolean showDetail = isShowDetail(message) && (detail != null);
190:
191: if (showSummary && !(title == null && tooltip)) {
192: writer.writeText(summary, null);
193: if (showDetail) {
194: writer.writeText(" ", null);
195: }
196: }
197:
198: if (showDetail) {
199: writer.writeText(detail, null);
200: }
201:
202: if (span) {
203: writer.endElement(HTML.SPAN_ELEM);
204: }
205: }
206:
207: public static String[] getStyleAndStyleClass(UIComponent message,
208: FacesMessage.Severity severity) {
209: String style = null;
210: String styleClass = null;
211: if (message instanceof ValidationHtmlMessage) {
212: if (severity == FacesMessage.SEVERITY_INFO) {
213: style = ((ValidationHtmlMessage) message)
214: .getInfoStyle();
215: styleClass = ((ValidationHtmlMessage) message)
216: .getInfoClass();
217: } else if (severity == FacesMessage.SEVERITY_WARN) {
218: style = ((ValidationHtmlMessage) message)
219: .getWarnStyle();
220: styleClass = ((ValidationHtmlMessage) message)
221: .getWarnClass();
222: } else if (severity == FacesMessage.SEVERITY_ERROR) {
223: style = ((ValidationHtmlMessage) message)
224: .getErrorStyle();
225: styleClass = ((ValidationHtmlMessage) message)
226: .getErrorClass();
227: } else if (severity == FacesMessage.SEVERITY_FATAL) {
228: style = ((ValidationHtmlMessage) message)
229: .getFatalStyle();
230: styleClass = ((ValidationHtmlMessage) message)
231: .getFatalClass();
232: }
233:
234: if (style == null) {
235: style = ((ValidationHtmlMessage) message).getStyle();
236: }
237:
238: if (styleClass == null) {
239: styleClass = ((ValidationHtmlMessage) message)
240: .getStyleClass();
241: }
242: } else {
243: Map attr = message.getAttributes();
244: if (severity == FacesMessage.SEVERITY_INFO) {
245: style = (String) attr.get(JSFAttr.INFO_STYLE_ATTR);
246: styleClass = (String) attr.get(JSFAttr.INFO_CLASS_ATTR);
247: } else if (severity == FacesMessage.SEVERITY_WARN) {
248: style = (String) attr.get(JSFAttr.WARN_STYLE_ATTR);
249: styleClass = (String) attr.get(JSFAttr.WARN_CLASS_ATTR);
250: } else if (severity == FacesMessage.SEVERITY_ERROR) {
251: style = (String) attr.get(JSFAttr.ERROR_STYLE_ATTR);
252: styleClass = (String) attr
253: .get(JSFAttr.ERROR_CLASS_ATTR);
254: } else if (severity == FacesMessage.SEVERITY_FATAL) {
255: style = (String) attr.get(JSFAttr.FATAL_STYLE_ATTR);
256: styleClass = (String) attr
257: .get(JSFAttr.FATAL_CLASS_ATTR);
258: }
259:
260: if (style == null) {
261: style = (String) attr.get(JSFAttr.STYLE_CLASS_ATTR);
262: }
263:
264: if (styleClass == null) {
265: styleClass = (String) attr
266: .get(JSFAttr.STYLE_CLASS_ATTR);
267: }
268: }
269:
270: return new String[] { style, styleClass };
271: }
272:
273: protected String getFor(UIComponent component) {
274: if (component instanceof UIMessage) {
275: return ((UIMessage) component).getFor();
276: } else {
277: return (String) component.getAttributes().get(
278: JSFAttr.FOR_ATTR);
279: }
280: }
281:
282: protected String getTitle(UIComponent component) {
283: if (component instanceof ValidationHtmlMessage) {
284: return ((ValidationHtmlMessage) component).getTitle();
285: } else {
286: return (String) component.getAttributes().get(
287: JSFAttr.TITLE_ATTR);
288: }
289: }
290:
291: protected boolean isTooltip(UIComponent component) {
292: if (component instanceof ValidationHtmlMessage) {
293: return ((ValidationHtmlMessage) component).isTooltip();
294: } else {
295: return JsfUtils.getBooleanAttribute(component,
296: JSFAttr.TOOLTIP_ATTR, false);
297: }
298: }
299:
300: protected boolean isShowSummary(UIComponent component) {
301: if (component instanceof UIMessage) {
302: return ((UIMessage) component).isShowSummary();
303: } else {
304: return JsfUtils.getBooleanAttribute(component,
305: JSFAttr.SHOW_SUMMARY_ATTR, false);
306: }
307: }
308:
309: protected boolean isShowDetail(UIComponent component) {
310: if (component instanceof UIMessage) {
311: return ((UIMessage) component).isShowDetail();
312: } else {
313: return JsfUtils.getBooleanAttribute(component,
314: JSFAttr.SHOW_DETAIL_ATTR, false);
315: }
316: }
317:
318: }
|