You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2007/02/15 16:08:55 UTC

svn commit: r507952 - in /myfaces/core/trunk/api/src: main/java/javax/faces/component/ test/java/javax/faces/component/

Author: mmarinschek
Date: Thu Feb 15 07:08:53 2007
New Revision: 507952

URL: http://svn.apache.org/viewvc?view=rev&rev=507952
Log:
MYFACES-1535: findComponent slow for a high amount of calls

Modified:
    myfaces/core/trunk/api/src/main/java/javax/faces/component/UIComponentBase.java
    myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentChildrenList.java
    myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentUtils.java
    myfaces/core/trunk/api/src/test/java/javax/faces/component/UIComponentBaseTest.java

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIComponentBase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UIComponentBase.java?view=diff&rev=507952&r1=507951&r2=507952
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UIComponentBase.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UIComponentBase.java Thu Feb 15 07:08:53 2007
@@ -216,7 +216,7 @@
             idWasNull = true;
         }
 
-        UIComponent namingContainer = _ComponentUtils.findParentNamingContainer(this, false);
+        UIComponent namingContainer = findParentNamingContainer(this, false);
         if (namingContainer != null)
         {
             _clientId = namingContainer.getClientId(context) + NamingContainer.SEPARATOR_CHAR + id;
@@ -277,6 +277,16 @@
         isIdValid(id);
         _id = id;
         _clientId = null;
+
+        UIComponent parent = getParent();
+
+        if(parent != null) {
+            List li = getParent().getChildren();
+
+            if(li instanceof _ComponentChildrenList) {
+                ((_ComponentChildrenList) li).updateId(_id,this);
+            }
+        }
     }
 
     public UIComponent getParent()
@@ -393,7 +403,7 @@
         UIComponent findBase;
         if (expr.charAt(0) == NamingContainer.SEPARATOR_CHAR)
         {
-            findBase = _ComponentUtils.getRootComponent(this);
+            findBase = getRootComponent(this);
             expr = expr.substring(1);
         }
         else
@@ -404,19 +414,19 @@
             }
             else
             {
-                findBase = _ComponentUtils.findParentNamingContainer(this, true /* root if not found */);
+                findBase = findParentNamingContainer(this, true /* root if not found */);
             }
         }
 
         int separator = expr.indexOf(NamingContainer.SEPARATOR_CHAR);
         if (separator == -1)
         {
-            return _ComponentUtils.findComponent(findBase, expr);
+            return findComponent(findBase, expr);
         }
         else
         {
             String id = expr.substring(0, separator);
-            findBase = _ComponentUtils.findComponent(findBase, id);
+            findBase = findComponent(findBase, id);
             if (findBase == null)
             {
                 return null;
@@ -429,6 +439,145 @@
                 return findBase.findComponent(expr.substring(separator + 1));
             }
         }
+    }
+
+    static UIComponent findParentNamingContainer(UIComponent component,
+                                                 boolean returnRootIfNotFound)
+    {
+        UIComponent parent = component.getParent();
+        if (returnRootIfNotFound && parent == null)
+        {
+            return component;
+        }
+        while (parent != null)
+        {
+            if (parent instanceof NamingContainer) return parent;
+            if (returnRootIfNotFound)
+            {
+                UIComponent nextParent = parent.getParent();
+                if (nextParent == null)
+                {
+                    return parent;  //Root
+                }
+                parent = nextParent;
+            }
+            else
+            {
+                parent = parent.getParent();
+            }
+        }
+        return null;
+    }
+
+    static UIComponent getRootComponent(UIComponent component)
+    {
+        UIComponent parent;
+        for(;;)
+        {
+            parent = component.getParent();
+            if (parent == null) return component;
+            component = parent;
+        }
+    }
+
+    /**
+     * Find the component with the specified id starting from the specified
+     * component.
+     * <p>
+     * Param id must not contain any NamingContainer.SEPARATOR_CHAR characters
+     * (ie ":"). This method explicitly does <i>not</i> search into any
+     * child naming container components; this is expected to be handled
+     * by the caller of this method.
+     * <p>
+     * For an implementation of findComponent which does descend into
+     * child naming components, see org.apache.myfaces.custom.util.ComponentUtils.
+     *
+     * @return findBase, a descendant of findBase, or null.
+     */
+    private UIComponent findComponent(UIComponent findBase, String id)
+    {
+        if (idsAreEqual(id, findBase)){
+            return findBase;
+        }
+
+        /*UIComponent comp = findComponentCached(id, findBase);
+
+        if(comp != null)
+            return comp;*/     
+
+        return findComponentNormal(id, findBase);
+    }
+
+    private UIComponent findComponentCached(String id, UIComponent findBase) {
+
+        if(!(findBase.getChildren() instanceof _ComponentChildrenList)) {
+            return null;
+        }
+
+        _ComponentChildrenList li = (_ComponentChildrenList) findBase.getChildren();
+
+        UIComponent comp = li.get(id);
+
+        if(comp != null)
+            return comp;
+
+        for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
+        {
+            UIComponent childOrFacet = (UIComponent)it.next();
+            UIComponent find = findComponentCached(id,childOrFacet);
+            if (find != null) return find;
+        }
+
+        return null;
+    }
+
+    private UIComponent findComponentNormal(String id, UIComponent findBase) {
+        if (idsAreEqual(id, findBase))
+        {
+            return findBase;
+        }
+
+        for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
+        {
+            UIComponent childOrFacet = (UIComponent)it.next();
+            UIComponent find = findComponentNormal(id, childOrFacet);
+            if (find != null) return find;
+        }
+
+        return null;
+    }
+
+    /*
+     * Return true if the specified component matches the provided id.
+     * This needs some quirks to handle components whose id value gets
+     * dynamically "tweaked", eg a UIData component whose id gets
+     * the current row index appended to it.
+     */
+    private boolean idsAreEqual(String id, UIComponent cmp)
+    {
+        if(id.equals(cmp.getId()))
+            return true;
+
+        if(cmp instanceof UIData)
+        {
+            UIData uiData = ((UIData) cmp);
+
+            if(uiData.getRowIndex()==-1)
+            {
+                return dynamicIdIsEqual(id,cmp.getId());
+            }
+            else
+            {
+                return id.equals(cmp.getId()+NamingContainer.SEPARATOR_CHAR+uiData.getRowIndex());
+            }
+        }
+
+        return false;
+    }
+
+    private boolean dynamicIdIsEqual(String dynamicId, String id)
+    {
+        return dynamicId.matches(id+":[0-9]*");
     }
 
 

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentChildrenList.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentChildrenList.java?view=diff&rev=507952&r1=507951&r2=507952
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentChildrenList.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentChildrenList.java Thu Feb 15 07:08:53 2007
@@ -19,9 +19,7 @@
 package javax.faces.component;
 
 import java.io.Serializable;
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 /**
  * @author Manfred Geiler (latest modification by $Author$)
@@ -34,11 +32,16 @@
 	private static final long serialVersionUID = -6775078929331154224L;
 	private UIComponent _component;
     private List _list = new ArrayList();
+    private Map _idIndexedMap = new HashMap();
 
     _ComponentChildrenList(UIComponent component)
     {
         _component = component;
     }
+    
+    public UIComponent get(String id) {
+       return (UIComponent) _idIndexedMap.get(id);
+    }
 
     public Object get(int index)
     {
@@ -55,7 +58,7 @@
         checkValue(value);
         setNewParent((UIComponent)value);
         UIComponent child = (UIComponent) _list.set(index, value);
-        if (child != null) child.setParent(null);
+        resetParent(child);
         return child;
     }
 
@@ -76,7 +79,7 @@
     public Object remove(int index)
     {
         UIComponent child = (UIComponent) _list.remove(index);
-        if (child != null) child.setParent(null);
+        resetParent(child);
         return child;
     }
 
@@ -89,6 +92,13 @@
             oldParent.getChildren().remove(child);
         }
         child.setParent(_component);
+        _idIndexedMap.put(child.getId(),child);
+    }
+
+    private void resetParent(UIComponent child) {
+        if (child != null)
+                child.setParent(null);
+        _idIndexedMap.remove(child.getId());
     }
 
     private void checkValue(Object value)
@@ -97,4 +107,8 @@
         if (!(value instanceof UIComponent)) throw new ClassCastException("value is not a UIComponent");
     }
 
+    public void updateId(String oldId, UIComponent component) {
+        _idIndexedMap.remove(oldId);
+        _idIndexedMap.put(component.getId(), component);
+    }
 }

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentUtils.java?view=diff&rev=507952&r1=507951&r2=507952
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentUtils.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_ComponentUtils.java Thu Feb 15 07:08:53 2007
@@ -25,10 +25,9 @@
 import javax.faces.el.ValueBinding;
 import javax.faces.validator.Validator;
 import javax.faces.validator.ValidatorException;
-import java.util.Iterator;
 
 /**
- * A collection of static helper methods for locating UIComponents.
+ * A collection of static helper methods for component-related issues.
  * 
  * @author Manfred Geiler (latest modification by $Author$)
  * @version $Revision$ $Date$
@@ -36,117 +35,6 @@
 class _ComponentUtils
 {
     private _ComponentUtils() {}
-
-    static UIComponent findParentNamingContainer(UIComponent component,
-                                                 boolean returnRootIfNotFound)
-    {
-        UIComponent parent = component.getParent();
-        if (returnRootIfNotFound && parent == null)
-        {
-            return component;
-        }
-        while (parent != null)
-        {
-            if (parent instanceof NamingContainer) return parent;
-            if (returnRootIfNotFound)
-            {
-                UIComponent nextParent = parent.getParent();
-                if (nextParent == null)
-                {
-                    return parent;  //Root
-                }
-                parent = nextParent;
-            }
-            else
-            {
-                parent = parent.getParent();
-            }
-        }
-        return null;
-    }
-
-    static UIComponent getRootComponent(UIComponent component)
-    {
-        UIComponent parent;
-        for(;;)
-        {
-            parent = component.getParent();
-            if (parent == null) return component;
-            component = parent;
-        }
-    }
-
-    /**
-     * Find the component with the specified id starting from the specified
-     * component.
-     * <p>
-     * Param id must not contain any NamingContainer.SEPARATOR_CHAR characters
-     * (ie ":"). This method explicitly does <i>not</i> search into any
-     * child naming container components; this is expected to be handled
-     * by the caller of this method.
-     * <p>
-     * For an implementation of findComponent which does descend into
-     * child naming components, see org.apache.myfaces.custom.util.ComponentUtils.
-     * 
-     * @return findBase, a descendant of findBase, or null.
-     */
-    static UIComponent findComponent(UIComponent findBase, String id)
-    {
-        if (idsAreEqual(id,findBase))
-        {
-            return findBase;
-        }
-
-        for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
-        {
-            UIComponent childOrFacet = (UIComponent)it.next();
-            if (!(childOrFacet instanceof NamingContainer))
-            {
-                UIComponent find = findComponent(childOrFacet, id);
-                if (find != null) return find;
-            }
-            else if (idsAreEqual(id,childOrFacet))
-            {
-                return childOrFacet;
-            }
-        }
-
-        return null;
-    }
-
-    /*
-     * Return true if the specified component matches the provided id.
-     * This needs some quirks to handle components whose id value gets
-     * dynamically "tweaked", eg a UIData component whose id gets
-     * the current row index appended to it.
-     */
-    private static boolean idsAreEqual(String id, UIComponent cmp)
-    {
-        if(id.equals(cmp.getId()))
-            return true;
-
-        if(cmp instanceof UIData)
-        {
-            UIData uiData = ((UIData) cmp);
-
-            if(uiData.getRowIndex()==-1)
-            {
-                return dynamicIdIsEqual(id,cmp.getId());
-            }
-            else
-            {
-                return id.equals(cmp.getId()+NamingContainer.SEPARATOR_CHAR+uiData.getRowIndex());
-            }
-        }
-
-        return false;
-    }
-
-    private static boolean dynamicIdIsEqual(String dynamicId, String id)
-    {
-        return dynamicId.matches(id+":[0-9]*");
-    }
-
 
     static void callValidators(FacesContext context, UIInput input, Object convertedValue)
     {

Modified: myfaces/core/trunk/api/src/test/java/javax/faces/component/UIComponentBaseTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/test/java/javax/faces/component/UIComponentBaseTest.java?view=diff&rev=507952&r1=507951&r2=507952
==============================================================================
--- myfaces/core/trunk/api/src/test/java/javax/faces/component/UIComponentBaseTest.java (original)
+++ myfaces/core/trunk/api/src/test/java/javax/faces/component/UIComponentBaseTest.java Thu Feb 15 07:08:53 2007
@@ -22,6 +22,7 @@
 import javax.faces.el.ValueBinding;
 
 import junit.framework.Test;
+import junit.framework.TestSuite;
 
 import org.apache.shale.test.base.AbstractJsfTestCase;
 import org.apache.shale.test.mock.MockRenderKitFactory;
@@ -39,7 +40,9 @@
 	}
 
 	public static Test suite() {
-		return null; // keep this method or maven won't run it
+        TestSuite suite = new TestSuite();
+        suite.addTestSuite(UIComponentBaseTest.class);
+        return suite;        
 	}
 
 	public void setUp() {
@@ -130,7 +133,7 @@
         
 		String str = input.getClientId(facesContext);
 
-		assertEquals(str, "data:input");
+		assertEquals(str, "data:input99");
 
 		UIData uiData = (UIData) input.getParent().getParent();
 
@@ -150,10 +153,13 @@
 
 		uiData.getChildren().add(column);
 
-		UIInput input = new UIInput();
-		input.setId("input");
+        UIInput input = null;
 
-		column.getChildren().add(input);
+        for(int i=0; i<100; i++) {
+            input = new UIInput();
+            input.setId("input"+i);
+            column.getChildren().add(input);
+        }
 
 		viewRoot.getChildren().add(uiData);
 
@@ -202,15 +208,13 @@
 
 		UIInput input = createInputInTree();
 
-		UIComponent comp = input.findComponent(":data:input");
-
-		assertEquals(input, comp);
-
-		comp = input.findComponent("input");
-
-		assertEquals(input, comp);
-
-	}
+        for(int j=0; j<100; j++) {
+            UIComponent comp = input.findComponent(":data:input"+j);
+            assertEquals("input-ids are not equal","input"+j, comp.getId());
+            comp = input.findComponent("input"+j);
+            assertEquals("input-ids are not equal","input"+j, comp.getId());
+        }
+    }
 
 	/*
 	 * Test method for 'javax.faces.component.UIComponentBase.getFacets()'