Author: jcompagner
Date: Mon Mar  3 08:19:17 2008
New Revision: 633155

URL: http://svn.apache.org/viewvc?rev=633155&view=rev
Log:
added optimization for remove/add of childs. Now a quick custom list is being 
used that grows *2. 
But the slow part for large things is still the add that does a linear search 
to get to the right component(id) 

Modified:
    
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
    
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java

Modified: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java?rev=633155&r1=633154&r2=633155&view=diff
==============================================================================
--- 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
 (original)
+++ 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
 Mon Mar  3 08:19:17 2008
@@ -16,6 +16,7 @@
  */
 package org.apache.wicket;
 
+import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -469,6 +470,10 @@
                                sorted = new ArrayList(1);
                                sorted.add(children);
                        }
+                       else if (children instanceof ChildList)
+                       {
+                               sorted = new ArrayList((ChildList)children);
+                       }
                        else
                        {
                                sorted = Arrays.asList((Component[])children);
@@ -574,13 +579,17 @@
                        int size = children_size();
                        for (int i = 0; i < size; i++)
                        {
-                               // Get next child
-                               final Component child = children_get(i);
+                               Object childObject = children_get(i, false);
+                               if (childObject instanceof Component)
+                               {
+                                       // Get next child
+                                       final Component child = 
(Component)childObject;
 
-                               // Do not call remove() because the state 
change would than be
-                               // recorded twice.
-                               child.detachModel();
-                               child.setParent(null);
+                                       // Do not call remove() because the 
state change would than be
+                                       // recorded twice.
+                                       child.detachModel();
+                                       child.setParent(null);
+                               }
                        }
 
                        children = null;
@@ -917,23 +926,12 @@
                }
                else
                {
-                       // Get current list size
-                       final int size = children_size();
-
-                       // Create array that holds size + 1 elements
-                       final Object[] children = new Object[size + 1];
-
-                       // Loop through existing children copying them
-                       for (int i = 0; i < size; i++)
+                       if (!(children instanceof ChildList))
                        {
-                               children[i] = children_get(i, false);
+                               // Save new children
+                               children = new ChildList(children);
                        }
-
-                       // Add new child to the end
-                       children[size] = child;
-
-                       // Save new children
-                       this.children = children;
+                       ((ChildList)children).add(child);
                }
        }
 
@@ -966,25 +964,39 @@
        private final Object children_get(int index, boolean reconstruct)
        {
                Object component = null;
-               if (index == 0 && children != null && children instanceof 
Object[] == false)
+               if (children != null)
                {
-                       component = postprocess(children, reconstruct, this, 0);
-                       if (children != component)
+                       if (children instanceof Object[] == false && children 
instanceof ChildList == false)
                        {
-                               children = component;
+                               if (index != 0)
+                                       throw new 
ArrayIndexOutOfBoundsException("index " + index +
+                                               " is greater then 0");
+                               component = postprocess(children, reconstruct, 
this, 0);
+                               if (children != component)
+                               {
+                                       children = component;
+                               }
                        }
-               }
-               else
-               {
-                       // we have a list
-                       Object[] children = (Object[])this.children;
-                       component = postprocess(children[index], reconstruct, 
this, index);
-                       if (children[index] != component)
+                       else
                        {
-                               children[index] = component;
+                               Object[] children = null;
+                               if (this.children instanceof ChildList)
+                               {
+                                       // we have a list
+                                       children = 
((ChildList)this.children).childs;
+                               }
+                               else
+                               {
+                                       // we have a object array
+                                       children = (Object[])this.children;
+                               }
+                               component = postprocess(children[index], 
reconstruct, this, index);
+                               if (children[index] != component)
+                               {
+                                       children[index] = component;
+                               }
                        }
                }
-
                return component;
        }
 
@@ -1013,30 +1025,46 @@
 
        private final Component children_get(final String id)
        {
+               if (children == null)
+               {
+                       return null;
+               }
                Component component = null;
-               if (children != null && children instanceof Object[] == false 
&& getId(children).equals(id))
+               if (children instanceof Object[] == false && children 
instanceof List == false)
                {
-                       component = (Component)postprocess(children, true, 
this, 0);
-                       if (children != component)
+                       if (getId(children).equals(id))
                        {
-                               children = component;
+                               component = (Component)postprocess(children, 
true, this, 0);
+                               if (children != component)
+                               {
+                                       children = component;
+                               }
                        }
                }
-               else if (children instanceof Object[])
+               else
                {
-                       final Object[] children = (Object[])this.children;
+                       Object[] children = null;
+                       int size = 0;
+                       if (this.children instanceof ChildList)
+                       {
+                               children = ((ChildList)this.children).childs;
+                               size = ((ChildList)this.children).size;
+                       }
+                       else
                        {
-                               for (int i = 0; i < children.length; i++)
+                               children = (Object[])this.children;
+                               size = children.length;
+                       }
+                       for (int i = 0; i < size; i++)
+                       {
+                               if (getId(children[i]).equals(id))
                                {
-                                       if (getId(children[i]).equals(id))
+                                       component = 
(Component)postprocess(children[i], true, this, i);
+                                       if (children[i] != component)
                                        {
-                                               component = 
(Component)postprocess(children[i], true, this, i);
-                                               if (children[i] != component)
-                                               {
-                                                       children[i] = component;
-                                               }
-                                               break;
+                                               children[i] = component;
                                        }
+                                       break;
                                }
                        }
                }
@@ -1045,15 +1073,33 @@
 
        private final int children_indexOf(Component child)
        {
-               if (children != null && children instanceof Object[] == false &&
-                       getId(children).equals(child.getId()))
+               if (children == null)
                {
-                       return 0;
+                       return -1;
                }
-               else if (children instanceof Object[])
+               if (children instanceof Object[] == false && children 
instanceof ChildList == false)
                {
-                       final Object[] children = (Object[])this.children;
-                       for (int i = 0; i < children.length; i++)
+                       if (getId(children).equals(child.getId()))
+                       {
+                               return 0;
+                       }
+               }
+               else
+               {
+                       int size = 0;
+                       Object[] children;
+                       if (this.children instanceof Object[])
+                       {
+                               children = (Object[])this.children;
+                               size = children.length;
+                       }
+                       else
+                       {
+                               children = ((ChildList)this.children).childs;
+                               size = ((ChildList)this.children).size;
+                       }
+
+                       for (int i = 0; i < size; i++)
                        {
                                if (getId(children[i]).equals(child.getId()))
                                {
@@ -1076,6 +1122,9 @@
 
        private final Component children_remove(int index)
        {
+               if (children == null)
+                       return null;
+
                if (children instanceof Component || children instanceof 
ComponentSourceEntry)
                {
                        if (index == 0)
@@ -1091,35 +1140,34 @@
                }
                else
                {
-                       Object[] c = ((Object[])children);
-                       final Object removed = c[index];
-                       if (c.length == 2)
-                       {
-                               if (index == 0)
-                               {
-                                       children = c[1];
-                               }
-                               else if (index == 1)
-                               {
-                                       children = c[0];
-                               }
-                               else
-                               {
-                                       throw new IndexOutOfBoundsException();
-                               }
-                       }
-                       else
+                       if (children instanceof Object[])
                        {
-                               Object[] newChildren = new Object[c.length - 1];
-                               int j = 0;
-                               for (int i = 0; i < c.length; i++)
+                               Object[] c = ((Object[])children);
+                               final Object removed = c[index];
+                               if (c.length == 2)
                                {
-                                       if (i != index)
+                                       if (index == 0)
+                                       {
+                                               children = c[1];
+                                       }
+                                       else if (index == 1)
                                        {
-                                               newChildren[j++] = c[i];
+                                               children = c[0];
                                        }
+                                       else
+                                       {
+                                               throw new 
IndexOutOfBoundsException();
+                                       }
+                                       return (Component)postprocess(removed, 
true, null, -1);
                                }
-                               children = newChildren;
+                               children = new ChildList(children);
+                       }
+
+                       ChildList lst = (ChildList)children;
+                       Object removed = lst.remove(index);
+                       if (lst.size == 1)
+                       {
+                               children = lst.get(0);
                        }
                        return (Component)postprocess(removed, true, null, -1);
                }
@@ -1128,19 +1176,25 @@
        private final Object children_set(int index, Object child, boolean 
reconstruct)
        {
                Object replaced;
-               if (index < children_size())
+               if (index >= 0 && index < children_size())
                {
-                       if (children == null || children instanceof Component ||
-                               children instanceof ComponentSourceEntry)
+                       if (children instanceof Component || children 
instanceof ComponentSourceEntry)
                        {
                                replaced = children;
                                children = child;
                        }
                        else
                        {
-                               final Object[] children = 
(Object[])this.children;
-                               replaced = children[index];
-                               children[index] = child;
+                               if (children instanceof ChildList)
+                               {
+                                       replaced = 
((ChildList)children).set(index, child);
+                               }
+                               else
+                               {
+                                       final Object[] children = 
(Object[])this.children;
+                                       replaced = children[index];
+                                       children[index] = child;
+                               }
                        }
                }
                else
@@ -1167,6 +1221,10 @@
                        {
                                return 1;
                        }
+                       else if (children instanceof ChildList)
+                       {
+                               return ((ChildList)children).size;
+                       }
                        return ((Object[])children).length;
                }
        }
@@ -1465,6 +1523,13 @@
                                }
                        }
                }
+               if (children instanceof ChildList)
+               {
+                       ChildList lst = (ChildList)children;
+                       Object[] tmp = new Object[lst.size];
+                       System.arraycopy(lst.childs, 0, tmp, 0, lst.size);
+                       children = tmp;
+               }
        }
 
        void internalMarkRendering()
@@ -1569,5 +1634,100 @@
                                return IVisitor.CONTINUE_TRAVERSAL;
                        }
                });
+       }
+
+       private static class ChildList extends AbstractList
+       {
+               private int size;
+               private Object[] childs;
+
+               /**
+                * Construct.
+                * 
+                * @param children
+                */
+               public ChildList(Object children)
+               {
+                       if (children instanceof Object[])
+                       {
+                               childs = (Object[])children;
+                               size = childs.length;
+                       }
+                       else
+                       {
+                               childs = new Object[3];
+                               add(children);
+                       }
+               }
+
+               public Object get(int index)
+               {
+                       return childs[index];
+               }
+
+               public int size()
+               {
+                       return size;
+               }
+
+               public boolean add(Object o)
+               {
+                       ensureCapacity(size + 1);
+                       childs[size++] = o;
+                       return true;
+               }
+
+               public void add(int index, Object element)
+               {
+                       if (index > size || index < 0)
+                               throw new IndexOutOfBoundsException("Index: " + 
index + ", Size: " + size);
+
+                       ensureCapacity(size + 1);
+                       System.arraycopy(childs, index, childs, index + 1, size 
- index);
+                       childs[index] = element;
+                       size++;
+               }
+
+               public Object set(int index, Object element)
+               {
+                       if (index >= size)
+                               throw new IndexOutOfBoundsException("Index: " + 
index + ", Size: " + size);
+
+                       Object oldValue = childs[index];
+                       childs[index] = element;
+                       return oldValue;
+               }
+
+               public Object remove(int index)
+               {
+                       if (index >= size)
+                               throw new IndexOutOfBoundsException("Index: " + 
index + ", Size: " + size);
+
+                       Object oldValue = childs[index];
+
+                       int numMoved = size - index - 1;
+                       if (numMoved > 0)
+                               System.arraycopy(childs, index + 1, childs, 
index, numMoved);
+                       childs[--size] = null; // Let gc do its work
+
+                       return oldValue;
+               }
+
+               /**
+                * @param minCapacity
+                */
+               public void ensureCapacity(int minCapacity)
+               {
+                       int oldCapacity = childs.length;
+                       if (minCapacity > oldCapacity)
+                       {
+                               Object oldData[] = childs;
+                               int newCapacity = oldCapacity * 2;
+                               if (newCapacity < minCapacity)
+                                       newCapacity = minCapacity;
+                               childs = new Object[newCapacity];
+                               System.arraycopy(oldData, 0, childs, 0, size);
+                       }
+               }
        }
 }

Modified: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java?rev=633155&r1=633154&r2=633155&view=diff
==============================================================================
--- 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
 (original)
+++ 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
 Mon Mar  3 08:19:17 2008
@@ -141,7 +141,7 @@
                if (model == null)
                {
                        throw new IllegalArgumentException(
-                                       "Null models are not allowed. If you 
have no model, you may prefer a Loop instead");
+                               "Null models are not allowed. If you have no 
model, you may prefer a Loop instead");
                }
 
                // A reasonable default for viewSize can not be determined 
right now,
@@ -236,7 +236,7 @@
                if ((Integer.MAX_VALUE - size) < firstIndex)
                {
                        throw new IllegalStateException(
-                                       "firstIndex + size must be smaller than 
Integer.MAX_VALUE");
+                               "firstIndex + size must be smaller than 
Integer.MAX_VALUE");
                }
 
                return size;
@@ -549,14 +549,17 @@
                                removeAll();
                        }
 
+                       boolean hasChildren = size() != 0;
                        // Loop through the markup in this container for each 
item
                        for (int i = 0; i < size; i++)
                        {
                                // Get index
                                final int index = firstIndex + i;
 
-                               // If this component does not already exist, 
populate it
-                               ListItem item = 
(ListItem)get(Integer.toString(index));
+                               ListItem item = null;
+                               if (hasChildren)
+                                       // If this component does not already 
exist, populate it
+                                       item = 
(ListItem)get(Integer.toString(index));
                                if (item == null)
                                {
                                        // Create item for index


Reply via email to