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/10/20 11:50:34 UTC

svn commit: r706174 - in /myfaces/orchestra/trunk/flow/src/main: java/org/apache/myfaces/orchestra/flow/ java/org/apache/myfaces/orchestra/flow/components/ resources/META-INF/

Author: skitching
Date: Mon Oct 20 02:50:34 2008
New Revision: 706174

URL: http://svn.apache.org/viewvc?rev=706174&view=rev
Log:
Add clearOnCommit component, and invoke it on flow commit.

Added:
    myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java   (with props)
    myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java   (with props)
Modified:
    myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/FlowHandler.java
    myfaces/orchestra/trunk/flow/src/main/resources/META-INF/faces-config.xml
    myfaces/orchestra/trunk/flow/src/main/resources/META-INF/myfaces_orchestra_flow.tld

Modified: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/FlowHandler.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/FlowHandler.java?rev=706174&r1=706173&r2=706174&view=diff
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/FlowHandler.java (original)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/FlowHandler.java Mon Oct 20 02:50:34 2008
@@ -38,6 +38,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.orchestra.conversation.ConversationContext;
 import org.apache.myfaces.orchestra.conversation.ConversationManager;
+import org.apache.myfaces.orchestra.flow.components.ClearOnCommit;
 import org.apache.myfaces.orchestra.flow.components.ModalFlow;
 import org.apache.myfaces.orchestra.flow.config.FlowAccept;
 import org.apache.myfaces.orchestra.flow.config.FlowCall;
@@ -323,6 +324,13 @@
                 // Now restore the view tree of the caller.
                 restoreViewRoot(facesContext, callerViewId, callerViewRoot);
 
+                if (callerViewRoot != null)
+                {
+                    // Clear any input components in the caller view which reference values that
+                    // are return values.
+                    ClearOnCommit.executeAllInstances(callerViewRoot, flowInfo.getCallerOutcome());
+                }
+
                 // And with the original context active, write parameters back then
                 // invoke any custom actions the caller wants to run.
                 //

Added: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java?rev=706174&view=auto
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java (added)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java Mon Oct 20 02:50:34 2008
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.orchestra.flow.components;
+
+import java.util.Iterator;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+
+/**
+ * A component which handles clearing of cached user input (submittedValue) from
+ * input components whose model has been modified by an invoked flow.
+ * <p>
+ * When a flowcall is triggered by an immediate component, data entered by the user
+ * into input components is not pushed into the model before the call; it just gets
+ * stored in the "submittedValue" property of the input components. This view tree
+ * is then cached, and on return from the flow the original tree is deliberately restored
+ * so that user-entered data is not lost.
+ * <p>
+ * However this is a problem for input components whose model value has been modified by
+ * the flowcall (ie which map to something updated by a return-value from the flow). In
+ * this case we *do* want to discard the submittedValue in the component so that the
+ * new value in the model is displayed.
+ * <p>
+ * There is no automatic way to detect which input components in a page are affected by
+ * the return parameters from a flow. It *is* possible to detect input components whose
+ * value attribute is an EL expression that is identical to an EL expression for a return
+ * value, and that might be implemented in future. However there are many cases where a
+ * dependency cannot be detected with this simple test.
+ * <p>
+ * Instances of this component can be added to the page to explicitly mark components that
+ * need to be cleared on return from a specific flowcall.
+ * <p>
+ * Clearing of the submittedValue obviously does NOT need to be done on the first render
+ * of a view; it is something that is only relevant when a view has had at least one
+ * postback cycle and is then being re-rendered. And it is not relevant when a flowcall
+ * is triggered by a non-immediate command-component; in that case there is no _submittedValue
+ * cached in any input component, so updated model values cannot be "hidden" by the
+ * componenent cached value. In fact in this case, the original view is not even cached at
+ * all, as it can simply be recreated.
+ * <p>
+ * This component cannot be used with input components that are within a dataTable component;
+ * in that case the cached submitted-values are actually stored secretly within the dataTable
+ * and simply cannot be accessed by this component. In that case, the only solution is to
+ * apply this component to the entire table, ie clear all user data in all input fields
+ * within the table on flow return. This is not perfect, but is the best that can be done.
+ * <p>
+ * Note that this component does not simply "reset" the component; it actually deletes the
+ * component from the tree and relies on the rendering phase to recreate a new clean instance.
+ * This is done because UIInput has a resetValue method, but UIData does not.
+ */
+
+public class ClearOnCommit extends UIComponentBase
+{
+    public static final String COMPONENT_FAMILY = "javax.faces.Component";
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.orchestra.flow.components.ClearOnCommit";
+
+    private String outcome;
+    private String target;
+
+    public String getFamily()
+    {
+        return COMPONENT_FAMILY;
+    }
+
+    /**
+     * The navigation outcome that causes this component to remove the target component
+     * from the component tree.
+     * <p>
+     * Static value only (EL expressions not supported).
+     */
+    public String getOutcome()
+    {
+        return outcome;
+    }
+
+    public void setOutcome(String outcome)
+    {
+        this.outcome = outcome;
+    }
+
+    /**
+     * Return the JSF component id of the target component to clear.
+     * <p>
+     * Static value only (EL expressions not supported).
+     */
+    public String getTarget()
+    {
+        return target;
+    }
+
+    public void setTarget(String target)
+    {
+        this.target = target;
+    }
+
+    /**
+     * If the specified navigation-outcome matches the outcome attribute of this component
+     * then delete the associated target component.
+     */
+    private void clearTargetComponent(String outcome)
+    {
+        if (!outcome.equals(this.outcome))
+        {
+            return;
+        }
+
+        if (this.getChildCount() > 0)
+        {
+            this.getChildren().clear();
+        }
+        
+        if (target != null)
+        {
+            UIComponent targetComponent = this.findComponent(target);
+            if (targetComponent == null)
+            {
+                throw new FacesException("Target component for clearOnCommit does not exist:" + target);
+            }
+            targetComponent.getParent().getChildren().remove(targetComponent);
+        }
+    }
+
+    // ================ State Methods =================
+
+    public void restoreState(FacesContext context, Object state)
+    throws FacesException
+    {
+        Object[] states = (Object[]) state;
+        super.restoreState(context, states[0]);
+        outcome = (String) states[1];
+        target = (String) states[2];
+    }
+
+    public Object saveState(FacesContext context)
+    {
+        return new Object[]
+            {
+                super.saveState(context),
+                outcome,
+                target
+            };
+    }
+
+    // ============ Static methods =================
+
+    /**
+     * Execute the clearTargetComponent method of each ClearOnCommit component in the specified view tree.
+     * <p>
+     * This clears any _submittedValue property from the "target" component of each clearOnCommit component
+     * in the tree which has an outcome that matches the specified outcome value.
+     */
+    public static void executeAllInstances(UIViewRoot viewRoot, String outcome)
+    {
+        applyToAll(viewRoot, outcome);
+    }
+
+    private static void applyToAll(UIComponent c, String outcome)
+    {
+        if (c instanceof ClearOnCommit)
+        {
+            ((ClearOnCommit) c).clearTargetComponent(outcome);
+        }
+
+        if (c.getChildCount() == 0)
+        {
+            return;
+        }
+
+        Iterator i = c.getChildren().iterator();
+        while (i.hasNext())
+        {
+            applyToAll((UIComponent) i.next(), outcome);
+        }
+    }
+
+}

Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommit.java
------------------------------------------------------------------------------
    svn:executable = *

Added: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java?rev=706174&view=auto
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java (added)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java Mon Oct 20 02:50:34 2008
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.orchestra.flow.components;
+
+import javax.faces.component.UIComponent;
+
+import org.apache.myfaces.shared_orchestra.taglib.UIComponentTagBase;
+
+/**
+ * Tag for ClearOnCommit component.
+ */
+public class ClearOnCommitTag extends UIComponentTagBase
+{
+    private String outcome;
+    private String target;
+
+    public String getComponentType()
+    {
+        return ClearOnCommit.COMPONENT_TYPE;
+    }
+
+    protected void setProperties(UIComponent component)
+    {
+        super.setProperties(component);
+
+        setStringProperty(component, "outcome", outcome);
+        setStringProperty(component, "target", target);
+    }
+
+    public void setOutcome(String outcome)
+    {
+        this.outcome = outcome;
+    }
+
+    public void setTarget(String target)
+    {
+        this.target = target;
+    }
+
+    public String getRendererType()
+    {
+        return null;
+    }
+}

Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ClearOnCommitTag.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: myfaces/orchestra/trunk/flow/src/main/resources/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/resources/META-INF/faces-config.xml?rev=706174&r1=706173&r2=706174&view=diff
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/resources/META-INF/faces-config.xml (original)
+++ myfaces/orchestra/trunk/flow/src/main/resources/META-INF/faces-config.xml Mon Oct 20 02:50:34 2008
@@ -37,5 +37,10 @@
         <component-type>org.apache.myfaces.orchestra.flow.components.ModalFlow</component-type>
         <component-class>org.apache.myfaces.orchestra.flow.components.ModalFlow</component-class>
     </component>
+
+    <component>
+        <component-type>org.apache.myfaces.orchestra.flow.components.ClearOnCommit</component-type>
+        <component-class>org.apache.myfaces.orchestra.flow.components.ClearOnCommit</component-class>
+    </component>
     
 </faces-config>

Modified: myfaces/orchestra/trunk/flow/src/main/resources/META-INF/myfaces_orchestra_flow.tld
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/resources/META-INF/myfaces_orchestra_flow.tld?rev=706174&r1=706173&r2=706174&view=diff
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/resources/META-INF/myfaces_orchestra_flow.tld (original)
+++ myfaces/orchestra/trunk/flow/src/main/resources/META-INF/myfaces_orchestra_flow.tld Mon Oct 20 02:50:34 2008
@@ -64,4 +64,28 @@
             </description>
         </attribute>
     </tag>
+    <tag>
+        <name>clearOnCommit</name>
+        <tag-class>org.apache.myfaces.orchestra.flow.components.ClearOnCommitTag</tag-class>
+        <body-content>JSP</body-content>
+        <description>Clears input components when a returning flow modifies the underlying model.</description>
+
+        <attribute>
+            <name>outcome</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <description>
+                The navigation outcome which triggered the flow call.
+            </description>
+        </attribute>
+        <attribute>
+            <name>target</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <description>
+                The id of the input component to clear. Either this should be set, OR this component
+                should have child components.
+            </description>
+        </attribute>
+    </tag>
 </taglib>