1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.tag.jsf.core;
20
21 import java.io.IOException;
22 import java.io.Serializable;
23
24 import javax.el.ELException;
25 import javax.el.ValueExpression;
26 import javax.faces.FacesException;
27 import javax.faces.component.EditableValueHolder;
28 import javax.faces.component.UIComponent;
29 import javax.faces.context.FacesContext;
30 import javax.faces.event.AbortProcessingException;
31 import javax.faces.event.ValueChangeEvent;
32 import javax.faces.event.ValueChangeListener;
33 import javax.faces.view.EditableValueHolderAttachedObjectHandler;
34 import javax.faces.view.facelets.ComponentHandler;
35 import javax.faces.view.facelets.FaceletContext;
36 import javax.faces.view.facelets.FaceletException;
37 import javax.faces.view.facelets.TagAttribute;
38 import javax.faces.view.facelets.TagAttributeException;
39 import javax.faces.view.facelets.TagConfig;
40 import javax.faces.view.facelets.TagException;
41 import javax.faces.view.facelets.TagHandler;
42
43 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
44 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
45 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
46 import org.apache.myfaces.view.facelets.util.ReflectionUtil;
47
48
49
50
51
52
53
54
55 @JSFFaceletTag(
56 name = "f:valueChangeListener",
57 bodyContent = "empty",
58 tagClass="org.apache.myfaces.taglib.core.ValueChangeListenerTag")
59 public final class ValueChangeListenerHandler extends TagHandler
60 implements EditableValueHolderAttachedObjectHandler
61 {
62
63 private static class LazyValueChangeListener implements ValueChangeListener, Serializable
64 {
65
66 private static final long serialVersionUID = 7613811124326963180L;
67
68 private final String type;
69
70 private final ValueExpression binding;
71
72 public LazyValueChangeListener(String type, ValueExpression binding)
73 {
74 this.type = type;
75 this.binding = binding;
76 }
77
78 public void processValueChange(ValueChangeEvent event) throws AbortProcessingException
79 {
80 ValueChangeListener instance = null;
81 FacesContext faces = FacesContext.getCurrentInstance();
82 if (faces == null)
83 {
84 return;
85 }
86 if (this.binding != null)
87 {
88 instance = (ValueChangeListener) binding.getValue(faces.getELContext());
89 }
90 if (instance == null && this.type != null)
91 {
92 try
93 {
94 instance = (ValueChangeListener) ReflectionUtil.forName(this.type).newInstance();
95 }
96 catch (Exception e)
97 {
98 throw new AbortProcessingException("Couldn't Lazily instantiate ValueChangeListener", e);
99 }
100 if (this.binding != null)
101 {
102 binding.setValue(faces.getELContext(), instance);
103 }
104 }
105 if (instance != null)
106 {
107 instance.processValueChange(event);
108 }
109 }
110 }
111
112 private final TagAttribute binding;
113
114 private final String listenerType;
115
116 public ValueChangeListenerHandler(TagConfig config)
117 {
118 super(config);
119 this.binding = this.getAttribute("binding");
120 TagAttribute type = this.getAttribute("type");
121 if (type != null)
122 {
123 if (!type.isLiteral())
124 {
125 throw new TagAttributeException(type, "Must be a literal class name of type ValueChangeListener");
126 }
127 else
128 {
129
130 try
131 {
132 ReflectionUtil.forName(type.getValue());
133 }
134 catch (ClassNotFoundException e)
135 {
136 throw new TagAttributeException(type, "Couldn't qualify ValueChangeListener", e);
137 }
138 }
139 this.listenerType = type.getValue();
140 }
141 else
142 {
143 this.listenerType = null;
144 }
145 }
146
147
148
149
150
151
152
153 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
154 ELException
155 {
156 if (!ComponentHandler.isNew(parent))
157 {
158 return;
159 }
160 if (parent instanceof EditableValueHolder)
161 {
162 applyAttachedObject(ctx.getFacesContext(), parent);
163 }
164 else if (UIComponent.isCompositeComponent(parent))
165 {
166 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
167 mctx.addAttachedObjectHandler(parent, this);
168 }
169 else
170 {
171 throw new TagException(this.tag,
172 "Parent not composite component or an instance of EditableValueHolder: " + parent);
173 }
174 }
175
176 public void applyAttachedObject(FacesContext context, UIComponent parent)
177 {
178
179 FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(
180 FaceletContext.FACELET_CONTEXT_KEY);
181
182 EditableValueHolder evh = (EditableValueHolder) parent;
183 ValueExpression b = null;
184 if (this.binding != null)
185 {
186 b = this.binding.getValueExpression(faceletContext, ValueChangeListener.class);
187 }
188 ValueChangeListener listener = new LazyValueChangeListener(this.listenerType, b);
189 evh.addValueChangeListener(listener);
190 }
191
192
193
194
195 @JSFFaceletAttribute
196 public String getFor()
197 {
198 TagAttribute forAttribute = getAttribute("for");
199
200 if (forAttribute == null)
201 {
202 return null;
203 }
204 else
205 {
206 return forAttribute.getValue();
207 }
208 }
209
210 }