Author: chris.laprun(a)jboss.com
Date: 2007-05-06 20:56:04 -0400 (Sun, 06 May 2007)
New Revision: 7209
Modified:
trunk/common/src/main/org/jboss/portal/common/util/MapAccessor.java
trunk/common/src/main/org/jboss/portal/common/util/TypedMap.java
trunk/common/src/main/org/jboss/portal/test/common/TypedMapTestCase.java
trunk/portlet/src/main/org/jboss/portal/portlet/PortletParameters.java
Log:
- MapAccessor.getMap now distinguishes between accessing the Map with an intent to modify
it or just read data off of it. This allows for lazy initialization.
Modified: trunk/common/src/main/org/jboss/portal/common/util/MapAccessor.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/util/MapAccessor.java 2007-05-07
00:49:23 UTC (rev 7208)
+++ trunk/common/src/main/org/jboss/portal/common/util/MapAccessor.java 2007-05-07
00:56:04 UTC (rev 7209)
@@ -35,7 +35,9 @@
/**
* Return the accessed map.
*
+ * @param requestWriteable whether or not the Map will be accessed for a write-type
(e.g., put, remove...) operation.
+ * This allows for lazy initialization via a create-on-write
mechanism.
* @return a non null map
*/
- Map getMap();
+ Map getMap(boolean requestWriteable);
}
Modified: trunk/common/src/main/org/jboss/portal/common/util/TypedMap.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/util/TypedMap.java 2007-05-07 00:49:23
UTC (rev 7208)
+++ trunk/common/src/main/org/jboss/portal/common/util/TypedMap.java 2007-05-07 00:56:04
UTC (rev 7209)
@@ -24,15 +24,15 @@
import org.jboss.portal.common.NotYetImplemented;
-import java.util.Map;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
-import java.util.HashMap;
/**
- * A decorator that enforce the map content to be checked against a type.
- * Null internal values are not supported.
+ * A decorator that enforce the map content to be checked against a type. Null internal
values are not supported.
*
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
* @version $Revision$
@@ -54,29 +54,24 @@
protected TypedMap(final Map delegate)
{
- accessor = new MapAccessor()
- {
- public Map getMap()
- {
- return delegate;
- }
- };
+ accessor = new LazyMapAccessor(delegate);
}
/**
* Return the map provided by the accessor.
*
+ * @param requestWriteable
* @return the delegate map
*/
- protected final Map getDelegate()
+ protected final Map getDelegate(boolean requestWriteable)
{
- return accessor.getMap();
+ return accessor.getMap(requestWriteable);
}
/**
* Override to check the validity of the key, the default implementation is an empty
method.
*
- * @throws ClassCastException if the class of the specified key prevents it from being
stored in this map
+ * @throws ClassCastException if the class of the specified key prevents it from
being stored in this map
* @throws IllegalArgumentException if some aspect of this key prevents it from being
stored in this map
*/
protected void assertKeyValidity(Object key) throws IllegalArgumentException,
ClassCastException
@@ -84,14 +79,13 @@
}
/**
- * Unwraps the key to the the internal key that will be stored in the map.
- * This method calls the <code>assertKeyValidity(Object key)</code> and
returns
- * the same key. It can be overriden to provide a customized key that will be used
- * instead of the external key.
+ * Unwraps the key to the the internal key that will be stored in the map. This method
calls the
+ * <code>assertKeyValidity(Object key)</code> and returns the same key. It
can be overriden to provide a customized
+ * key that will be used instead of the external key.
*
* @param key the key to unwrap
* @return the unwrapped key
- * @throws ClassCastException if the class of the specified key prevents it from being
stored in this map
+ * @throws ClassCastException if the class of the specified key prevents it from
being stored in this map
* @throws IllegalArgumentException if some aspect of this key prevents it from being
stored in this map
*/
protected Object getInternalKey(Object key) throws IllegalArgumentException,
ClassCastException
@@ -103,9 +97,8 @@
}
/**
- * Wrap the internal key into its external representation, by default returns the same
key.
- * It can be overriden to provide a customized key that will be used instead of the
internal
- * key.
+ * Wrap the internal key into its external representation, by default returns the same
key. It can be overriden to
+ * provide a customized key that will be used instead of the internal key.
*/
protected Object getExternalKey(Object key)
{
@@ -157,7 +150,7 @@
*
* @param value the value to unwrap
* @return the unwrapped value
- * @throws ClassCastException if the class of the specified value prevents it from
being stored in this map
+ * @throws ClassCastException if the class of the specified value prevents it
from being stored in this map
* @throws IllegalArgumentException if some aspect of this value prevents it from
being stored in this map
*/
protected Object getInternalValue(Object value) throws IllegalArgumentException,
ClassCastException
@@ -166,9 +159,9 @@
}
/**
- * Wrap the internal value into its external representation. The external
representation value should not be null.
- * If it is not possible to obtain an external value representation of the internal
value, then the the
- * null value should be returned from this method.
+ * Wrap the internal value into its external representation. The external
representation value should not be null. If
+ * it is not possible to obtain an external value representation of the internal
value, then the the null value
+ * should be returned from this method.
*
* @param value the param value which will not be null
* @return the external value
@@ -212,8 +205,8 @@
*
* @param internalValue the internal value
* @return the non null external value
- * @throws IllegalStateException if the internal value was null or some aspect
prevented it to be converted
- * to an external representation
+ * @throws IllegalStateException if the internal value was null or some aspect
prevented it to be converted to an
+ * external representation
*/
protected final Object wrapValue(Object internalValue) throws IllegalStateException
{
@@ -236,8 +229,8 @@
}
/**
- * Compare internal values, the default implementation delegates the operation to the
equals method
- * of the left argument.
+ * Compare internal values, the default implementation delegates the operation to the
equals method of the left
+ * argument.
*
* @param left
* @param right
@@ -250,29 +243,32 @@
public int size()
{
- return getDelegate().size();
+ return getDelegate(false).size();
}
public void clear()
{
- getDelegate().clear();
+ if (!isEmpty())
+ {
+ getDelegate(true).clear();
+ }
}
public boolean isEmpty()
{
- return getDelegate().isEmpty();
+ return getDelegate(false).isEmpty();
}
public boolean containsKey(Object key)
{
key = unwrapKey(key);
- return getDelegate().containsKey(key);
+ return getDelegate(false).containsKey(key);
}
public boolean containsValue(Object value)
{
value = unwrapValue(value);
- return getDelegate().containsValue(value);
+ return getDelegate(false).containsValue(value);
}
public Collection values()
@@ -283,7 +279,7 @@
public void putAll(Map t)
{
t = convert(t);
- getDelegate().putAll(t);
+ getDelegate(true).putAll(t);
}
public Set entrySet()
@@ -299,14 +295,20 @@
public Object get(Object key)
{
key = unwrapKey(key);
- Object value = getDelegate().get(key);
+ Object value = getDelegate(false).get(key);
return value == null ? null : wrapValue(value);
}
public Object remove(Object key)
{
key = unwrapKey(key);
- Object value = getDelegate().remove(key);
+
+ Object value = null;
+ if (!isEmpty())
+ {
+ value = getDelegate(true).remove(key);
+ }
+
return value == null ? null : wrapValue(value);
}
@@ -314,7 +316,7 @@
{
key = unwrapKey(key);
value = unwrapValue(value);
- value = getDelegate().put(key, value);
+ value = getDelegate(true).put(key, value);
return value == null ? null : wrapValue(value);
}
@@ -330,7 +332,7 @@
if (o instanceof Map)
{
Map that = (Map)o;
- Map delegate = getDelegate();
+ Map delegate = getDelegate(false);
// Must have same sizes
if (that.size() != delegate.size())
@@ -395,7 +397,7 @@
/**
* Replace the content with the new map which is validated before replacement.
- *
+ *
* @param t the replacement map
* @throws ClassCastException
* @throws NullPointerException
@@ -403,12 +405,15 @@
*/
public void replace(Map t) throws ClassCastException, NullPointerException,
IllegalArgumentException
{
- t = convert(t);
+ if (!t.isEmpty())
+ {
+ t = convert(t);
- //
- Map delegate = getDelegate();
- delegate.clear();
- delegate.putAll(t);
+ //
+ Map delegate = getDelegate(true);
+ delegate.clear();
+ delegate.putAll(t);
+ }
}
/**
@@ -420,7 +425,7 @@
*/
public void validate() throws ClassCastException, NullPointerException,
IllegalArgumentException
{
- for (Iterator i = getDelegate().entrySet().iterator(); i.hasNext();)
+ for (Iterator i = getDelegate(false).entrySet().iterator(); i.hasNext();)
{
Entry entry = (Entry)i.next();
wrapKey(entry.getKey());
@@ -428,9 +433,7 @@
}
}
- /**
- * Validate the map and unwrap it if necessary.
- */
+ /** Validate the map and unwrap it if necessary. */
protected final Map convert(Map t) throws IllegalArgumentException,
NullPointerException, ClassCastException
{
if (t == null)
@@ -450,13 +453,13 @@
public class ValueCollection implements Collection
{
-
+
/** . */
private final Collection delegate;
public ValueCollection()
{
- this.delegate = getDelegate().values();
+ this.delegate = getDelegate(false).values();
}
public int size()
@@ -562,7 +565,7 @@
public KeySet()
{
- this.delegate = getDelegate().keySet();
+ this.delegate = getDelegate(false).keySet();
}
public int size()
@@ -572,7 +575,10 @@
public void clear()
{
- delegate.clear();
+ if (!isEmpty())
+ {
+ delegate.clear();
+ }
}
public boolean isEmpty()
@@ -585,7 +591,7 @@
try
{
Object key = unwrapKey(o);
- return getDelegate().containsKey(key);
+ return getDelegate(false).containsKey(key);
}
catch (IllegalArgumentException e)
{
@@ -640,7 +646,7 @@
//
boolean changed = false;
- for (Iterator i = iterator();i.hasNext();)
+ for (Iterator i = iterator(); i.hasNext();)
{
Object key = i.next();
if (!c.contains(key))
@@ -700,7 +706,7 @@
public TypedEntrySet()
{
- this.delegate = getDelegate().entrySet();
+ this.delegate = getDelegate(false).entrySet();
}
public int size()
@@ -710,7 +716,10 @@
public void clear()
{
- delegate.clear();
+ if (!isEmpty())
+ {
+ delegate.clear();
+ }
}
public boolean isEmpty()
@@ -843,4 +852,32 @@
}
}
}
+
+ private static class LazyMapAccessor implements MapAccessor
+ {
+ private Map delegate;
+
+ public LazyMapAccessor(Map delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ public Map getMap(boolean requestWriteable)
+ {
+ // if the delegate is null, wait until we need to write to it to initialize it
+ if (delegate == null)
+ {
+ if (requestWriteable)
+ {
+ delegate = new HashMap();
+ }
+ else
+ {
+ return Collections.EMPTY_MAP;
+ }
+ }
+
+ return delegate;
+ }
+ }
}
Modified: trunk/common/src/main/org/jboss/portal/test/common/TypedMapTestCase.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/test/common/TypedMapTestCase.java 2007-05-07
00:49:23 UTC (rev 7208)
+++ trunk/common/src/main/org/jboss/portal/test/common/TypedMapTestCase.java 2007-05-07
00:56:04 UTC (rev 7209)
@@ -23,13 +23,12 @@
package org.jboss.portal.test.common;
import junit.framework.TestCase;
-import org.jboss.portal.common.util.TypedMap;
import org.jboss.portal.common.util.CollectionBuilder;
+import org.jboss.portal.common.util.TypedMap;
-import java.util.Map;
-import java.util.HashMap;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
/**
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
@@ -399,7 +398,7 @@
super(new HashMap());
//
- delegate = getDelegate();
+ delegate = getDelegate(false);
}
protected void assertKeyValidity(Object key) throws ClassCastException
Modified: trunk/portlet/src/main/org/jboss/portal/portlet/PortletParameters.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletParameters.java 2007-05-07
00:49:23 UTC (rev 7208)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/PortletParameters.java 2007-05-07
00:56:04 UTC (rev 7209)
@@ -99,7 +99,7 @@
}
// Merge or use appended values
- Map delegate = getDelegate();
+ Map delegate = getDelegate(true);
while (--index >= 0)
{
String appendedName = appendedNames[index];
@@ -123,7 +123,7 @@
public String toString()
{
StringBuffer buffer = new StringBuffer("Parameters[");
- Map delegate = getDelegate();
+ Map delegate = getDelegate(false);
for (Iterator i = delegate.entrySet().iterator(); i.hasNext();)
{
Map.Entry entry = (Map.Entry)i.next();
@@ -144,8 +144,8 @@
}
/**
- * Safely wrap the map as a portlet parameters object. If the map is already a portlet
parameter object,
- * just return that object otherwise return a wrapper around the map.
+ * Safely wrap the map as a portlet parameters object. If the map is already a portlet
parameter object, just return
+ * that object otherwise return a wrapper around the map.
*/
public static PortletParameters wrap(Map map)
{