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()'