You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by gv...@apache.org on 2006/05/28 00:57:45 UTC

svn commit: r409894 - in /struts/shale/trunk/clay-plugin/src: java/org/apache/shale/clay/config/ java/org/apache/shale/clay/config/beans/ java/org/apache/shale/clay/parser/builder/ test/org/apache/shale/clay/config/

Author: gvanmatre
Date: Sat May 27 15:57:44 2006
New Revision: 409894

URL: http://svn.apache.org/viewvc?rev=409894&view=rev
Log:
Fix for issue SHALE-181 reported by "ÁÖ Ã÷ aftermath_lin2@hotmail.com".

Added:
    struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java   (with props)
Modified:
    struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayTemplateParser.java
    struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
    struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/builder/VerbatimBuilder.java

Modified: struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayTemplateParser.java
URL: http://svn.apache.org/viewvc/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayTemplateParser.java?rev=409894&r1=409893&r2=409894&view=diff
==============================================================================
--- struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayTemplateParser.java (original)
+++ struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayTemplateParser.java Sat May 27 15:57:44 2006
@@ -29,6 +29,7 @@
 import org.apache.shale.clay.config.beans.ComponentConfigBean;
 import org.apache.shale.clay.config.beans.ConfigBean;
 import org.apache.shale.clay.config.beans.ElementBean;
+import org.apache.shale.clay.config.beans.TemplateConfigBean;
 import org.apache.shale.clay.parser.Node;
 import org.apache.shale.clay.parser.Parser;
 import org.apache.shale.clay.parser.builder.Builder;
@@ -142,6 +143,11 @@
             //verify there is not a duplicate component id within a naming 
             //container.
             config.checkTree(root);
+            
+            //compress the tree merging adjacent verbatim nodes
+            if (config instanceof TemplateConfigBean)
+              ((TemplateConfigBean) config).optimizeTree(root);
+            
             
             return root;
     }

Modified: struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
URL: http://svn.apache.org/viewvc/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java?rev=409894&r1=409893&r2=409894&view=diff
==============================================================================
--- struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java (original)
+++ struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java Sat May 27 15:57:44 2006
@@ -18,6 +18,7 @@
 
 package org.apache.shale.clay.config.beans;
 
+import java.util.BitSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;
@@ -218,5 +219,126 @@
         return b;
     }
  
+   
+    /**
+     * <p>Determines if the <code>node</code> is a transient 
+     * <code>outputText</code> (<strong>verbatim</strong>) component.</p>
+     */
+    private boolean isVerbatim(ComponentBean node) {
+
+        AttributeBean attr = null;
+        if (node.getJsfid().equals("verbatim") 
+             && node.getComponentType().equals("javax.faces.HtmlOutputText")) {
+            
+            if ((attr = node.getAttribute("isTransient")) != null) {
+                if (attr.getValue() != null && attr.getValue().length() > 0) {
+                    return (Character.toLowerCase(attr.getValue().charAt(0)) == 't');
+                }
+            }
+        }
+
+        return false;
+    }
+    
+    
+    /**
+     * <p>Recursively walks down the graph of meta-data {@link ComponentBean}'s
+     * looking at the children of the <code>root</code>.  Adjacent
+     * children that are both <code>verbatim</code> component 
+     * definitions are merged.  If there is only one child and
+     * the child and root nodes are both <code>verbatim</code>
+     * definitions, the child is merged up to the root.</p>
+     */
+    public void optimizeTree(ComponentBean root) {
+        
+        // children is a TreeSet that is returned as a Collection.
+        int size = root.getChildren().size();
+        ComponentBean[] children = new ComponentBean[size];
+        BitSet verbatimSet = new BitSet(size);
+        verbatimSet.clear(0, size);
+        
+        StringBuffer buff = new StringBuffer();
+        
+        int i = 0;
+        Iterator ci = root.getChildrenIterator();
+        while (ci.hasNext()) {     
+            children[i] = (ComponentBean) ci.next();
+            if (isVerbatim(children[i])) {
+                
+                verbatimSet.set(i);
+            } 
+            
+            if (children[i].getChildren().size() > 0) {
+                optimizeTree(children[i]);    // merge children for the top down 
+                // starting a the botton of the tree.
+            }
+            
+            i++;
+        }
+        
+        int s = -1;
+        while ((s = verbatimSet.nextSetBit(++s)) > -1) {
+            
+            merge: for (int j = s + 1; j < children.length; j++) {
+                if (verbatimSet.get(j)) {
+                    buff.setLength(0);
+                    
+                    // grap the value attribute of the first one in the stack
+                    // and concat to a buffer
+                    AttributeBean attrTop = null;
+                    if (((attrTop = children[s].getAttribute("value")) != null)) {
+                        if (attrTop.getValue() != null)
+                            buff.append(attrTop.getValue());
+                    } else
+                        break merge;   // a verbatim without a value should never happen
+                    
+                    AttributeBean attrNext = null;  // the next in sequence to be merged
+                    if (((attrNext = children[j].getAttribute("value")) != null)) {
+                        if (attrNext.getValue() != null)
+                            buff.append(attrNext.getValue());
+                    } else
+                        continue merge;   // a verbatim without a value should never happen
+                    
+                    // merge node values
+                    attrTop.setValue(buff.toString());
+                    root.getChildren().remove(children[j]); // delete the node after merge from the parent 
+                    
+                } else {
+                    // the verbatims are not in sequence (true, false, true)
+                    s = j;
+                    break merge;
+                }
+            }
+        
+        
+        }
+               
+        // if the root is a verbatim and the only child is a verbatim
+        // merge up to the root
+        if (isVerbatim(root) && root.getChildren().size() == 1
+                && isVerbatim(children[0])) {
+            
+            buff.setLength(0);
+            
+            // grap the value attribute of the first one in the stack
+            // and concat to a buffer
+            AttributeBean attrTop = null;
+            if (((attrTop = root.getAttribute("value")) != null)) {
+                if (attrTop.getValue() != null)
+                    buff.append(attrTop.getValue());
+                
+                AttributeBean attrNext = null;  // the next in sequence to be merged
+                if (((attrNext = children[0].getAttribute("value")) != null)) {
+                    if (attrNext.getValue() != null)
+                        buff.append(attrNext.getValue());
+                } 
+                // merge node values
+                attrTop.setValue(buff.toString());
+                root.getChildren().clear(); // delete the node after merge from the parent 
+            }
+        }
+        
+        
+    }
     
 }

Modified: struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/builder/VerbatimBuilder.java
URL: http://svn.apache.org/viewvc/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/builder/VerbatimBuilder.java?rev=409894&r1=409893&r2=409894&view=diff
==============================================================================
--- struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/builder/VerbatimBuilder.java (original)
+++ struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/builder/VerbatimBuilder.java Sat May 27 15:57:44 2006
@@ -52,7 +52,7 @@
      * </p>
      */    
     protected String getJsfid(Node node) {
-        return "outputText";
+        return "verbatim";
     }
  
     /**

Added: struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java
URL: http://svn.apache.org/viewvc/struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java?rev=409894&view=auto
==============================================================================
--- struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java (added)
+++ struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java Sat May 27 15:57:44 2006
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.clay.config;
+
+import java.util.Iterator;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.shale.clay.config.beans.AttributeBean;
+import org.apache.shale.clay.config.beans.ComponentBean;
+import org.apache.shale.clay.config.beans.ElementBean;
+import org.apache.shale.clay.config.beans.TemplateConfigBean;
+
+// tests squeezing the component tree
+public class OptimizeTreeTestCase extends AbstractTestCaseConfig {
+
+    // Construct a new instance of this test case.
+    public OptimizeTreeTestCase(String name) {
+        super(name);
+    }
+
+    // Return the tests included in this test case.
+    public static Test suite() {
+
+        return (new TestSuite(OptimizeTreeTestCase.class));
+
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    private ComponentBean createVerbatim(Class classz, String value)
+            throws InstantiationException, IllegalAccessException {
+
+        ComponentBean target = (ComponentBean) classz.newInstance();
+        target.setJsfid("verbatim");
+        target.setComponentType("javax.faces.HtmlOutputText");
+
+        AttributeBean attr = new AttributeBean();
+        attr.setBindingType(AttributeBean.BINDING_TYPE_VALUE);
+        attr.setName("value");
+        attr.setValue(value);
+        target.addAttribute(attr);
+
+        attr = new AttributeBean();
+        attr.setBindingType(AttributeBean.BINDING_TYPE_NONE);
+        attr.setName("escape");
+        attr.setValue(Boolean.FALSE.toString());
+        target.addAttribute(attr);
+
+        attr = new AttributeBean();
+        attr.setBindingType(AttributeBean.BINDING_TYPE_NONE);
+        attr.setName("isTransient");
+        attr.setValue(Boolean.TRUE.toString());
+        target.addAttribute(attr);
+
+        return target;
+    }
+
+    public void testRollup() throws Exception {
+
+        ComponentBean root = createVerbatim(ComponentBean.class, "0");
+        for (int i = 1; i < 10; i++) {
+            ElementBean child = (ElementBean) createVerbatim(ElementBean.class,
+                    String.valueOf(i));
+            child.setRenderId(i);
+            root.addChild(child);
+        }
+
+        ((TemplateConfigBean) htmlTemplateConfigBean).optimizeTree(root);
+
+        assertEquals("#Children", 0, root.getChildren().size());
+
+        AttributeBean attr = root.getAttribute("value");
+        assertNotNull(attr);
+
+        assertEquals("root value", "0123456789", attr.getValue());
+
+    }
+
+    public void testRollupNested() throws Exception {
+
+        // root 0
+        // + 1
+        // + 2
+        // + 3
+        // + 4
+        //   + 5
+        //   + 6
+        //   + 7
+        //   + 8
+        //   + 9
+        ComponentBean root = createVerbatim(ComponentBean.class, "0");
+        ElementBean lastChild = null;
+        for (int i = 1; i < 5; i++) {
+            lastChild = (ElementBean) createVerbatim(ElementBean.class, String
+                    .valueOf(i));
+            lastChild.setRenderId(i);
+            root.addChild(lastChild);
+        }
+
+        for (int i = 5; i < 10; i++) {
+            ElementBean child = (ElementBean) createVerbatim(ElementBean.class,
+                    String.valueOf(i));
+            child.setRenderId(i);
+            lastChild.addChild(child);
+        }
+
+        ((TemplateConfigBean) htmlTemplateConfigBean).optimizeTree(root);
+
+        assertEquals("#Children", 0, root.getChildren().size());
+
+        AttributeBean attr = root.getAttribute("value");
+        assertNotNull(attr);
+
+        assertEquals("root value", "0123456789", attr.getValue());
+
+    }
+
+    public void testInterwoven() throws Exception {
+
+        // 0
+        // +1
+        // +2
+        // +3 not verbatim
+        // +4
+        // +5 not verbatim
+        // +6
+        // +7 not verbatim
+        // +8
+        // +9
+
+        AttributeBean attr = null;
+        ElementBean child = null;
+        ComponentBean root = createVerbatim(ComponentBean.class, "0");
+        // root is not a verbatim
+        root.setJsfid("outputText");
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "1");
+        child.setRenderId(1);
+        root.addChild(child);
+        
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "2");
+        child.setRenderId(2);
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "3");
+        child.setRenderId(3);
+        // root is not a verbatim
+        child.setJsfid("outputText");
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "4");
+        child.setRenderId(4);
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "5");
+        child.setRenderId(5);
+        // root is not a verbatim
+        child.setJsfid("outputText");
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "6");
+        child.setRenderId(6);
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "7");
+        child.setRenderId(7);
+        // root is not a verbatim
+        child.setJsfid("outputText");
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "8");
+        child.setRenderId(8);
+        root.addChild(child);
+
+        child = (ElementBean) createVerbatim(ElementBean.class, "9");
+        child.setRenderId(9);
+        root.addChild(child);
+
+        ((TemplateConfigBean) htmlTemplateConfigBean).optimizeTree(root);
+
+        assertEquals("#Children", 7, root.getChildren().size());
+
+        Iterator ci = root.getChildren().iterator();
+        int i = 0;
+        while (ci.hasNext()) {
+            child = (ElementBean) ci.next();
+
+            switch (++i) {
+            case 1: {
+                // first two nodes merged
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "12", attr.getValue());
+                break;
+            }
+            case 2: {
+                // non-verbatim
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "3", attr.getValue());
+                break;
+            }
+            case 3: {
+                // verbatim non-adjacent
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "4", attr.getValue());
+                break;
+            }
+            case 4: {
+                // non-verbatim
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "5", attr.getValue());
+                break;
+            }
+            case 5: {
+                // verbatim non-adjacent
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "6", attr.getValue());
+                break;
+            }
+            case 6: {
+                // non-verbatim
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "7", attr.getValue());
+                break;
+            }
+            case 7: {
+                // first two nodes merged
+                attr = child.getAttribute("value");
+                assertNotNull(attr);
+                assertEquals("root value", "89", attr.getValue());
+                break;
+            }
+            
+            };
+        }
+
+    }
+
+}

Propchange: struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/OptimizeTreeTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL