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
56 @JSFFaceletTag(
57 name = "f:valueChangeListener",
58 bodyContent = "empty",
59 tagClass="org.apache.myfaces.taglib.core.ValueChangeListenerTag")
60 public final class ValueChangeListenerHandler extends TagHandler
61 implements EditableValueHolderAttachedObjectHandler
62 {
63
64 private static class LazyValueChangeListener implements ValueChangeListener, Serializable
65 {
66
67 private static final long serialVersionUID = 7613811124326963180L;
68
69 private final String type;
70
71 private final ValueExpression binding;
72
73 public LazyValueChangeListener(String type, ValueExpression binding)
74 {
75 this.type = type;
76 this.binding = binding;
77 }
78
79 public void processValueChange(ValueChangeEvent event) throws AbortProcessingException
80 {
81 ValueChangeListener instance = null;
82 FacesContext faces = FacesContext.getCurrentInstance();
83 if (faces == null)
84 {
85 return;
86 }
87 if (this.binding != null)
88 {
89 instance = (ValueChangeListener) binding.getValue(faces.getELContext());
90 }
91 if (instance == null && this.type != null)
92 {
93 try
94 {
95 instance = (ValueChangeListener) ReflectionUtil.forName(this.type).newInstance();
96 }
97 catch (Exception e)
98 {
99 throw new AbortProcessingException("Couldn't Lazily instantiate ValueChangeListener", e);
100 }
101 if (this.binding != null)
102 {
103 binding.setValue(faces.getELContext(), instance);
104 }
105 }
106 if (instance != null)
107 {
108 instance.processValueChange(event);
109 }
110 }
111 }
112
113 private final TagAttribute binding;
114
115 private final String listenerType;
116
117 public ValueChangeListenerHandler(TagConfig config)
118 {
119 super(config);
120 this.binding = this.getAttribute("binding");
121 TagAttribute type = this.getAttribute("type");
122 if (type != null)
123 {
124 if (!type.isLiteral())
125 {
126 throw new TagAttributeException(type, "Must be a literal class name of type ValueChangeListener");
127 }
128 else
129 {
130
131 try
132 {
133 ReflectionUtil.forName(type.getValue());
134 }
135 catch (ClassNotFoundException e)
136 {
137 throw new TagAttributeException(type, "Couldn't qualify ValueChangeListener", e);
138 }
139 }
140 this.listenerType = type.getValue();
141 }
142 else
143 {
144 this.listenerType = null;
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 }