001: /*
002: * $Header: /cvsroot/jvalidate/jvalidate-framework/jvalidate-jsf/src/main/java/nl/knowlogy/validation/jsf/component/field/FieldMessageComponent.java,v 1.5 2007/06/01 09:06:58 roberthofstra Exp $
003: * $Revision: 1.5 $
004: * $Date: 2007/06/01 09:06:58 $
005: *
006: *
007: * Created on Oct 6, 2004
008: *
009: * All right reserved(c) 2004, Knowlogy
010: *
011: * Copyright 2004 - 2005 Knowlogy, the Netherlands. All rights reserved.
012: * All Knowlogy brand and product names are trademarks or registered trademarks
013: * of Knowlogy in the Netherlands and other countries.
014: *
015: * No part of this publication may be reproduced, transmitted, stored in a retrieval system,
016: * or translated into any human or computer language, in any form, or by any means, electronic,
017: * mechanical, magnetic, optical, chemical, manual, or otherwise,
018: * without the prior written permission of the copyright owner, Knowlogy.
019: *
020: */
021: package nl.knowlogy.validation.jsf.component.field;
022:
023: import java.io.IOException;
024: import java.util.ArrayList;
025: import java.util.Collections;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import javax.faces.application.FacesMessage;
030: import javax.faces.component.UIComponent;
031: import javax.faces.component.UIComponentBase;
032: import javax.faces.context.FacesContext;
033: import javax.faces.el.ValueBinding;
034:
035: import nl.knowlogy.validation.Messages;
036: import nl.knowlogy.validation.jsf.MessagesUtil;
037: import nl.knowlogy.validation.jsf.utils.JsfUtils;
038:
039: import org.apache.commons.lang.StringUtils;
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042:
043: /**
044: *
045: *
046: * @author <a href="mailto:arjen.van.staalduinen@knowlogy.nl">Arjen van Staalduinen, Knowlogy</a>
047: *
048: */
049: public class FieldMessageComponent extends UIComponentBase {
050:
051: public static final String STYLE_EXCLAMATION = "exclamation";
052:
053: private Boolean objectLevelOnly = Boolean.FALSE;
054: private String forComponent;
055: private String fieldName;
056: List errorMessages;
057: List errorList;
058: private String messageStyle;
059: private String objectExpression;
060: private boolean initializedObjectExpression = false;
061:
062: //private boolean hasDeterminedErrors;
063:
064: private static final Log log = LogFactory
065: .getLog(FieldMessageComponent.class);
066:
067: /**
068: * @return Returns the objectLevelOnly.
069: */
070: public Boolean getObjectLevelOnly() {
071: return objectLevelOnly;
072: }
073:
074: /**
075: * @param objectLevelOnly The objectLevelOnly to set.
076: */
077: public void setObjectLevelOnly(Boolean objectLevelOnly) {
078: this .objectLevelOnly = objectLevelOnly;
079: }
080:
081: /**
082: * @return Returns the forObject.
083: */
084: public Object getForObject(FacesContext context) {
085: ValueBinding valueBinding = getValueBinding("forObject");
086: if (valueBinding == null) {
087: String objectExpresion = getObjectExpression(context);
088: if (objectExpresion != null) {
089: return JsfUtils.getBindedObject(context,
090: objectExpresion);
091: }
092: return null;
093: }
094: return valueBinding.getValue(context);
095: }
096:
097: private String getObjectExpression(FacesContext context) {
098: if (!initializedObjectExpression) {
099: if (forComponent != null) {
100: UIComponent forUIComponent = getForComponent(context,
101: forComponent, this );
102: objectExpression = JsfUtils
103: .getObjectPart(forUIComponent);
104: fieldName = JsfUtils
105: .getPropertyNamePart(forUIComponent);
106: }
107: initializedObjectExpression = true;
108: }
109: return objectExpression;
110: }
111:
112: public FieldMessageComponent() {
113: }
114:
115: public String getRendererType() {
116: if (StringUtils.isBlank(messageStyle)
117: || STYLE_EXCLAMATION.equals(messageStyle)) {
118: return "nl.knowlogy.validation.FieldMessage.exclamation";
119: } else {
120: return "nl.knowlogy.validation.FieldMessage.flat";
121: }
122: }
123:
124: public String getFamily() {
125: return "nl.knowlogy.validation.FieldMessage";
126: }
127:
128: public Object saveState(FacesContext context) {
129: Object values[] = new Object[6];
130: values[0] = super .saveState(context);
131: values[1] = forComponent;
132: values[2] = fieldName;
133: values[3] = messageStyle;
134: values[4] = objectExpression;
135: values[5] = objectLevelOnly;
136:
137: return ((Object) (values));
138: }
139:
140: public void restoreState(FacesContext context, Object state) {
141: Object values[] = (Object[]) state;
142: super .restoreState(context, values[0]);
143: forComponent = (String) values[1];
144: fieldName = (String) values[2];
145: messageStyle = (String) values[3];
146: objectExpression = (String) values[4];
147: objectLevelOnly = (Boolean) values[5];
148: }
149:
150: public void encodeBegin(FacesContext context) throws IOException {
151:
152: if (context == null) {
153: throw new NullPointerException();
154: }
155: if (!isRendered()) {
156: return;
157: }
158:
159: //if (!hasDeterminedErrors) {
160: determineErrors(context);
161: //}
162:
163: String rendererType = getRendererType();
164: if (rendererType != null) {
165: getRenderer(context).encodeBegin(context, this );
166: }
167:
168: }
169:
170: protected Iterator getMessageIter(FacesContext context,
171: String forComponent, UIComponent component) {
172: Iterator messageIter = null;
173: // Attempt to use the "for" attribute to locate
174: // messages. Three possible scenarios here:
175: // 1. valid "for" attribute - messages returned
176: // for valid component identified by "for" expression.
177: // 2. zero length "for" expression - global errors
178: // not associated with any component returned
179: // 3. no "for" expression - all messages returned.
180: if (null != forComponent) {
181: if (forComponent.length() == 0) {
182: messageIter = context.getMessages(null);
183: } else {
184: UIComponent result = getForComponent(context,
185: forComponent, component);
186: if (result == null) {
187: messageIter = Collections.EMPTY_LIST.iterator();
188: } else {
189: messageIter = context.getMessages(result
190: .getClientId(context));
191: }
192: }
193: } else {
194: messageIter = Collections.EMPTY_LIST.iterator();
195: }
196: return messageIter;
197: }
198:
199: /**
200: * Locates the component identified by <code>forComponent</code>
201: *
202: * @param forComponent -
203: * the component to search for
204: * @param component -
205: * the starting point in which to begin the search
206: * @return the component with the the <code>id</code that matches
207: * <code>forComponent</code> otheriwse null if no match is found.
208: */
209: protected UIComponent getForComponent(FacesContext context,
210: String forComponent, UIComponent component) {
211: UIComponent result = JsfUtils.getForComponent(context,
212: forComponent, this );
213: //
214: // if (null == forComponent || forComponent.length() == 0) {
215: // return null;
216: // }
217: //
218: // UIComponent result = null;
219: // UIComponent currentParent = component;
220: // try {
221: // // Check the naming container of the current
222: // // component for component identified by
223: // // 'forComponent'
224: // while (currentParent != null) {
225: // // If the current component is a NamingContainer,
226: // // see if it contains what we're looking for.
227: // result = currentParent.findComponent(forComponent);
228: // if (result != null)
229: // break;
230: // // if not, start checking further up in the view
231: // currentParent = currentParent.getParent();
232: // }
233: //
234: // // no hit from above, scan for a NamingContainer
235: // // that contains the component we're looking for from the root.
236: // if (result == null) {
237: // result = findUIComponentBelow(context.getViewRoot(),
238: // forComponent);
239: // }
240: // } catch (Throwable t) {
241: // //Object[] params = { forComponent };
242: // throw new RuntimeException(""
243: // //Util.getExceptionMessageString(Util.COMPONENT_NOT_FOUND_ERROR_MESSAGE_ID, params)
244: // );
245: // }
246: // log a message if we were unable to find the specified
247: // component (probably a misconfigured 'for' attribute
248: if (result == null) {
249: if (log.isWarnEnabled()) {
250: log.warn("COMPONENT_NOT_FOUND_IN_VIEW_WARNING_ID"
251: //Util.getExceptionMessageString( Util.COMPONENT_NOT_FOUND_IN_VIEW_WARNING_ID,
252: //new Object[] { forComponent })
253: );
254: }
255: }
256: return result;
257: }
258:
259: public String getForComponent() {
260: return forComponent;
261: }
262:
263: public void setForComponent(String componentId) {
264: this .forComponent = componentId;
265: }
266:
267: public String getFieldName() {
268: return fieldName;
269: }
270:
271: public void setFieldName(String propertyName) {
272: this .fieldName = propertyName;
273: }
274:
275: public List getErrorMessages() {
276: return errorMessages;
277: }
278:
279: public void setErrorMessages(List errorMessages) {
280: this .errorMessages = errorMessages;
281: }
282:
283: public List getErrorList() {
284: return errorList;
285: }
286:
287: public void setErrorList(List errorList) {
288: this .errorList = errorList;
289: }
290:
291: /* (non-Javadoc)
292: * @see javax.faces.component.UIComponent#processDecodes(javax.faces.context.FacesContext)
293: */
294: public void processDecodes(FacesContext context) {
295: //hasDeterminedErrors = false;
296: super .processDecodes(context);
297: }
298:
299: /* (non-Javadoc)
300: * @see nl.iza.common.jsf.component.field.ValidationDisplayingComponent#determineErrors(javax.faces.context.FacesContext)
301: */
302: public void determineErrors(FacesContext context) {
303: errorMessages = new ArrayList();
304: errorList = new ArrayList();
305: Iterator iter = getMessageIter(context, forComponent, this );
306: while (iter.hasNext()) {
307: FacesMessage element = (FacesMessage) iter.next();
308: errorMessages.add(element.getDetail());
309:
310: }
311:
312: ValueBinding valueBinding = context.getApplication()
313: .createValueBinding(MessagesUtil.VALUE_BINDING_NAME);
314:
315: Object object = valueBinding.getValue(context);
316:
317: if (object != null && object instanceof Messages) {
318:
319: Messages messages = (Messages) object;
320:
321: List propertyErrors = null;
322:
323: Object forObject = getForObject(context);
324: if (forObject != null) {
325: if (log.isDebugEnabled()) {
326: log.debug("Retrieved object " + forObject
327: + " fieldName " + fieldName
328: + " objectLevelOnly " + objectLevelOnly);
329: }
330: if (fieldName != null) {
331: propertyErrors = messages.getMessages(forObject,
332: fieldName);
333: } else {
334: propertyErrors = messages.getMessages(forObject,
335: objectLevelOnly.booleanValue());
336: }
337: }
338:
339: if (propertyErrors != null) {
340: for (Iterator iterator = propertyErrors.iterator(); iterator
341: .hasNext();) {
342: errorList.add(iterator.next());
343:
344: }
345: }
346: }
347: //hasDeterminedErrors = true;
348: }
349:
350: public String getMessageStyle() {
351: return messageStyle;
352: }
353:
354: public void setMessageStyle(String messageStyle) {
355: this.messageStyle = messageStyle;
356: }
357: }
|