KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > facelets > tag > jsf > ComponentHandler


1 /**
2  * Licensed under the Common Development and Distribution License,
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://www.sun.com/cddl/
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */

14
15 package com.sun.facelets.tag.jsf;
16
17 import java.io.IOException JavaDoc;
18 import java.util.logging.Level JavaDoc;
19 import java.util.logging.Logger JavaDoc;
20
21 import javax.el.ELException;
22 import javax.el.MethodExpression;
23 import javax.el.ValueExpression;
24 import javax.faces.FacesException;
25 import javax.faces.application.Application;
26 import javax.faces.component.ActionSource;
27 import javax.faces.component.ActionSource2;
28 import javax.faces.component.EditableValueHolder;
29 import javax.faces.component.UIComponent;
30 import javax.faces.component.UIViewRoot;
31 import javax.faces.component.ValueHolder;
32 import javax.faces.context.FacesContext;
33 import javax.faces.convert.Converter;
34 import javax.faces.el.ValueBinding;
35 import javax.faces.event.ActionEvent;
36 import javax.faces.event.MethodExpressionActionListener;
37 import javax.faces.event.MethodExpressionValueChangeListener;
38 import javax.faces.event.ValueChangeEvent;
39 import javax.faces.validator.MethodExpressionValidator;
40
41 import com.sun.facelets.FaceletContext;
42 import com.sun.facelets.el.ELAdaptor;
43 import com.sun.facelets.el.LegacyMethodBinding;
44 import com.sun.facelets.el.LegacyValueBinding;
45 import com.sun.facelets.tag.MetaTagHandler;
46 import com.sun.facelets.tag.TagAttribute;
47 import com.sun.facelets.tag.Metadata;
48 import com.sun.facelets.tag.TagException;
49 import com.sun.facelets.tag.TagHandler;
50 import com.sun.facelets.tag.MetaRuleset;
51 import com.sun.facelets.util.FacesAPI;
52
53 /**
54  * Implementation of the tag logic used in the JSF specification. This is your
55  * golden hammer for wiring UIComponents to Facelets.
56  *
57  * @author Jacob Hookom
58  * @version $Id: ComponentHandler.java,v 1.14 2006/03/29 15:01:22 jhook Exp $
59  */

60 public class ComponentHandler extends MetaTagHandler {
61
62     private final static Logger JavaDoc log = Logger
63             .getLogger("facelets.tag.component");
64     
65     private final TagAttribute binding;
66
67     private final String JavaDoc componentType;
68
69     private final TagAttribute id;
70
71     private final String JavaDoc rendererType;
72
73     public ComponentHandler(ComponentConfig config) {
74         super(config);
75         this.componentType = config.getComponentType();
76         this.rendererType = config.getRendererType();
77         this.id = this.getAttribute("id");
78         this.binding = this.getAttribute("binding");
79     }
80
81     /**
82      * Method handles UIComponent tree creation in accordance with the JSF 1.2
83      * spec.
84      * <ol>
85      * <li>First determines this UIComponent's id by calling
86      * {@link #getId(FaceletContext) getId(FaceletContext)}.</li>
87      * <li>Search the parent for an existing UIComponent of the id we just
88      * grabbed</li>
89      * <li>If found, {@link #markForDeletion(UIComponent) mark} its children
90      * for deletion.</li>
91      * <li>If <i>not</i> found, call
92      * {@link #createComponent(FaceletContext) createComponent}.
93      * <ol>
94      * <li>Only here do we apply
95      * {@link ObjectHandler#setAttributes(FaceletContext, Object) attributes}</li>
96      * <li>Set the UIComponent's id</li>
97      * <li>Set the RendererType of this instance</li>
98      * </ol>
99      * </li>
100      * <li>Now apply the nextHandler, passing the UIComponent we've
101      * created/found.</li>
102      * <li>Now add the UIComponent to the passed parent</li>
103      * <li>Lastly, if the UIComponent already existed (found), then
104      * {@link #finalizeForDeletion(UIComponent) finalize} for deletion.</li>
105      * </ol>
106      *
107      * @see com.sun.facelets.FaceletHandler#apply(com.sun.facelets.FaceletContext,
108      * javax.faces.component.UIComponent)
109      *
110      * @throws TagException
111      * if the UIComponent parent is null
112      */

113     public final void apply(FaceletContext ctx, UIComponent parent)
114             throws IOException JavaDoc, FacesException, ELException {
115         // make sure our parent is not null
116
if (parent == null) {
117             throw new TagException(this.tag, "Parent UIComponent was null");
118         }
119
120         // our id
121
String JavaDoc id = ctx.generateUniqueId(this.tagId);
122
123         // grab our component
124
UIComponent c = ComponentSupport.findChildByTagId(parent, id);
125         boolean componentFound = false;
126         if (c != null) {
127             componentFound = true;
128             // mark all children for cleaning
129
if (log.isLoggable(Level.FINE)) {
130                 log.fine(this.tag
131                         + " Component["+id+"] Found, marking children for cleanup");
132             }
133             ComponentSupport.markForDeletion(c);
134         } else {
135             c = this.createComponent(ctx);
136             if (log.isLoggable(Level.FINE)) {
137                 log.fine(this.tag + " Component["+id+"] Created: "
138                         + c.getClass().getName());
139             }
140             this.setAttributes(ctx, c);
141             
142             // mark it owned by a facelet instance
143
c.getAttributes().put(ComponentSupport.MARK_CREATED, id);
144             
145             // assign our unique id
146
if (this.id != null) {
147                 c.setId(this.id.getValue(ctx));
148             } else {
149                 UIViewRoot root = ComponentSupport.getViewRoot(ctx, parent);
150                 if (root != null) {
151                     String JavaDoc uid = root.createUniqueId();
152                     c.setId(uid);
153                 }
154             }
155             
156             if (this.rendererType != null) {
157                 c.setRendererType(this.rendererType);
158             }
159             
160             // hook method
161
this.onComponentCreated(ctx, c, parent);
162         }
163
164         // first allow c to get populated
165
this.applyNextHandler(ctx, c);
166
167         // finish cleaning up orphaned children
168
if (componentFound) {
169             ComponentSupport.finalizeForDeletion(c);
170             parent.getChildren().remove(c);
171         }
172         
173
174         this.onComponentPopulated(ctx, c, parent);
175
176         // add to the tree afterwards
177
// this allows children to determine if it's
178
// been part of the tree or not yet
179
parent.getChildren().add(c);
180     }
181
182     /**
183      * If the binding attribute was specified, use that in conjuction with our
184      * componentType String variable to call createComponent on the Application,
185      * otherwise just pass the componentType String.
186      * <p />
187      * If the binding was used, then set the ValueExpression "binding" on the
188      * created UIComponent.
189      *
190      * @see Application#createComponent(javax.faces.el.ValueBinding,
191      * javax.faces.context.FacesContext, java.lang.String)
192      * @see Application#createComponent(java.lang.String)
193      * @param ctx
194      * FaceletContext to use in creating a component
195      * @return
196      */

197     protected UIComponent createComponent(FaceletContext ctx) {
198         UIComponent c = null;
199         FacesContext faces = ctx.getFacesContext();
200         Application app = faces.getApplication();
201         if (this.binding != null) {
202             ValueExpression ve = this.binding.getValueExpression(ctx,
203                     Object JavaDoc.class);
204             if (FacesAPI.getVersion() >= 12) {
205                 c = app.createComponent(ve, faces, this.componentType);
206                 if (c != null) {
207                     // Make sure the component supports 1.2
208
if (FacesAPI.getComponentVersion(c) >= 12) {
209                         c.setValueExpression("binding", ve);
210                     } else {
211                         ValueBinding vb = new LegacyValueBinding(ve);
212                         c.setValueBinding("binding", vb);
213                     }
214
215                 }
216             } else {
217                 ValueBinding vb = new LegacyValueBinding(ve);
218                 c = app.createComponent(vb, faces, this.componentType);
219                 if (c != null) {
220                     c.setValueBinding("binding", vb);
221                 }
222             }
223         } else {
224             c = app.createComponent(this.componentType);
225         }
226         return c;
227     }
228
229     /**
230      * If the id TagAttribute was specified, get it's value, otherwise generate
231      * a unique id from our tagId.
232      *
233      * @see TagAttribute#getValue(FaceletContext)
234      * @param ctx
235      * FaceletContext to use
236      * @return what should be a unique Id
237      */

238     protected String JavaDoc getId(FaceletContext ctx) {
239         if (this.id != null) {
240             return this.id.getValue(ctx);
241         }
242         return ctx.generateUniqueId(this.tagId);
243     }
244
245     protected MetaRuleset createMetaRuleset(Class JavaDoc type) {
246         MetaRuleset m = super.createMetaRuleset(type);
247         
248         // ignore standard component attributes
249
m.ignore("binding").ignore("id");
250         
251         // add auto wiring for attributes
252
m.addRule(ComponentRule.Instance);
253         
254         // if it's an ActionSource
255
if (ActionSource.class.isAssignableFrom(type)) {
256             m.addRule(ActionSourceRule.Instance);
257         }
258         
259         // if it's a ValueHolder
260
if (ValueHolder.class.isAssignableFrom(type)) {
261             m.addRule(ValueHolderRule.Instance);
262             
263             // if it's an EditableValueHolder
264
if (EditableValueHolder.class.isAssignableFrom(type)) {
265                 m.ignore("submittedValue");
266                 m.ignore("valid");
267                 m.addRule(EditableValueHolderRule.Instance);
268             }
269         }
270         
271         return m;
272     }
273     
274     /**
275      * A hook method for allowing developers to do additional processing once Facelets
276      * creates the component. The 'setAttributes' method is still perferred, but this
277      * method will provide the parent UIComponent before it's been added to the tree and
278      * before any children have been added to the newly created UIComponent.
279      *
280      * @param ctx
281      * @param c
282      * @param parent
283      */

284     protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent) {
285         // do nothing
286
}
287
288     protected void onComponentPopulated(FaceletContext ctx, UIComponent c, UIComponent parent) {
289         // do nothing
290
}
291
292     protected void applyNextHandler(FaceletContext ctx, UIComponent c)
293             throws IOException JavaDoc, FacesException, ELException {
294         // first allow c to get populated
295
this.nextHandler.apply(ctx, c);
296     }
297 }
298
Popular Tags