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 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import javax.el.ELException;
29 import javax.el.ValueExpression;
30 import javax.faces.FacesException;
31 import javax.faces.component.ActionSource;
32 import javax.faces.component.UIComponent;
33 import javax.faces.component.UIViewRoot;
34 import javax.faces.context.FacesContext;
35 import javax.faces.event.AbortProcessingException;
36 import javax.faces.event.ActionEvent;
37 import javax.faces.event.ActionListener;
38 import javax.faces.view.ActionSource2AttachedObjectHandler;
39 import javax.faces.view.AttachedObjectHandler;
40 import javax.faces.view.Location;
41 import javax.faces.view.facelets.ComponentHandler;
42 import javax.faces.view.facelets.FaceletContext;
43 import javax.faces.view.facelets.FaceletException;
44 import javax.faces.view.facelets.TagAttribute;
45 import javax.faces.view.facelets.TagConfig;
46 import javax.faces.view.facelets.TagException;
47 import javax.faces.view.facelets.TagHandler;
48 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
49 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
50 import org.apache.myfaces.shared.renderkit.JSFAttr;
51 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
52 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
53
54
55
56
57
58 @JSFFaceletTag(
59 name = "f:resetValues",
60 bodyContent = "empty")
61 public class ResetValuesActionListenerHandler extends TagHandler
62 implements ActionSource2AttachedObjectHandler
63 {
64
65
66
67 @JSFFaceletAttribute(name = "render", className = "javax.el.ValueExpression",
68 deferredValueType = "java.lang.Object")
69 private final TagAttribute _render;
70
71 private final Collection<String> _clientIds;
72
73 public ResetValuesActionListenerHandler(TagConfig config)
74 {
75 super(config);
76 _render = getRequiredAttribute("render");
77 if (_render.isLiteral())
78 {
79 String value = _render.getValue();
80 if (value == null)
81 {
82 _clientIds = Collections.emptyList();
83 }
84 else
85 {
86 String[] arrValue = value.split(" ");
87 _clientIds = Arrays.asList(arrValue);
88 }
89 }
90 else
91 {
92 _clientIds = null;
93 }
94 }
95
96
97
98
99
100
101 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
102 ELException
103 {
104
105 if (!ComponentHandler.isNew(parent))
106 {
107 return;
108 }
109 if (parent instanceof ActionSource)
110 {
111 applyAttachedObject(ctx.getFacesContext(), parent, false);
112 }
113 else if (UIComponent.isCompositeComponent(parent))
114 {
115 if (getAttribute(JSFAttr.FOR_ATTR) == null)
116 {
117 throw new TagException(tag, "is nested inside a composite component"
118 + " but does not have a for attribute.");
119 }
120 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
121 mctx.addAttachedObjectHandler(parent, this);
122 }
123 else
124 {
125 throw new TagException(this.tag,
126 "Parent is not composite component or of type ActionSource, type is: " + parent);
127 }
128 }
129
130 public void applyAttachedObject(FacesContext context, UIComponent parent)
131 {
132 applyAttachedObject(context, parent, true);
133 }
134
135 public void applyAttachedObject(FacesContext context, UIComponent parent, boolean checkForParentCC)
136 {
137 UIComponent topParentComponent = null;
138
139 FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(
140 FaceletContext.FACELET_CONTEXT_KEY);
141
142 if (checkForParentCC)
143 {
144 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(faceletContext);
145 UIComponent parentComponent = parent;
146 while (parentComponent != null)
147 {
148 if (UIComponent.isCompositeComponent(parentComponent))
149 {
150 List<AttachedObjectHandler> handlerList = mctx.getAttachedObjectHandlers(parentComponent);
151 if (handlerList != null && handlerList.contains(this))
152 {
153
154 topParentComponent = parentComponent;
155 }
156 }
157 parentComponent = parentComponent.getParent();
158 }
159 }
160
161 ActionSource as = (ActionSource) parent;
162 ActionListener listener = null;
163 if (_render.isLiteral())
164 {
165 listener = new LiteralResetValuesActionListener(_clientIds,
166 topParentComponent != null ?
167 (Location) topParentComponent.getAttributes().get(
168 CompositeComponentELUtils.LOCATION_KEY) : null);
169 }
170 else
171 {
172 listener = new ResetValuesActionListener(_render
173 .getValueExpression(faceletContext, Object.class) ,
174 topParentComponent != null ?
175 (Location) topParentComponent.getAttributes().get(
176 CompositeComponentELUtils.LOCATION_KEY) : null);
177 }
178 as.addActionListener(listener);
179 }
180
181
182
183
184 @JSFFaceletAttribute
185 public String getFor()
186 {
187 TagAttribute forAttribute = getAttribute("for");
188
189 if (forAttribute == null)
190 {
191 return null;
192 }
193 else
194 {
195 return forAttribute.getValue();
196 }
197 }
198
199 private final static class ResetValuesActionListener implements ActionListener, Serializable
200 {
201 private static final long serialVersionUID = -9200000013153262119L;
202
203 private ValueExpression renderExpression;
204
205 private Location topCompositeComponentReference;
206
207 private ResetValuesActionListener()
208 {
209 }
210
211 public ResetValuesActionListener(ValueExpression renderExpression, Location location)
212 {
213 this.renderExpression = renderExpression;
214 this.topCompositeComponentReference = location;
215 }
216
217 public void processAction(ActionEvent event) throws AbortProcessingException
218 {
219 FacesContext faces = FacesContext.getCurrentInstance();
220 if (faces == null)
221 {
222 return;
223 }
224 UIViewRoot root = faces.getViewRoot();
225 if (root == null)
226 {
227 return;
228 }
229 Object value = renderExpression.getValue(faces.getELContext());
230 Collection<String> clientIds = null;
231 if (value == null)
232 {
233 value = Collections.emptyList();
234 }
235 if (value instanceof Collection)
236 {
237 clientIds = (Collection) value;
238 }
239 else if (value instanceof String)
240 {
241 String[] arrValue = ((String)value).split(" ");
242 clientIds = Arrays.asList(arrValue);
243 }
244 else
245 {
246 throw new IllegalArgumentException("Type " + value.getClass()
247 + " not supported for attribute render");
248 }
249
250
251 UIComponent contextComponent = null;
252 if (topCompositeComponentReference != null)
253 {
254 contextComponent = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(
255 faces, event.getComponent(), topCompositeComponentReference);
256 if (contextComponent == null)
257 {
258 contextComponent = event.getComponent();
259 }
260 else
261 {
262 contextComponent = contextComponent.getParent();
263 }
264 }
265 else
266 {
267 contextComponent = event.getComponent();
268 }
269 List<String> list = new ArrayList<String>();
270 for (String id : clientIds)
271 {
272 list.add(getComponentId(faces, contextComponent, id));
273 }
274
275
276 root.resetValues(faces, list);
277 }
278 }
279
280 private final static class LiteralResetValuesActionListener implements ActionListener, Serializable
281 {
282 private static final long serialVersionUID = -9200000013153262119L;
283
284 private Collection<String> clientIds;
285
286 private Location topCompositeComponentReference;
287
288 private LiteralResetValuesActionListener()
289 {
290 }
291
292 public LiteralResetValuesActionListener(Collection<String> clientIds, Location location)
293 {
294 this.clientIds = clientIds;
295 this.topCompositeComponentReference = location;
296 }
297
298 public void processAction(ActionEvent event) throws AbortProcessingException
299 {
300 FacesContext faces = FacesContext.getCurrentInstance();
301 if (faces == null)
302 {
303 return;
304 }
305 UIViewRoot root = faces.getViewRoot();
306 if (root == null)
307 {
308 return;
309 }
310
311
312 UIComponent contextComponent = null;
313 if (topCompositeComponentReference != null)
314 {
315 contextComponent = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(
316 faces, event.getComponent(), topCompositeComponentReference);
317 if (contextComponent == null)
318 {
319 contextComponent = event.getComponent();
320 }
321 else
322 {
323 contextComponent = contextComponent.getParent();
324 }
325 }
326 else
327 {
328 contextComponent = event.getComponent();
329 }
330 List<String> list = new ArrayList<String>();
331 for (String id : clientIds)
332 {
333 list.add(getComponentId(faces, contextComponent, id));
334 }
335
336 root.resetValues(faces, list);
337 }
338 }
339
340 private static final String getComponentId(FacesContext facesContext,
341 UIComponent contextComponent, String id)
342 {
343 UIComponent target = contextComponent.findComponent(id);
344 if (target == null)
345 {
346 target = contextComponent.findComponent(
347 facesContext.getNamingContainerSeparatorChar() + id);
348 }
349 if (target != null)
350 {
351 return target.getClientId(facesContext);
352 }
353 return id;
354 }
355 }