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 org.apache.myfaces.custom.valueChangeNotifier;
20
21 import javax.faces.component.EditableValueHolder;
22 import javax.faces.component.UIComponent;
23 import javax.faces.webapp.UIComponentTag;
24 import javax.servlet.jsp.JspException;
25 import javax.servlet.jsp.tagext.Tag;
26 import javax.servlet.jsp.tagext.TagSupport;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 /**
32 * <p>ValueChangeNotifier</p>
33 *
34 * Like valueChangeListener, but will send valueChange events after the
35 * UPDATE_MODEL phase. <br />
36 * This simply means you CAN update your model values within such an event now.
37 * <br />
38 * <ul>
39 * <li>It wont be overwritten by the model update</li>
40 * <li>And wont trigger another valueChange if you update a value with an
41 * valueChangeListener attached</li>
42 * </ul>
43 *
44 * @JSFJspTag
45 * name="s:valueChangeNotifier"
46 * bodyContent="JSP"
47 *
48 * @author Mario Ivankovits <imario - at - apache.org> (latest modification by $Author$)
49 * @version $Revision$ $Date$
50 */
51 public class ValueChangeNotifierTag extends TagSupport
52 {
53 private String method = null;
54
55 private static Log log = LogFactory.getLog(ValueChangeNotifierTag.class);
56
57 public ValueChangeNotifierTag()
58 {
59 }
60
61 /**
62 * The bean.method name of your valueChange method<br />
63 * Currently only methods listeners are supported.<br />
64 * e.g. myBean.myListenerMethod
65 *
66 * @JSFJspAttribute
67 * required = "true"
68 */
69 public void setMethod(String method)
70 {
71 this.method = method;
72 }
73
74 public int doStartTag() throws JspException
75 {
76 if (method == null)
77 {
78 throw new JspException("name attribute not set");
79 }
80
81 // Find parent UIComponentTag
82 UIComponentTag componentTag = UIComponentTag
83 .getParentUIComponentTag(pageContext);
84 if (componentTag == null)
85 {
86 throw new JspException(
87 "ValueChangeListenerTag has no UIComponentTag ancestor");
88 }
89
90 if (componentTag.getCreated())
91 {
92 // Component was just created, so we add the Listener
93 UIComponent component = componentTag.getComponentInstance();
94 if (component instanceof EditableValueHolder)
95 {
96 setupClassListener(component);
97 }
98 else
99 {
100 throw new JspException("Component " + component.getId()
101 + " is no EditableValueHolder");
102 }
103 }
104
105 return Tag.SKIP_BODY;
106 }
107
108 protected void setupClassListener(UIComponent component)
109 {
110 if (UIComponentTag.isValueReference(method))
111 {
112 ((EditableValueHolder) component)
113 .addValueChangeListener(new ValueChangeCollector(method));
114 }
115 else
116 {
117 if(log.isErrorEnabled()){
118 log.error("Invalid expression " + method);
119 }
120 }
121 }
122 }