You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/11/04 15:12:39 UTC
svn commit: r711257 -
/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java
Author: skitching
Date: Tue Nov 4 06:12:38 2008
New Revision: 711257
URL: http://svn.apache.org/viewvc?rev=711257&view=rev
Log:
Prevent text content within the of:flowCall tag from being added as transient child elements to the component.
Modified:
myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java
Modified: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java?rev=711257&r1=711256&r2=711257&view=diff
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java (original)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/FlowCallComponentHandler.java Tue Nov 4 06:12:38 2008
@@ -19,8 +19,11 @@
package org.apache.myfaces.orchestra.flow.components;
+import java.io.IOException;
import java.util.Iterator;
+import javax.el.ELException;
+import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import com.sun.facelets.FaceletContext;
@@ -31,9 +34,14 @@
/**
* Facelets component-handler which creates a FlowCallComponent instance.
* <p>
- * Note that a facelets ComponentHandler is invoked only when the component is first created;
- * later re-renders of the same view do not invoke ComponentHandlers for components that
- * already exist.
+ * Note that a facelets ComponentHandler is a subclass of TagHandler. The methods in TagHandler
+ * are "tag oriented", ie focused on handling a tree of tags. The methods in a ComponentHandler
+ * are "higher level", ie the callbacks are focused on component creation and configuration.
+ * <p>
+ * Facelets first parses the input into a syntax tree (of Facelets Instruction nodes) and caches
+ * it (for later use). It then walks the tree, invoking the appropriate tag or component handler.
+ * Each ComponentHandler has access to the list of nodes nested within it via the "nextHandler"
+ * member.
*/
public class FlowCallComponentHandler extends ComponentHandler
{
@@ -43,26 +51,33 @@
}
/**
- * When Facelets encounters the start tag for this component, it will create the
- * component and assign any attributes. It then calls this method.
+ * When Facelets encounters the start tag for this component, it will create the component and assign any
+ * attributes. It then calls this method.
+ * <p>
+ * Here we ask the nodes nested within this element to return their text. Then the nested text is passed
+ * to the new component. This has the same effect as a JSP tag overriding "doAfterBody", but is pull-style
+ * rather than waiting for a callback to occur. Note, however that the body of this element *has* already
+ * been parsed into instruction nodes; there appears to be no way to stop Facelets doing this.
* <p>
- * Here we do a kind of "pull parsing" of the input, fetching the nested text. Then
- * the nested text is passed to the new component. This has the same effect as a
- * JSP tag overriding "doAfterBody", but is pull-style rather than waiting for a
- * callback to occur.
+ * Note that even though we process the body text explicitly here, facelets will try to process the nested
+ * Instruction nodes after this method has returned. Therefore the applyNextHandler method is overridden
+ * to prevent that.
*/
protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent)
{
StringBuffer content = new StringBuffer();
- // Method findNextByType will repeatedly call the facelets parser ("compiler") to get
- // "nodes" from the input. If the "handler" for that node is of the specified type then
- // the handler is returned. I'm not sure what happens for nodes whose handler is not of
- // the specified type, but in this case we don't expect anything other than Text nodes
- // nested within an of:flowCall tag.
+ // Method findNextByType will scan the list of child "nodes" for the "StartElementInstruction" node
+ // that triggered the call to this method. We actually expect just one node (of type Instruction)
+ // which implements the TextHandler interface. It will internally have broken down the XML content
+ // of the flowCall element into separate nodes for the xml elements, attributes and body-text.
+ // However we don't need to know that; just calling getText on that top-level child will cause
+ // it to append together the text representations of all the child elements and return the complete
+ // string.
//
- // The iterator stops (hasNext is false) when the end-tag for this of:flowCall tag
- // is encountered.
+ // The loop is just in case there are multiple child Instruction objects for some reason; this is
+ // not expected. The iterator always stops (hasNext is false) when there are no more child nodes
+ // for this flowCall element.
content.append("<flowCall>\n");
Iterator iter = findNextByType(TextHandler.class);
while (iter.hasNext())
@@ -79,4 +94,29 @@
((FlowCallComponent) c).setBody(content.toString());
}
+
+ protected void onComponentPopulated(FaceletContext ctx, UIComponent c, UIComponent parent)
+ {
+ // do nothing
+ }
+
+ protected void applyNextHandler(FaceletContext ctx, UIComponent c)
+ throws IOException, FacesException, ELException
+ {
+ // Do nothing.
+ //
+ // This method is called by the Facelets framework immediately after onComponentCreated
+ // is called.
+ //
+ // The normal behaviour is to call this.nextHandler.apply(ctx, c) in order to iterate over
+ // the child instructions of this element and process them. But we don't want this as out
+ // onComponentCreated method has already extracted all of the data we wanted. Without
+ // this override, transient text children would be added to component "c".
+ //
+ // It would be better if we could tell Facelets to not create Instruction nodes for the
+ // nested content of this element at all; then it would not be necessary to override
+ // this method as there *would* be no nested Instruction nodes. But I haven't figured
+ // out how to do that. Facelets is of course driven by a normal XML parser that will
+ // always break down the input into SAX events anyway...
+ }
}