Author: knopp
Date: Thu Oct 11 12:40:50 2007
New Revision: 583930

URL: http://svn.apache.org/viewvc?rev=583930&view=rev
Log:
WICKET-1060

Added:
    
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java
   (with props)
    
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java
   (with props)
    
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java
   (with props)

Added: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java?rev=583930&view=auto
==============================================================================
--- 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java
 (added)
+++ 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java
 Thu Oct 11 12:40:50 2007
@@ -0,0 +1,328 @@
+/*
+ * 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.wicket;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.wicket.util.string.AppendingStringBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Represents a "dehydrated" component state keeping only the minimum 
information needed to
+ * reconstruct the component. That includes component id, [EMAIL PROTECTED] 
IComponentSource} and componentInfo
+ * string. The string contains generated <code>markupID</code>s and 
<code>markupIndex</code>es
+ * of the component and all it's children. Those are wicket internal variables 
and it's up to wicket
+ * (not [EMAIL PROTECTED] IComponentSource} implementation to reconstruct that 
transparently for the user.
+ * These information are encoded as one string to minimize object overhead.
+ */
+abstract class ComponentSourceEntry implements Serializable
+{
+       private static final long serialVersionUID = 1L;
+
+       final String id;
+       private final IComponentSource componentSource;
+       private final String componentInfo;
+
+       /**
+        * Checks if the component ID or markup ID doesn't contain invalid 
characters. This might be a
+        * little more strict that default wicket rules, but it is necessary 
for the componentInfo
+        * string
+        * 
+        * @param name
+        * @param id
+        */
+       private final void checkId(String name, String id)
+       {
+               if (id.indexOf('(') != -1 || id.indexOf('(') != -1 || 
id.indexOf(' ') != -1 ||
+                               id.indexOf(',') != -1)
+               {
+                       throw new IllegalStateException(name + "'" + id +
+                                       "' is not valid, it may not contain any 
of the ' ', '(', ')', ',' characters");
+               }
+       }
+
+       /**
+        * Appends component state to info string
+        * 
+        * @param buffer
+        * @param component
+        */
+       private final void appendComponent(AppendingStringBuffer buffer, 
Component component)
+       {
+               checkId("Component id", component.getId());
+               buffer.append(component.getId());
+               buffer.append(' ');
+               if (component.hasMarkupIdMetaData())
+               {
+
+                       checkId("Component markup id", component.getMarkupId());
+                       // if the markup id starts with component id, append 
only the difference prefixed by '*'
+                       if 
(component.getMarkupId().startsWith(component.getId()))
+                       {
+                               buffer.append('*');
+                               
buffer.append(component.getMarkupId().substring(component.getId().length()));
+                       }
+                       else
+                       {
+                               buffer.append(component.getMarkupId());
+                       }
+                       buffer.append(' ');
+               }
+               buffer.append(component.markupIndex);
+
+               if (component instanceof MarkupContainer &&
+                               
((MarkupContainer)component).iterator().hasNext())
+               {
+                       buffer.append('(');
+
+                       Iterator i = ((MarkupContainer)component).iterator();
+                       while (i.hasNext())
+                       {
+                               Component child = (Component)i.next();
+                               appendComponent(buffer, child);
+                               if (i.hasNext())
+                               {
+                                       buffer.append(',');
+                               }
+                       }
+
+                       buffer.append(')');
+               }
+       }
+
+       /**
+        * Creates a ComponentSourceEntry instance
+        * 
+        * @param container
+        * @param component
+        * @param componentSource
+        */
+       ComponentSourceEntry(MarkupContainer container, Component component,
+                       IComponentSource componentSource)
+       {
+               id = component.getId();
+
+               this.componentSource = componentSource;
+               AppendingStringBuffer buffer = new AppendingStringBuffer();
+               appendComponent(buffer, component);
+               componentInfo = buffer.toString();
+
+               System.out.println("Info: " + componentInfo);
+       }
+
+       /**
+        * The subclass of this method calls private method on [EMAIL 
PROTECTED] MarkupContainer}, so it needs to
+        * be implemented by a markup container inner class
+        * 
+        * @param parent
+        * @param index
+        * @param child
+        */
+       protected abstract void setChild(MarkupContainer parent, int index, 
Component child);
+
+       /**
+        * Reconstructs the component
+        * 
+        * @param parent
+        *            parent of the component
+        * @param index
+        *            position in parent's children
+        * @return
+        */
+       Component reconstruct(MarkupContainer parent, int index)
+       {
+               Component component = componentSource.restoreComponent(id);
+
+               if (parent != null)
+               {
+                       component.setParent(parent);
+               }
+
+               component.beforeRender();
+
+               parseComponentInfo(parent, componentInfo, component);
+
+               return component;
+       };
+
+       /**
+        * Returns the first part of string that belongs to a single component
+        * 
+        * @param string
+        * @return
+        */
+       private static String getComponentSubString(String string)
+       {
+               int len = string.length();
+
+               int i = string.indexOf(',');
+               if (i != -1 && i < len)
+               {
+                       len = i;
+               }
+
+               i = string.indexOf(')');
+               if (i != -1 && i < len)
+               {
+                       len = i;
+               }
+
+               i = string.substring(0, len).indexOf('(');
+               if (i != -1 && i < len)
+               {
+                       len = i;
+               }
+
+               return string.substring(0, len);
+       }
+
+       /**
+        * Parses the component info substring and applies it to component with 
id specified in string
+        * that belongs to 'parent'. If the component is a MarkupContainer, 
returns the component
+        * instance otherwise returns null
+        * 
+        * @param parent
+        * @param info
+        * @param component
+        * @return
+        */
+       private static MarkupContainer applyComponentInfo(MarkupContainer 
parent, String info,
+                       Component component)
+       {
+               if (parent == null)
+               {
+                       return null;
+               }
+
+               String parts[] = info.split(" ");
+
+               final String id = parts[0];
+               final String markupId;
+               final int markupIndex;
+
+               if (parts.length == 2)
+               {
+                       markupId = null;
+                       markupIndex = Integer.parseInt(parts[1]);
+               }
+               else if (parts.length == 3)
+               {
+                       if (parts[1] != null && parts[1].startsWith("*"))
+                       {
+                               markupId = id + parts[1].substring(1);
+                       }
+                       else
+                       {
+                               markupId = parts[1];
+                       }
+                       markupIndex = Integer.parseInt(parts[2]);
+               }
+               else
+               {
+                       throw new IllegalArgumentException("Malformed component 
info string '" + info + "'.");
+               }
+
+               if (component == null)
+               {
+                       component = parent.get(id);
+               }
+
+               if (component == null)
+               {
+                       logger
+                                       .warn("Couldn't find component with id 
'" + id +
+                                                       "'. This means that the 
component was not properly reconstructed from ComponentSource.");
+               }
+               else
+               {
+                       if (markupId != null)
+                       {
+                               component.setMarkupId(markupId);
+                       }
+                       component.markupIndex = markupIndex;
+               }
+               return component instanceof MarkupContainer ? 
(MarkupContainer)component : null;
+       }
+
+       /**
+        * Parses the info string and applies the stored attributes (markupId 
and markupIndex) to the
+        * components (recursively)
+        * 
+        * @param component
+        *            The initial (root) reconstructed component. We need to 
specify this component
+        *            explicitly, because the parent still contains 
ComponentSourceEntry (and not the
+        *            component itself) during reconstruction
+        * @param parent
+        * @param info
+        * @return
+        */
+       private static int parseComponentInfo(MarkupContainer parent, String 
info, Component component)
+       {
+               // find the first part for the component
+               final String substring = getComponentSubString(info);
+
+               // if it is followed by '(' it means there are children
+               int len = substring.length();
+               boolean hasChildren = false;
+               if (len < info.length() && info.charAt(len) == '(')
+               {
+                       hasChildren = true;
+                       ++len; // skip the '('
+               }
+
+               final MarkupContainer child = applyComponentInfo(parent, 
substring, component);
+
+               if (hasChildren)
+               {
+                       int i = 0;
+                       String children = info.substring(len); // part with 
children info
+
+
+                       while (i < children.length())
+                       {
+                               if (children.charAt(i) == ',')
+                               {
+                                       ++i; // skip the ',' that can be left 
there from previous child
+                               }
+
+                               i += parseComponentInfo(child, 
children.substring(i), null);
+
+                               // if the child is followed by a ')' it means 
there are no more children left
+                               if (children.charAt(i) == ')')
+                               {
+                                       ++i;
+                                       break;
+                               }
+                       }
+
+                       // advance by the length of component part and the 
length of children part
+                       return len + i;
+               }
+               else
+               {
+                       // advance by the length of component part
+                       return len;
+               }
+       }
+
+       private static final Logger logger = 
LoggerFactory.getLogger(ComponentSourceEntry.class);
+
+
+}
\ No newline at end of file

Propchange: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ComponentSourceEntry.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java?rev=583930&view=auto
==============================================================================
--- 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java
 (added)
+++ 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java
 Thu Oct 11 12:40:50 2007
@@ -0,0 +1,43 @@
+/*
+ * 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.wicket;
+
+import java.io.Serializable;
+
+/**
+ * Interface for objects that are capable of reconstructing a component. The 
component and it's
+ * children must be in the exact state as they were before "dehydrating".
+ * <p>
+ * This is useful for parts of page that are memory heavy but easy to 
reconstruct. Between requests
+ * only the [EMAIL PROTECTED] IComponentSource} instance is kept, rather then 
actual component. The component
+ * is then reconstructed on first access
+ * <p>
+ * This feature is experimental.
+ * 
+ * @author Matej Knopp
+ */
+public interface IComponentSource extends Serializable
+{
+       /**
+        * This method must reconstruct the component as it was before 
"dehydrating" it. Also it's
+        * children must be reconstructed
+        * 
+        * @param id
+        * @return
+        */
+       public Component restoreComponent(String id);
+}

Propchange: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java?rev=583930&view=auto
==============================================================================
--- 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java
 (added)
+++ 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java
 Thu Oct 11 12:40:50 2007
@@ -0,0 +1,36 @@
+/*
+ * 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.wicket;
+
+/**
+ * Components that implement this interface indicate that they are able to 
provide a
+ * [EMAIL PROTECTED] IComponentSource}, which represents object with minimal 
state that is able to reconstruct
+ * a component.
+ * <p>
+ * This feature is experimental.
+ * 
+ * @author Matej Knopp
+ */
+public interface IComponentSourceProvider
+{
+       /**
+        * Returns an [EMAIL PROTECTED] IComponentSource} instance
+        * 
+        * @return
+        */
+       public IComponentSource getComponentSource();
+}

Propchange: 
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/IComponentSourceProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to