Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ComponentHandler |
|
| 3.0;3 |
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.view.facelets.tag.jsf; | |
20 | ||
21 | import java.io.IOException; | |
22 | import java.util.logging.Level; | |
23 | import java.util.logging.Logger; | |
24 | ||
25 | import javax.el.ELException; | |
26 | import javax.el.ValueExpression; | |
27 | import javax.faces.FacesException; | |
28 | import javax.faces.application.Application; | |
29 | import javax.faces.component.ActionSource; | |
30 | import javax.faces.component.EditableValueHolder; | |
31 | import javax.faces.component.UIComponent; | |
32 | import javax.faces.component.UIViewRoot; | |
33 | import javax.faces.component.ValueHolder; | |
34 | import javax.faces.context.FacesContext; | |
35 | import javax.faces.view.facelets.ComponentConfig; | |
36 | import javax.faces.view.facelets.FaceletContext; | |
37 | import javax.faces.view.facelets.MetaRuleset; | |
38 | import javax.faces.view.facelets.MetaTagHandler; | |
39 | import javax.faces.view.facelets.TagAttribute; | |
40 | import javax.faces.view.facelets.TagException; | |
41 | ||
42 | import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl; | |
43 | ||
44 | /** | |
45 | * Implementation of the tag logic used in the JSF specification. This is your golden hammer for wiring UIComponents to | |
46 | * Facelets. | |
47 | * | |
48 | * @deprecated Use javax.faces.view.facelets.ComponentHandler instead | |
49 | * @author Jacob Hookom | |
50 | * @version $Id$ | |
51 | */ | |
52 | @Deprecated | |
53 | public class ComponentHandler extends MetaTagHandler | |
54 | { | |
55 | ||
56 | //private final static Logger log = Logger.getLogger("facelets.tag.component"); | |
57 | 0 | private final static Logger log = Logger.getLogger(ComponentHandler.class.getName()); |
58 | ||
59 | private final TagAttribute binding; | |
60 | ||
61 | private final String componentType; | |
62 | ||
63 | private final TagAttribute id; | |
64 | ||
65 | private final String rendererType; | |
66 | ||
67 | public ComponentHandler(ComponentConfig config) | |
68 | { | |
69 | 0 | super(config); |
70 | 0 | this.componentType = config.getComponentType(); |
71 | 0 | this.rendererType = config.getRendererType(); |
72 | 0 | this.id = this.getAttribute("id"); |
73 | 0 | this.binding = this.getAttribute("binding"); |
74 | 0 | } |
75 | ||
76 | /** | |
77 | * Method handles UIComponent tree creation in accordance with the JSF 1.2 spec. | |
78 | * <ol> | |
79 | * <li>First determines this UIComponent's id by calling {@link #getId(FaceletContext) getId(FaceletContext)}.</li> | |
80 | * <li>Search the parent for an existing UIComponent of the id we just grabbed</li> | |
81 | * <li>If found, {@link #markForDeletion(UIComponent) mark} its children for deletion.</li> | |
82 | * <li>If <i>not</i> found, call {@link #createComponent(FaceletContext) createComponent}. | |
83 | * <ol> | |
84 | * <li>Only here do we apply {@link ObjectHandler#setAttributes(FaceletContext, Object) attributes}</li> | |
85 | * <li>Set the UIComponent's id</li> | |
86 | * <li>Set the RendererType of this instance</li> | |
87 | * </ol> | |
88 | * </li> | |
89 | * <li>Now apply the nextHandler, passing the UIComponent we've created/found.</li> | |
90 | * <li>Now add the UIComponent to the passed parent</li> | |
91 | * <li>Lastly, if the UIComponent already existed (found), then {@link #finalizeForDeletion(UIComponent) finalize} | |
92 | * for deletion.</li> | |
93 | * </ol> | |
94 | * | |
95 | * @see javax.faces.view.facelets.FaceletHandler#apply(javax.faces.view.facelets.FaceletContext, javax.faces.component.UIComponent) | |
96 | * | |
97 | * @throws TagException | |
98 | * if the UIComponent parent is null | |
99 | */ | |
100 | public final void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, ELException | |
101 | { | |
102 | // make sure our parent is not null | |
103 | 0 | if (parent == null) |
104 | { | |
105 | 0 | throw new TagException(this.tag, "Parent UIComponent was null"); |
106 | } | |
107 | ||
108 | // possible facet scoped | |
109 | 0 | String facetName = this.getFacetName(ctx, parent); |
110 | ||
111 | // our id | |
112 | 0 | String id = ctx.generateUniqueId(this.tagId); |
113 | ||
114 | // grab our component | |
115 | 0 | UIComponent c = ComponentSupport.findChildByTagId(parent, id); |
116 | 0 | boolean componentFound = false; |
117 | 0 | if (c != null) |
118 | { | |
119 | 0 | componentFound = true; |
120 | // mark all children for cleaning | |
121 | 0 | if (log.isLoggable(Level.FINE)) |
122 | { | |
123 | 0 | log.fine(this.tag + " Component[" + id + "] Found, marking children for cleanup"); |
124 | } | |
125 | 0 | ComponentSupport.markForDeletion(c); |
126 | } | |
127 | else | |
128 | { | |
129 | 0 | c = this.createComponent(ctx); |
130 | 0 | if (log.isLoggable(Level.FINE)) |
131 | { | |
132 | 0 | log.fine(this.tag + " Component[" + id + "] Created: " + c.getClass().getName()); |
133 | } | |
134 | 0 | this.setAttributes(ctx, c); |
135 | ||
136 | // mark it owned by a facelet instance | |
137 | 0 | c.getAttributes().put(ComponentSupport.MARK_CREATED, id); |
138 | ||
139 | // assign our unique id | |
140 | 0 | if (this.id != null) |
141 | { | |
142 | 0 | c.setId(this.id.getValue(ctx)); |
143 | } | |
144 | else | |
145 | { | |
146 | 0 | UIViewRoot root = ComponentSupport.getViewRoot(ctx, parent); |
147 | 0 | if (root != null) |
148 | { | |
149 | 0 | String uid = root.createUniqueId(); |
150 | 0 | c.setId(uid); |
151 | } | |
152 | } | |
153 | ||
154 | 0 | if (this.rendererType != null) |
155 | { | |
156 | 0 | c.setRendererType(this.rendererType); |
157 | } | |
158 | ||
159 | // hook method | |
160 | 0 | this.onComponentCreated(ctx, c, parent); |
161 | } | |
162 | ||
163 | // first allow c to get populated | |
164 | 0 | this.applyNextHandler(ctx, c); |
165 | ||
166 | // finish cleaning up orphaned children | |
167 | 0 | if (componentFound) |
168 | { | |
169 | 0 | ComponentSupport.finalizeForDeletion(c); |
170 | ||
171 | 0 | if (facetName == null) |
172 | { | |
173 | 0 | parent.getChildren().remove(c); |
174 | } | |
175 | } | |
176 | ||
177 | 0 | this.onComponentPopulated(ctx, c, parent); |
178 | ||
179 | // add to the tree afterwards | |
180 | // this allows children to determine if it's | |
181 | // been part of the tree or not yet | |
182 | 0 | if (facetName == null) |
183 | { | |
184 | 0 | parent.getChildren().add(c); |
185 | } | |
186 | else | |
187 | { | |
188 | 0 | parent.getFacets().put(facetName, c); |
189 | } | |
190 | 0 | } |
191 | ||
192 | /** | |
193 | * Return the Facet name we are scoped in, otherwise null | |
194 | * | |
195 | * @param ctx | |
196 | * @return | |
197 | */ | |
198 | protected final String getFacetName(FaceletContext ctx, UIComponent parent) | |
199 | { | |
200 | // TODO: REFACTOR - "facelets.FACET_NAME" should be a constant somewhere, used to be in FacetHandler | |
201 | // from real Facelets | |
202 | 0 | return (String) parent.getAttributes().get("facelets.FACET_NAME"); |
203 | } | |
204 | ||
205 | /** | |
206 | * If the binding attribute was specified, use that in conjuction with our componentType String variable to call | |
207 | * createComponent on the Application, otherwise just pass the componentType String. <p /> If the binding was used, | |
208 | * then set the ValueExpression "binding" on the created UIComponent. | |
209 | * | |
210 | * @see Application#createComponent(javax.faces.el.ValueBinding, javax.faces.context.FacesContext, java.lang.String) | |
211 | * @see Application#createComponent(java.lang.String) | |
212 | * @param ctx | |
213 | * FaceletContext to use in creating a component | |
214 | * @return | |
215 | */ | |
216 | protected UIComponent createComponent(FaceletContext ctx) | |
217 | { | |
218 | 0 | UIComponent c = null; |
219 | 0 | FacesContext faces = ctx.getFacesContext(); |
220 | 0 | Application app = faces.getApplication(); |
221 | 0 | if (this.binding != null) |
222 | { | |
223 | 0 | ValueExpression ve = this.binding.getValueExpression(ctx, Object.class); |
224 | ||
225 | 0 | c = app.createComponent(ve, faces, this.componentType); |
226 | 0 | if (c != null) |
227 | { | |
228 | 0 | c.setValueExpression("binding", ve); |
229 | } | |
230 | 0 | } |
231 | else | |
232 | { | |
233 | 0 | c = app.createComponent(this.componentType); |
234 | } | |
235 | 0 | return c; |
236 | } | |
237 | ||
238 | /** | |
239 | * If the id TagAttribute was specified, get it's value, otherwise generate a unique id from our tagId. | |
240 | * | |
241 | * @see TagAttribute#getValue(FaceletContext) | |
242 | * @param ctx | |
243 | * FaceletContext to use | |
244 | * @return what should be a unique Id | |
245 | */ | |
246 | protected String getId(FaceletContext ctx) | |
247 | { | |
248 | 0 | if (this.id != null) |
249 | { | |
250 | 0 | return this.id.getValue(ctx); |
251 | } | |
252 | 0 | return ctx.generateUniqueId(this.tagId); |
253 | } | |
254 | ||
255 | @Override | |
256 | protected MetaRuleset createMetaRuleset(Class type) | |
257 | { | |
258 | /*MetaRuleset m = super.createMetaRuleset(type); | |
259 | ||
260 | // ignore standard component attributes | |
261 | m.ignore("binding").ignore("id"); | |
262 | ||
263 | // add auto wiring for attributes | |
264 | m.addRule(ComponentRule.Instance); | |
265 | ||
266 | // if it's an ActionSource | |
267 | if (ActionSource.class.isAssignableFrom(type)) | |
268 | { | |
269 | m.addRule(ActionSourceRule.Instance); | |
270 | } | |
271 | ||
272 | // if it's a ValueHolder | |
273 | if (ValueHolder.class.isAssignableFrom(type)) | |
274 | { | |
275 | m.addRule(ValueHolderRule.Instance); | |
276 | ||
277 | // if it's an EditableValueHolder | |
278 | if (EditableValueHolder.class.isAssignableFrom(type)) | |
279 | { | |
280 | m.ignore("submittedValue"); | |
281 | m.ignore("valid"); | |
282 | m.addRule(EditableValueHolderRule.Instance); | |
283 | } | |
284 | } | |
285 | ||
286 | return m;*/ | |
287 | ||
288 | // FIXME: Implement correctly | |
289 | // temporally restore code | |
290 | 0 | MetaRuleset m = new MetaRulesetImpl(this.tag, type); |
291 | // ignore standard component attributes | |
292 | 0 | m.ignore("binding").ignore("id"); |
293 | ||
294 | // add auto wiring for attributes | |
295 | 0 | m.addRule(ComponentRule.INSTANCE); |
296 | ||
297 | // if it's an ActionSource | |
298 | 0 | if (ActionSource.class.isAssignableFrom(type)) |
299 | { | |
300 | 0 | m.addRule(ActionSourceRule.INSTANCE); |
301 | } | |
302 | ||
303 | // if it's a ValueHolder | |
304 | 0 | if (ValueHolder.class.isAssignableFrom(type)) |
305 | { | |
306 | 0 | m.addRule(ValueHolderRule.INSTANCE); |
307 | ||
308 | // if it's an EditableValueHolder | |
309 | 0 | if (EditableValueHolder.class.isAssignableFrom(type)) |
310 | { | |
311 | 0 | m.ignore("submittedValue"); |
312 | 0 | m.ignore("valid"); |
313 | 0 | m.addRule(EditableValueHolderRule.INSTANCE); |
314 | } | |
315 | } | |
316 | ||
317 | 0 | return m; |
318 | } | |
319 | ||
320 | /** | |
321 | * A hook method for allowing developers to do additional processing once Facelets creates the component. The | |
322 | * 'setAttributes' method is still perferred, but this method will provide the parent UIComponent before it's been | |
323 | * added to the tree and before any children have been added to the newly created UIComponent. | |
324 | * | |
325 | * @param ctx | |
326 | * @param c | |
327 | * @param parent | |
328 | */ | |
329 | protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent) | |
330 | { | |
331 | // do nothing | |
332 | 0 | } |
333 | ||
334 | protected void onComponentPopulated(FaceletContext ctx, UIComponent c, UIComponent parent) | |
335 | { | |
336 | // do nothing | |
337 | 0 | } |
338 | ||
339 | protected void applyNextHandler(FaceletContext ctx, UIComponent c) throws IOException, FacesException, ELException | |
340 | { | |
341 | // first allow c to get populated | |
342 | 0 | this.nextHandler.apply(ctx, c); |
343 | 0 | } |
344 | } |