KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > jsfext > layout > descriptor > LayoutElementBase


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.tools.jsfext.layout.descriptor;
24
25 import com.sun.enterprise.tools.jsfext.component.ComponentUtil;
26 import com.sun.enterprise.tools.jsfext.event.AfterEncodeEvent;
27 import com.sun.enterprise.tools.jsfext.event.BeforeEncodeEvent;
28 import com.sun.enterprise.tools.jsfext.event.EncodeEvent;
29 import com.sun.enterprise.tools.jsfext.event.handlers.Handler;
30 import com.sun.enterprise.tools.jsfext.event.handlers.HandlerContext;
31 import com.sun.enterprise.tools.jsfext.event.handlers.HandlerContextImpl;
32
33 import com.sun.web.ui.util.RenderingUtilities;
34
35 import java.io.IOException JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.EventObject JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Map JavaDoc;
42
43 import javax.faces.component.UIComponent;
44 import javax.faces.context.FacesContext;
45
46
47 /**
48  * <p> This class provides some common functionality between the various types
49  * of {@link LayoutElement}s. It is the base class of most
50  * implementations (perhaps all).</p>
51  *
52  * @author Ken Paulsen (ken.paulsen@sun.com)
53  */

54 public abstract class LayoutElementBase implements LayoutElement {
55
56     /**
57      * <p> Constructor.</p>
58      *
59      * @param parent The parent LayoutElement
60      * @param id Identifier for this LayoutElement
61      */

62     protected LayoutElementBase(LayoutElement parent, String JavaDoc id) {
63     setParent(parent);
64     _id = id;
65     }
66
67
68     /**
69      * <p> This method is used to add a {@link LayoutElement}.
70      * {@link LayoutElement}s should be added sequentially in the order
71      * in which they are to be rendered.</p>
72      *
73      * @param element The {@link LayoutElement} to add as a child.
74      */

75     public void addChildLayoutElement(LayoutElement element) {
76     _layoutElements.add(element);
77     }
78
79
80     /**
81      * <p> This method returns the {@link LayoutElement}s as a List.</p>
82      *
83      * @return List of {@link LayoutElement}s.
84      */

85     public List JavaDoc getChildLayoutElements() {
86     return _layoutElements;
87     }
88
89
90     /**
91      * <p> This method walks to the top-most {@link LayoutElement}, which
92      * should be a {@link LayoutDefinition}. If not, it will throw an
93      * exception.</p>
94      *
95      * @return The {@link LayoutDefinition}.
96      */

97     public LayoutDefinition getLayoutDefinition() {
98     // Find the top-most LayoutElement
99
LayoutElement cur = this;
100     while (cur.getParent() != null) {
101         cur = cur.getParent();
102     }
103
104     // This should be the LayoutDefinition, return it
105
return (LayoutDefinition) cur;
106     }
107
108
109     /**
110      * <p> This method returns the parent {@link LayoutElement}.</p>
111      *
112      * @return parent LayoutElement
113      */

114     public LayoutElement getParent() {
115     return _parent;
116     }
117
118
119     /**
120      * <p> This method sets the parent {@link LayoutElement}.</p>
121      *
122      * @param parent Parent {@link LayoutElement}.
123      */

124     protected void setParent(LayoutElement parent) {
125     _parent = parent;
126     }
127
128
129     /**
130      * <p> Accessor method for id. This returns a non-null value, it may
131      * return "" if id is not set or does not apply.</p>
132      *
133      * <p> This method will also NOT resolve EL strings.</p>
134      *
135      * @return a non-null id
136      */

137     private String JavaDoc getId() {
138     if (_id == null) {
139         return "";
140     }
141     return _id;
142     }
143
144     /**
145      * <p> This method generally should not be used. It does not resolve
146      * expressions. Instead use
147      * {@link #getId(FacesContext, UIComponent)}.</p>
148      *
149      * @return The unevaluated id.
150      */

151     public String JavaDoc getUnevaluatedId() {
152     return _id;
153     }
154
155     /**
156      * <p> Accessor method for id. This returns a non-null value, it may
157      * return "" if id is not set or does not apply.</p>
158      *
159      * <p> This method will also attempt to resolve EL strings.</p>
160      *
161      * @param context The <code>FacesContext</code>
162      * @param parent The parent <code>UIComponent</code>. This is used
163      * because the current UIComponent is typically
164      * unknown (or not even created yet).
165      *
166      * @return A non-null id.
167      */

168     public String JavaDoc getId(FacesContext context, UIComponent parent) {
169     // Evaluate the id...
170
Object JavaDoc value = resolveValue(context, parent, getId());
171
172     // Return the result
173
return (value == null) ? "" : value.toString();
174     }
175
176     /**
177      * <p> This method will attempt to resolve EL strings in the given
178      * value.</p>
179      *
180      * @param context The <code>FacesContext</code>
181      * @param parent The parent <code>UIComponent</code>. This is used
182      * because the current UIComponent is typically
183      * unknown (or not even created yet).
184      * @param value The String to resolve
185      *
186      * @return The evaluated value (may be null).
187      */

188     public Object JavaDoc resolveValue(FacesContext context, UIComponent parent, String JavaDoc value) {
189     return ComponentUtil.resolveValue(context, this, parent, value);
190     }
191
192     /**
193      * <p> This method allows each LayoutElement to provide it's own encode
194      * functionality. If the {@link LayoutElement} should render its
195      * children, this method should return true. Otherwise, this method
196      * should return false.</p>
197      *
198      * @param context The FacesContext
199      * @param component The UIComponent
200      *
201      * @return true if children are to be rendered, false otherwise.
202      */

203     protected abstract boolean encodeThis(FacesContext context, UIComponent component) throws IOException JavaDoc;
204
205     /**
206      * <p> This is the base implementation for encode. Typically each type of
207      * LayoutElement wants to do something specific then conditionally have
208      * its children rendered. This method invokes the abstract method
209      * "encodeThis" to do specific functionality, it the walks the children
210      * and renders them, if encodeThis returns true. It skips the children
211      * if encodeThis returns false.</p>
212      *
213      * <p> NOTE: Some subclasses override this method, be careful when
214      * changing/adding to this code.</p>
215      *
216      * @param context The <code>FacesContext</code>
217      * @param component The <code>UIComponent</code>
218      */

219     public void encode(FacesContext context, UIComponent component) throws IOException JavaDoc {
220     // Invoke "before" handlers
221
// FIXME: Consider true/false for skipping component
222
Object JavaDoc result = dispatchHandlers(context, BEFORE_ENCODE,
223         new BeforeEncodeEvent(component));
224
225     // Do LayoutElement specific stuff...
226
boolean renderChildren = encodeThis(context, component);
227
228 // FIXME: Consider buffering HTML and passing to "endDisplay" handlers...
229
// FIXME: Storing in the EventObject may be useful if we go this route.
230

231     // Perhaps we want our own Response writer to buffer children?
232
//ResponseWriter out = context.getResponseWriter();
233

234     // Conditionally render children...
235
if (renderChildren) {
236         result = dispatchHandlers(context, ENCODE,
237         new EncodeEvent(component));
238
239         // Iterate over children
240
LayoutElement childElt = null;
241         Iterator JavaDoc it = getChildLayoutElements().iterator();
242         while (it.hasNext()) {
243         childElt = (LayoutElement) it.next();
244         childElt.encode(context, component);
245         }
246     }
247
248     // Invoke "after" handlers
249
result = dispatchHandlers(context, AFTER_ENCODE,
250         new AfterEncodeEvent(component));
251     }
252
253
254     /**
255      * <p> This method iterates over the handlers and executes each one. A
256      * HandlerContext will be created to pass to each Handler. The
257      * HandlerContext object is reused across all Handlers that are
258      * invoked; the setHandler(Handler) method is invoked with the
259      * correct Handler descriptor before the handler is executed.</p>
260      *
261      * @param context The FacesContext
262      * @param eventType The event type which is being fired
263      * @param event An optional EventObject providing more detail
264      *
265      * @return By default, (null) is returned. However, if any of the
266      * handlers produce a non-null return value, then the value from
267      * the last handler to produces a non-null return value is
268      * returned.
269      */

270     public Object JavaDoc dispatchHandlers(FacesContext context, String JavaDoc eventType, EventObject JavaDoc event) {
271     // Get the handlers for this eventType
272
Object JavaDoc eventObj = event.getSource();
273     if (!(eventObj instanceof UIComponent)) {
274         eventObj = null;
275     }
276     List JavaDoc handlers = getHandlers(eventType, (UIComponent) eventObj);
277
278     // Make sure we have something to do...
279
if (handlers == null) {
280         return null;
281     }
282
283     // Create a HandlerContext
284
HandlerContext handlerContext =
285         createHandlerContext(context, event, eventType);
286
287     // This method is broken down so that recursion is easier
288
return dispatchHandlers(handlerContext, handlers);
289     }
290
291     /**
292      * <p> As currently implemented, this method is essentially a utility
293      * method. It dispatches the given List of <code>Handler<code>s.
294      * This may be available as a static method in the future.</p>
295      */

296     public Object JavaDoc dispatchHandlers(HandlerContext handlerCtx, List JavaDoc handlers) {
297     Object JavaDoc retVal = null;
298     Object JavaDoc result = null;
299     Handler handler = null;
300     Iterator JavaDoc it = handlers.iterator();
301     while (it.hasNext()) {
302         try {
303         // Get the Handler
304
handler = (Handler) it.next();
305         handlerCtx.setHandler(handler);
306
307         // Delegate to the Handler to perform invocation
308
retVal = handler.invoke(handlerCtx);
309
310         // Check for return value
311
if (retVal != null) {
312             result = retVal;
313         }
314         } catch (Exception JavaDoc ex) {
315         throw new RuntimeException JavaDoc(
316             ex.getClass().getName() + " while attempting to "
317             + "process a '" + handlerCtx.getEventType()
318             + "' event for '" + getId() + "'.", ex);
319         }
320     }
321
322     // Return the return value (null by default)
323
return result;
324     }
325
326     /**
327      * <p> This method is responsible for creating a new HandlerContext. It
328      * does not set the Handler descriptor. This is done right before a
329      * Handler is invoked. This allows the HandlerContext object to be
330      * reused.</p>
331      *
332      * @param context The FacesContext
333      */

334     protected HandlerContext createHandlerContext(FacesContext context, EventObject JavaDoc event, String JavaDoc eventType) {
335     return new HandlerContextImpl(context, this, event, eventType);
336     }
337
338     /**
339      * <p> This method retrieves the Handlers for the requested type.</p>
340      *
341      * @param type The type of Handlers to retrieve.
342      *
343      * @return A List of Handlers.
344      */

345     public List JavaDoc getHandlers(String JavaDoc type) {
346     return (List JavaDoc) _handlersByType.get(type);
347     }
348
349     /**
350      * <p> This method provides access to the "handlersByType"
351      * <code>Map</code>.</p>
352      */

353     public Map JavaDoc getHandlersByTypeMap() {
354     return _handlersByType;
355     }
356
357     /**
358      * <p> This method provides a means to set the "handlersByType" Map.
359      * Normally this is done for each type individually via
360      * {@link #setHandlers(String, List)}. This Map may not be null (null
361      * will be ignored) and should contain entries that map to
362      * <code>List</code>s of {@link Handler}s.
363      */

364     public void setHandlersByTypeMap(Map JavaDoc map) {
365     if (map != null) {
366         _handlersByType = map;
367     }
368     }
369
370     /**
371      * <p> This method retrieves the Handlers for the requested type.</p>
372      *
373      * @param type The type of <code>Handler</code>s to retrieve.
374      * @param event The associated <code>UIComponent</code> (or null).
375      *
376      * @return A List of Handlers.
377      */

378     public List JavaDoc getHandlers(String JavaDoc type, UIComponent comp) {
379     // 1st get list of handlers for definition of this LayoutElement
380
List JavaDoc handlers = getHandlers(type);
381
382     // NOTE: At this point, very few types should support "instance"
383
// NOTE: handlers (LayoutComponent, LayoutDefinition, more??). To
384
// NOTE: support them, the future, the specific LayoutElement subclass
385
// NOTE: will have to deal with this. For example, LayoutComponent
386
// NOTE: "instance" handlers are dealt with in LayoutComponent (it
387
// NOTE: overrides this method).
388

389     return handlers;
390     }
391
392     /**
393      * <p> This method associates 'type' with the given list of Handlers.</p>
394      *
395      * @param type The String type for the List of Handlers
396      * @param handlers The List of Handlers
397      */

398     public void setHandlers(String JavaDoc type, List JavaDoc handlers) {
399     _handlersByType.put(type, handlers);
400     }
401
402     /**
403      * <p> This method is a convenience method for encoding the given
404      * <code>UIComponent</code>. It calls the appropriate encoding
405      * methods on the component and calls itself recursively for all
406      * <code>UIComponent</code> children that do not render their own
407      * children.</p>
408      *
409      * @param context <code>FacesContext</code>
410      * @param component <code>UIComponent</code> to encode
411      */

412     public static void encodeChild(FacesContext context, UIComponent component) throws IOException JavaDoc {
413 /*
414     This code is removed b/c of the way the Table code is designed. It
415     needs to recalculate the clientId all the time. Rather than deal with
416     this in the table code, the design requires that every component
417     regenerate its clientId every time it is rendered. Hopefully the Table
418     code will be rewritten to not require this, or to do this task itself.
419
420     For now, I will avoid doing the "right" thing and call a helper method
421     in LH wich sets the component ID (causing the clientId to be erased).
422     In the future, I may want to eliminate the dependency on this class and
423     do the hack myself, or better yet, do the code here that is commented
424     out. Ken
425
426     if (!component.isRendered()) {
427         return;
428     }
429
430     component.encodeBegin(context);
431     if (component.getRendersChildren()) {
432         component.encodeChildren(context);
433     } else {
434         Iterator i = component.getChildren().iterator();
435         while (i.hasNext()) {
436         UIComponent child = (UIComponent) i.next();
437         encodeChild(context, child);
438         }
439     }
440     component.encodeEnd(context);
441 */

442
443     RenderingUtilities.renderComponent(component, context);
444     }
445
446
447     /**
448      * List of renderable elements (if, facet, UIComponents)
449      */

450     private List JavaDoc _layoutElements = new ArrayList JavaDoc();
451
452
453     /**
454      * The parent LayoutElement. This will be null for the LayoutDefinition.
455      */

456     private LayoutElement _parent = null;
457
458     /**
459      * Map containing Lists of Handlers
460      */

461     private Map JavaDoc _handlersByType = new HashMap JavaDoc();
462
463     /**
464      * This stores the id for the LayoutElement
465      */

466     private String JavaDoc _id = null;
467
468     /**
469      * <p> This is the "type" for handlers to be invoked after the encoding
470      * of this element.</p>
471      */

472      public static final String JavaDoc AFTER_ENCODE = "afterEncode";
473
474     /**
475      * <p> This is the "type" for handlers to be invoked before the encoding
476      * of this element.</p>
477      */

478      public static final String JavaDoc BEFORE_ENCODE = "beforeEncode";
479
480     /**
481      * <p> This is the "type" for handlers to be invoked during the encoding
482      * of this element. This occurs before any child LayoutElements are
483      * invoked and only if child Elements are to be invoked.</p>
484      */

485      public static final String JavaDoc ENCODE = "encode";
486 }
487
Popular Tags