You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2010/03/17 01:34:38 UTC

svn commit: r924074 [6/6] - in /wicket/trunk: testing/wicket-threadtest/src/main/java/org/apache/wicket/threadtest/ wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/data/table/filter/ wicket-guice/src/test/java/org/apac...

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IValueMap.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IValueMap.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IValueMap.java (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IValueMap.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,435 @@
+/*
+ * 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.util.value;
+
+import java.util.Map;
+
+import org.apache.wicket.util.string.StringValue;
+import org.apache.wicket.util.string.StringValueConversionException;
+import org.apache.wicket.util.time.Duration;
+import org.apache.wicket.util.time.Time;
+
+
+/**
+ * A <code>Map</code> interface that holds values, parses <code>String</code>s, and exposes a
+ * variety of convenience methods.
+ * 
+ * @author Johan Compagner
+ * @author Doug Donohoe
+ * @since 1.2.6
+ */
+public interface IValueMap extends Map<String, Object>
+{
+	/**
+	 * Retrieves a <code>boolean</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	boolean getBoolean(final String key) throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>double</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	double getDouble(final String key) throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>double</code> value by key, using a default value if not found.
+	 * 
+	 * @param key
+	 *            the key
+	 * @param defaultValue
+	 *            value to use if no value is in this <code>IValueMap</code>
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	double getDouble(final String key, final double defaultValue)
+		throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>Duration</code> by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>Duration</code> value
+	 * @throws StringValueConversionException
+	 */
+	Duration getDuration(final String key) throws StringValueConversionException;
+
+	/**
+	 * Retrieves an <code>int</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	int getInt(final String key) throws StringValueConversionException;
+
+	/**
+	 * Retrieves an <code>int</code> value by key, using a default value if not found.
+	 * 
+	 * @param key
+	 *            the key
+	 * @param defaultValue
+	 *            value to use if no value is in this <code>IValueMap</code>
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	int getInt(final String key, final int defaultValue) throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>long</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	long getLong(final String key) throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>long</code> value by key, using a default value if not found.
+	 * 
+	 * @param key
+	 *            the key
+	 * @param defaultValue
+	 *            value to use if no value in this <code>IValueMap</code>
+	 * @return the value
+	 * @throws StringValueConversionException
+	 */
+	long getLong(final String key, final long defaultValue) throws StringValueConversionException;
+
+	/**
+	 * Retrieves a <code>String</code> by key, using a default value if not found.
+	 * 
+	 * @param key
+	 *            the key
+	 * @param defaultValue
+	 *            default value to return if value is <code>null</code>
+	 * @return the <code>String</code>
+	 */
+	String getString(final String key, final String defaultValue);
+
+	/**
+	 * Retrieves a <code>String</code> by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>String</code>
+	 */
+	String getString(final String key);
+
+	/**
+	 * Retrieves a <code>CharSequence</code> by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>CharSequence</code>
+	 */
+	CharSequence getCharSequence(final String key);
+
+	/**
+	 * Retrieves a <code>String</code> array by key. If the value was a <code>String[]</code> it
+	 * will be returned directly. If it was a <code>String</code> it will be converted to a
+	 * <code>String</code> array of length one. If it was an array of another type, a
+	 * <code>String</code> array will be made and each element will be converted to a
+	 * <code>String</code>.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>String</code> array of that key
+	 */
+	String[] getStringArray(final String key);
+
+	/**
+	 * Retrieves a <code>StringValue</code> object by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>StringValue</code> object
+	 */
+	StringValue getStringValue(final String key);
+
+	/**
+	 * Retrieves a <code>Time</code> object by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the <code>Time</code> object
+	 * @throws StringValueConversionException
+	 */
+	Time getTime(final String key) throws StringValueConversionException;
+
+	/**
+	 * Returns whether or not this <code>IValueMap</code> is immutable.
+	 * 
+	 * @return whether or not this <code>IValueMap</code> is immutable
+	 */
+	boolean isImmutable();
+
+	/**
+	 * Makes this <code>IValueMap</code> immutable by changing the underlying map representation to
+	 * a <code>Collections.unmodifiableMap</code>. After calling this method, any attempt to modify
+	 * this <code>IValueMap</code> will result in a <code>RuntimeException</code> being thrown by
+	 * the <code>Collections</code> framework.
+	 * 
+	 * @return this <code>IValueMap</code>
+	 */
+	IValueMap makeImmutable();
+
+	/**
+	 * Provided that the hash key is a <code>String</code> and you need to access the value ignoring
+	 * the key's case (upper- or lowercase letters), then you may use this method to get the correct
+	 * writing.
+	 * 
+	 * @param key
+	 *            the key
+	 * @return the key with the correct writing
+	 */
+	String getKey(final String key);
+
+	// //
+	// // getAs convenience methods
+	// //
+
+	/**
+	 * Retrieves a <code>Boolean</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid boolean or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Boolean getAsBoolean(String key);
+
+	/**
+	 * Retrieves a <code>boolean</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid boolean or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	boolean getAsBoolean(String key, boolean defaultValue);
+
+	/**
+	 * Retrieves an <code>Integer</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid integer or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Integer getAsInteger(String key);
+
+	/**
+	 * Retrieves an <code>integer</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid integer or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	int getAsInteger(String key, int defaultValue);
+
+	/**
+	 * Retrieves a <code>Long</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid long or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Long getAsLong(String key);
+
+	/**
+	 * Retrieves a <code>long</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid long or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	long getAsLong(String key, long defaultValue);
+
+	/**
+	 * Retrieves a <code>Double</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid double or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Double getAsDouble(String key);
+
+	/**
+	 * Retrieves a <code>double</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid double or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	double getAsDouble(String key, double defaultValue);
+
+	/**
+	 * Retrieves a <code>Duration</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid Duration or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Duration getAsDuration(String key);
+
+	/**
+	 * Retrieves a <code>Duration</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid Duration or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Duration getAsDuration(String key, Duration defaultValue);
+
+	/**
+	 * Retrieves a <code>Time</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @return the value or null if value is not a valid Time or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Time getAsTime(String key);
+
+	/**
+	 * Retrieves a <code>Time</code> value by key.
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default to return
+	 * 
+	 * @return the value or defaultValue if value is not a valid Time or no value is in this
+	 *         <code>IValueMap</code>
+	 * 
+	 */
+	Time getAsTime(String key, Time defaultValue);
+
+	/**
+	 * Retrieves an <code>Enum</code> value by key.
+	 * 
+	 * @param <T>
+	 *            type of enum
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param eClass
+	 *            the enumeration class
+	 * 
+	 * @return the value or null if value is not a valid value of the Enumeration or no value is in
+	 *         this <code>IValueMap</code>
+	 * 
+	 */
+	<T extends Enum<T>> T getAsEnum(String key, Class<T> eClass);
+
+	/**
+	 * Retrieves an <code>Enum</code> value by key.
+	 * 
+	 * @param <T>
+	 *            type of enum
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param defaultValue
+	 *            the default value from the Enumeration (cannot be null)
+	 * 
+	 * @return the value or defaultValue if value is not a valid value of the Enumeration or no
+	 *         value is in this <code>IValueMap</code>
+	 * 
+	 */
+	<T extends Enum<T>> T getAsEnum(String key, T defaultValue);
+
+	/**
+	 * Retrieves an <code>Enum</code> value by key.
+	 * 
+	 * @param <T>
+	 *            type of enum
+	 * 
+	 * @param key
+	 *            the key
+	 * 
+	 * @param eClass
+	 *            the enumeration class
+	 * 
+	 * @param defaultValue
+	 *            the default value from the Enumeration (may be null)
+	 * 
+	 * @return the value or defaultValue if value is not a valid value of the Enumeration or no
+	 *         value is in this <code>IValueMap</code>
+	 * 
+	 */
+	<T extends Enum<T>> T getAsEnum(String key, Class<T> eClass, T defaultValue);
+}
\ No newline at end of file

Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IValueMap.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IntValue.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IntValue.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IntValue.java (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IntValue.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,162 @@
+/*
+ * 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.util.value;
+
+import java.io.Serializable;
+
+import org.apache.wicket.util.lang.Primitives;
+
+
+/**
+ * A base class based on the Java <code>int</code> primitive for value classes that want to
+ * implement standard operations on that value without the pain of aggregating an
+ * <code>Integer</code> object.
+ * 
+ * @author Jonathan Locke
+ * @since 1.2.6
+ */
+public class IntValue implements Comparable<IntValue>, Serializable
+{
+	private static final long serialVersionUID = 1L;
+
+	/** the <code>int</code> value */
+	protected final int value;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param value
+	 *            the <code>int</code> value
+	 */
+	public IntValue(final int value)
+	{
+		this.value = value;
+	}
+
+	/**
+	 * @param that
+	 *            The object to compare with
+	 * @return 0 if equal, -1 if less than or 1 if greater than
+	 */
+	public final int compareTo(final IntValue that)
+	{
+		if (value < that.value)
+		{
+			return -1;
+		}
+
+		if (value > that.value)
+		{
+			return 1;
+		}
+
+		return 0;
+	}
+
+	/**
+	 * Compares this <code>Object</code> to a given <code>Object</code>.
+	 * 
+	 * @param that
+	 *            the <code>Object</code> to compare with
+	 * @return 0 if equal, -1 if less than the given <code>Object</code>'s value, or 1 if greater
+	 *         than given <code>Object</code>'s value
+	 */
+	@Override
+	public final boolean equals(final Object that)
+	{
+		if (that instanceof IntValue)
+		{
+			return value == ((IntValue)that).value;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Compares this <code>IntValue</code> with a primitive <code>int</code> value.
+	 * 
+	 * @param value
+	 *            the <code>int</code> value to compare with
+	 * @return <code>true</code> if this <code>IntValue</code> is greater than the given
+	 *         <code>int</code> value
+	 */
+	public final boolean greaterThan(final int value)
+	{
+		return this.value > value;
+	}
+
+	/**
+	 * Compares this <code>IntValue</code> with another <code>IntValue</code>.
+	 * 
+	 * @param that
+	 *            the <code>IntValue</code> to compare with
+	 * @return <code>true</code> if this <code>IntValue</code> is greater than the given
+	 *         <code>IntValue</code>
+	 */
+	public final boolean greaterThan(final IntValue that)
+	{
+		return value > that.value;
+	}
+
+	/**
+	 * Returns the hash code for this <code>Object</code>.
+	 * 
+	 * @return hash code for this <code>Object</code>
+	 */
+	@Override
+	public final int hashCode()
+	{
+		return Primitives.hashCode(value);
+	}
+
+	/**
+	 * Compares this <code>IntValue</code> with a primitive <code>int</code> value.
+	 * 
+	 * @param that
+	 *            the <code>int</code> value to compare with
+	 * @return <code>true</code> if this <code>IntValue</code> is less than the given
+	 *         <code>int</code> value
+	 */
+	public final boolean lessThan(final int that)
+	{
+		return value < that;
+	}
+
+	/**
+	 * Compares this <code>IntValue</code> with another <code>IntValue</code>.
+	 * 
+	 * @param that
+	 *            the <code>IntValue</code> to compare with
+	 * @return <code>true</code> if this <code>IntValue</code> is less than the given
+	 *         <code>IntValue</code>
+	 */
+	public final boolean lessThan(final IntValue that)
+	{
+		return value < that.value;
+	}
+
+	/**
+	 * Converts this <code>LongValue</code> to a <code>String</code>.
+	 * 
+	 * @return a <code>String</code> representation of this <code>LongValue</code>
+	 */
+	@Override
+	public String toString()
+	{
+		return String.valueOf(value);
+	}
+}

Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/IntValue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/LongValue.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/LongValue.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/LongValue.java (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/LongValue.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,165 @@
+/*
+ * 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.util.value;
+
+import java.io.Serializable;
+
+import org.apache.wicket.util.lang.Primitives;
+
+
+/**
+ * A base class based on the Java <code>long</code> primitive for value classes that want to
+ * implement standard operations on that value without the pain of aggregating a <code>Long</code>
+ * object.
+ * 
+ * @author Jonathan Locke
+ * @since 1.2.6
+ */
+public class LongValue implements Comparable<LongValue>, Serializable
+{
+	private static final long serialVersionUID = 1L;
+
+	/** the <code>long</code> value */
+	protected final long value;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param value
+	 *            the <code>long</code> value
+	 */
+	public LongValue(final long value)
+	{
+		this.value = value;
+	}
+
+	/**
+	 * Compares this <code>Object</code> to a given <code>Object</code>.
+	 * 
+	 * @param that
+	 *            the <code>Object</code> to compare with
+	 * @return 0 if equal, -1 if less than the given <code>Object</code>'s value, or 1 if greater
+	 *         than given <code>Object</code>'s value
+	 */
+	public final int compareTo(final LongValue that)
+	{
+		if (value < that.value)
+		{
+			return -1;
+		}
+
+		if (value > that.value)
+		{
+			return 1;
+		}
+
+		return 0;
+	}
+
+	/**
+	 * Tests for equality.
+	 * 
+	 * @param that
+	 *            the <code>Object</code> to compare with
+	 * @return <code>true</code> if this <code>Object</code>'s value is equal to the given
+	 *         <code>Object</code>'s value
+	 */
+	@Override
+	public final boolean equals(final Object that)
+	{
+		if (that instanceof LongValue)
+		{
+			return value == ((LongValue)that).value;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Compares this <code>LongValue</code> with a primitive <code>long</code> value.
+	 * 
+	 * @param value
+	 *            the <code>long</code> value to compare with
+	 * @return <code>true</code> if this <code>LongValue</code> is greater than the given
+	 *         <code>long</code> value
+	 */
+	public final boolean greaterThan(final long value)
+	{
+		return this.value > value;
+	}
+
+	/**
+	 * Compares this <code>LongValue</code> with another <code>LongValue</code>.
+	 * 
+	 * @param that
+	 *            the <code>LongValue</code> to compare with
+	 * @return <code>true</code> if this <code>LongValue</code> is greater than the given
+	 *         <code>LongValue</code>
+	 */
+	public final boolean greaterThan(final LongValue that)
+	{
+		return value > that.value;
+	}
+
+	/**
+	 * Returns the hash code for this <code>Object</code>.
+	 * 
+	 * @return hash code for this <code>Object</code>
+	 */
+	@Override
+	public final int hashCode()
+	{
+		return Primitives.hashCode(value);
+	}
+
+	/**
+	 * Compares this <code>LongValue</code> with a primitive <code>long</code> value.
+	 * 
+	 * @param that
+	 *            the <code>long</code> value to compare with
+	 * @return <code>true</code> if this <code>LongValue</code> is less than the given
+	 *         <code>long</code> value
+	 */
+	public final boolean lessThan(final long that)
+	{
+		return value < that;
+	}
+
+	/**
+	 * Compares this <code>LongValue</code> with another <code>LongValue</code>.
+	 * 
+	 * @param that
+	 *            the <code>LongValue</code> value to compare with
+	 * @return <code>true</code> if this <code>LongValue</code> is less than the given
+	 *         <code>LongValue</code>
+	 */
+	public final boolean lessThan(final LongValue that)
+	{
+		return value < that.value;
+	}
+
+	/**
+	 * Converts this <code>LongValue</code> to a <code>String</code>.
+	 * 
+	 * @return a <code>String</code> representation of this <code>LongValue</code>
+	 */
+	@Override
+	public String toString()
+	{
+		return String.valueOf(value);
+	}
+}

Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/LongValue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/ValueMap.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/ValueMap.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/ValueMap.java (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/ValueMap.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,865 @@
+/*
+ * 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.util.value;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.wicket.util.parse.metapattern.MetaPattern;
+import org.apache.wicket.util.parse.metapattern.parsers.VariableAssignmentParser;
+import org.apache.wicket.util.string.IStringIterator;
+import org.apache.wicket.util.string.StringList;
+import org.apache.wicket.util.string.StringValue;
+import org.apache.wicket.util.string.StringValueConversionException;
+import org.apache.wicket.util.time.Duration;
+import org.apache.wicket.util.time.Time;
+
+
+/**
+ * A <code>IValueMap</code> implementation that holds values, parses <code>String</code>s, and
+ * exposes a variety of convenience methods.
+ * <p>
+ * In addition to a no-arg constructor and a copy constructor that takes a <code>Map</code>
+ * argument, <code>ValueMap</code>s can be constructed using a parsing constructor.
+ * <code>ValueMap(String)</code> will parse values from the string in comma separated key/value
+ * assignment pairs. For example, <code>new ValueMap("a=9,b=foo")</code>.
+ * <p>
+ * Values can be retrieved from the <code>ValueMap</code> in the usual way or with methods that do
+ * handy conversions to various types, including <code>String</code>, <code>StringValue</code>,
+ * <code>int</code>, <code>long</code>, <code>double</code>, <code>Time</code> and
+ * <code>Duration</code>.
+ * <p>
+ * The <code>makeImmutable</code> method will make the underlying <code>Map</code> immutable.
+ * Further attempts to change the <code>Map</code> will result in a <code>RuntimeException</code>.
+ * <p>
+ * The <code>toString</code> method converts a <code>ValueMap</code> object to a readable key/value
+ * string for diagnostics.
+ * 
+ * @author Jonathan Locke
+ * @author Doug Donohoe
+ * @since 1.2.6
+ */
+public class ValueMap extends LinkedHashMap<String, Object> implements IValueMap
+{
+	/** an empty <code>ValueMap</code>. */
+	public static final ValueMap EMPTY_MAP;
+
+	/** create EMPTY_MAP, make immutable * */
+	static
+	{
+		EMPTY_MAP = new ValueMap();
+		EMPTY_MAP.makeImmutable();
+	}
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * <code>true</code> if this <code>ValueMap</code> has been made immutable.
+	 */
+	private boolean immutable = false;
+
+	/**
+	 * Constructs empty <code>ValueMap</code>.
+	 */
+	public ValueMap()
+	{
+		super();
+	}
+
+	/**
+	 * Copy constructor.
+	 * 
+	 * @param map
+	 *            the <code>ValueMap</code> to copy
+	 */
+	public ValueMap(final Map<? extends String, ? extends Object> map)
+	{
+		super();
+
+		super.putAll(map);
+	}
+
+	/**
+	 * Constructor.
+	 * <p>
+	 * NOTE: Please use <code>RequestUtils.decodeParameters()</code> if you wish to properly decode
+	 * a request URL.
+	 * 
+	 * @param keyValuePairs
+	 *            list of key/value pairs separated by commas. For example, "
+	 *            <code>param1=foo,param2=bar</code>"
+	 */
+	public ValueMap(final String keyValuePairs)
+	{
+		this(keyValuePairs, ",");
+	}
+
+	/**
+	 * Constructor.
+	 * <p>
+	 * NOTE: Please use <code>RequestUtils.decodeParameters()</code> if you wish to properly decode
+	 * a request URL.
+	 * 
+	 * @param keyValuePairs
+	 *            list of key/value pairs separated by a given delimiter. For example, "
+	 *            <code>param1=foo,param2=bar</code>" where delimiter is "<code>,</code>".
+	 * @param delimiter
+	 *            delimiter <code>String</code> used to separate key/value pairs
+	 */
+	public ValueMap(final String keyValuePairs, final String delimiter)
+	{
+		super();
+
+		int start = 0;
+		int equalsIndex = keyValuePairs.indexOf('=');
+		int delimiterIndex = keyValuePairs.indexOf(delimiter, equalsIndex);
+		if (delimiterIndex == -1)
+		{
+			delimiterIndex = keyValuePairs.length();
+		}
+		while (equalsIndex != -1)
+		{
+			if (delimiterIndex < keyValuePairs.length())
+			{
+				int equalsIndex2 = keyValuePairs.indexOf('=', delimiterIndex + 1);
+				if (equalsIndex2 != -1)
+				{
+					delimiterIndex = keyValuePairs.lastIndexOf(delimiter, equalsIndex2);
+				}
+				else
+				{
+					delimiterIndex = keyValuePairs.length();
+				}
+			}
+			String key = keyValuePairs.substring(start, equalsIndex);
+			String value = keyValuePairs.substring(equalsIndex + 1, delimiterIndex);
+			add(key, value);
+			if (delimiterIndex < keyValuePairs.length())
+			{
+				start = delimiterIndex + 1;
+				equalsIndex = keyValuePairs.indexOf('=', start);
+				if (equalsIndex != -1)
+				{
+					delimiterIndex = keyValuePairs.indexOf(delimiter, equalsIndex);
+					if (delimiterIndex == -1)
+					{
+						delimiterIndex = keyValuePairs.length();
+					}
+				}
+			}
+			else
+			{
+				equalsIndex = -1;
+			}
+		}
+	}
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param keyValuePairs
+	 *            list of key/value pairs separated by a given delimiter. For example, "
+	 *            <code>param1=foo,param2=bar</code>" where delimiter is "<code>,</code>".
+	 * @param delimiter
+	 *            delimiter string used to separate key/value pairs
+	 * @param valuePattern
+	 *            pattern for value. To pass a simple regular expression, pass "
+	 *            <code>new MetaPattern(regexp)</code>".
+	 */
+	public ValueMap(final String keyValuePairs, final String delimiter,
+		final MetaPattern valuePattern)
+	{
+		super();
+
+		// Get list of strings separated by the delimiter
+		final StringList pairs = StringList.tokenize(keyValuePairs, delimiter);
+
+		// Go through each string in the list
+		for (IStringIterator iterator = pairs.iterator(); iterator.hasNext();)
+		{
+			// Get the next key value pair
+			final String pair = iterator.next();
+
+			// Parse using metapattern parser for variable assignments
+			final VariableAssignmentParser parser = new VariableAssignmentParser(pair, valuePattern);
+
+			// Does it parse?
+			if (parser.matches())
+			{
+				// Succeeded. Put key and value into map
+				put(parser.getKey(), parser.getValue());
+			}
+			else
+			{
+				throw new IllegalArgumentException("Invalid key value list: '" + keyValuePairs +
+					'\'');
+			}
+		}
+	}
+
+	/**
+	 * @see java.util.Map#clear()
+	 */
+	@Override
+	public final void clear()
+	{
+		checkMutability();
+		super.clear();
+	}
+
+	/**
+	 * @see IValueMap#getBoolean(String)
+	 */
+	public final boolean getBoolean(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toBoolean();
+	}
+
+	/**
+	 * @see IValueMap#getDouble(String)
+	 */
+	public final double getDouble(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toDouble();
+	}
+
+	/**
+	 * @see IValueMap#getDouble(String, double)
+	 */
+	public final double getDouble(final String key, final double defaultValue)
+		throws StringValueConversionException
+	{
+		return getStringValue(key).toDouble(defaultValue);
+	}
+
+	/**
+	 * @see IValueMap#getDuration(String)
+	 */
+	public final Duration getDuration(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toDuration();
+	}
+
+	/**
+	 * @see IValueMap#getInt(String)
+	 */
+	public final int getInt(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toInt();
+	}
+
+	/**
+	 * @see IValueMap#getInt(String, int)
+	 */
+	public final int getInt(final String key, final int defaultValue)
+		throws StringValueConversionException
+	{
+		return getStringValue(key).toInt(defaultValue);
+	}
+
+	/**
+	 * @see IValueMap#getLong(String)
+	 */
+	public final long getLong(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toLong();
+	}
+
+	/**
+	 * @see IValueMap#getLong(String, long)
+	 */
+	public final long getLong(final String key, final long defaultValue)
+		throws StringValueConversionException
+	{
+		return getStringValue(key).toLong(defaultValue);
+	}
+
+	/**
+	 * @see IValueMap#getString(String, String)
+	 */
+	public final String getString(final String key, final String defaultValue)
+	{
+		final String value = getString(key);
+		return value != null ? value : defaultValue;
+	}
+
+	/**
+	 * @see IValueMap#getString(String)
+	 */
+	public final String getString(final String key)
+	{
+		final Object o = get(key);
+		if (o == null)
+		{
+			return null;
+		}
+		else if (o.getClass().isArray() && Array.getLength(o) > 0)
+		{
+			// if it is an array just get the first value
+			final Object arrayValue = Array.get(o, 0);
+			if (arrayValue == null)
+			{
+				return null;
+			}
+			else
+			{
+				return arrayValue.toString();
+			}
+
+		}
+		else
+		{
+			return o.toString();
+		}
+	}
+
+	/**
+	 * @see IValueMap#getCharSequence(String)
+	 */
+	public final CharSequence getCharSequence(final String key)
+	{
+		final Object o = get(key);
+		if (o == null)
+		{
+			return null;
+		}
+		else if (o.getClass().isArray() && Array.getLength(o) > 0)
+		{
+			// if it is an array just get the first value
+			final Object arrayValue = Array.get(o, 0);
+			if (arrayValue == null)
+			{
+				return null;
+			}
+			else
+			{
+				if (arrayValue instanceof CharSequence)
+				{
+					return (CharSequence)arrayValue;
+				}
+				return arrayValue.toString();
+			}
+
+		}
+		else
+		{
+			if (o instanceof CharSequence)
+			{
+				return (CharSequence)o;
+			}
+			return o.toString();
+		}
+	}
+
+	/**
+	 * @see IValueMap#getStringArray(String)
+	 */
+	public String[] getStringArray(final String key)
+	{
+		final Object o = get(key);
+		if (o == null)
+		{
+			return null;
+		}
+		else if (o instanceof String[])
+		{
+			return (String[])o;
+		}
+		else if (o.getClass().isArray())
+		{
+			int length = Array.getLength(o);
+			String[] array = new String[length];
+			for (int i = 0; i < length; i++)
+			{
+				final Object arrayValue = Array.get(o, i);
+				if (arrayValue != null)
+				{
+					array[i] = arrayValue.toString();
+				}
+			}
+			return array;
+		}
+		return new String[] { o.toString() };
+	}
+
+	/**
+	 * @see IValueMap#getStringValue(String)
+	 */
+	public StringValue getStringValue(final String key)
+	{
+		return StringValue.valueOf(getString(key));
+	}
+
+	/**
+	 * @see IValueMap#getTime(String)
+	 */
+	public final Time getTime(final String key) throws StringValueConversionException
+	{
+		return getStringValue(key).toTime();
+	}
+
+	/**
+	 * @see IValueMap#isImmutable()
+	 */
+	public final boolean isImmutable()
+	{
+		return immutable;
+	}
+
+	/**
+	 * @see IValueMap#makeImmutable()
+	 */
+	public final IValueMap makeImmutable()
+	{
+		immutable = true;
+		return this;
+	}
+
+	/**
+	 * @see java.util.Map#put(Object, Object)
+	 */
+	@Override
+	public Object put(final String key, final Object value)
+	{
+		checkMutability();
+		return super.put(key, value);
+	}
+
+	/**
+	 * Adds the value to this <code>ValueMap</code> with the given key. If the key already is in the
+	 * <code>ValueMap</code> it will combine the values into a <code>String</code> array, else it
+	 * will just store the value itself.
+	 * 
+	 * @param key
+	 *            the key to store the value under
+	 * @param value
+	 *            the value that must be added/merged to the <code>ValueMap</code>
+	 * @return the value itself if there was no previous value, or a <code>String</code> array with
+	 *         the combined values
+	 */
+	public final Object add(final String key, final String value)
+	{
+		checkMutability();
+		final Object o = get(key);
+		if (o == null)
+		{
+			return put(key, value);
+		}
+		else if (o.getClass().isArray())
+		{
+			int length = Array.getLength(o);
+			String destArray[] = new String[length + 1];
+			for (int i = 0; i < length; i++)
+			{
+				final Object arrayValue = Array.get(o, i);
+				if (arrayValue != null)
+				{
+					destArray[i] = arrayValue.toString();
+				}
+			}
+			destArray[length] = value;
+
+			return put(key, destArray);
+		}
+		else
+		{
+			return put(key, new String[] { o.toString(), value });
+		}
+	}
+
+	/**
+	 * @see java.util.Map#putAll(java.util.Map)
+	 */
+	@Override
+	public void putAll(final Map<? extends String, ? extends Object> map)
+	{
+		checkMutability();
+		super.putAll(map);
+	}
+
+	/**
+	 * @see java.util.Map#remove(java.lang.Object)
+	 */
+	@Override
+	public Object remove(final Object key)
+	{
+		checkMutability();
+		return super.remove(key);
+	}
+
+	/**
+	 * @see IValueMap#getKey(String)
+	 */
+	public String getKey(final String key)
+	{
+		for (Object keyValue : keySet())
+		{
+			if (keyValue instanceof String)
+			{
+				String keyString = (String)keyValue;
+				if (key.equalsIgnoreCase(keyString))
+				{
+					return keyString;
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Generates a <code>String</code> representation of this object.
+	 * 
+	 * @return <code>String</code> representation of this <code>ValueMap</code> consistent with the
+	 *         tag-attribute style of markup elements. For example: <code>a="x" b="y" c="z"</code>.
+	 */
+	@Override
+	public String toString()
+	{
+		final StringBuffer buffer = new StringBuffer();
+		boolean first = true;
+		for (Map.Entry<String, Object> entry : entrySet())
+		{
+			if (first == false)
+			{
+				buffer.append(' ');
+			}
+			first = false;
+
+			buffer.append(entry.getKey());
+			buffer.append(" = \"");
+			final Object value = entry.getValue();
+			if (value == null)
+			{
+				buffer.append("null");
+			}
+			else if (value.getClass().isArray())
+			{
+				buffer.append(Arrays.asList((Object[])value));
+			}
+			else
+			{
+				buffer.append(value);
+			}
+
+			buffer.append('\"');
+		}
+		return buffer.toString();
+	}
+
+	/**
+	 * Throws an exception if <code>ValueMap</code> is immutable.
+	 */
+	private void checkMutability()
+	{
+		if (immutable)
+		{
+			throw new UnsupportedOperationException("Map is immutable");
+		}
+	}
+
+	// //
+	// // getAs convenience methods
+	// //
+
+	/**
+	 * @see IValueMap#getAsBoolean(String)
+	 * 
+	 */
+	public Boolean getAsBoolean(String key)
+	{
+		if (!containsKey(key))
+		{
+			return null;
+		}
+
+		try
+		{
+			return getBoolean(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return null;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsBoolean(String, boolean)
+	 * 
+	 */
+	public boolean getAsBoolean(String key, boolean defaultValue)
+	{
+		try
+		{
+			return getBoolean(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsInteger(String)
+	 */
+	public Integer getAsInteger(String key)
+	{
+		if (!containsKey(key))
+		{
+			return null;
+		}
+
+		try
+		{
+			return getInt(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return null;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsInteger(String, int)
+	 */
+	public int getAsInteger(String key, int defaultValue)
+	{
+		try
+		{
+			return getInt(key, defaultValue);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsLong(String)
+	 */
+	public Long getAsLong(String key)
+	{
+		if (!containsKey(key))
+		{
+			return null;
+		}
+
+		try
+		{
+			return getLong(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return null;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsLong(String, long)
+	 */
+	public long getAsLong(String key, long defaultValue)
+	{
+		try
+		{
+			return getLong(key, defaultValue);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsDouble(String)
+	 */
+	public Double getAsDouble(String key)
+	{
+		if (!containsKey(key))
+		{
+			return null;
+		}
+
+		try
+		{
+			return getDouble(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return null;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsDouble(String, double)
+	 */
+	public double getAsDouble(final String key, final double defaultValue)
+	{
+		try
+		{
+			return getDouble(key, defaultValue);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsDuration(String)
+	 */
+	public Duration getAsDuration(final String key)
+	{
+		return getAsDuration(key, null);
+	}
+
+	/**
+	 * @see IValueMap#getAsDuration(String, Duration)
+	 */
+	public Duration getAsDuration(final String key, final Duration defaultValue)
+	{
+		if (!containsKey(key))
+		{
+			return defaultValue;
+		}
+
+		try
+		{
+			return getDuration(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see IValueMap#getAsTime(String)
+	 */
+	public Time getAsTime(final String key)
+	{
+		return getAsTime(key, null);
+	}
+
+	/**
+	 * @see IValueMap#getAsTime(String, Time)
+	 */
+	public Time getAsTime(final String key, final Time defaultValue)
+	{
+		if (!containsKey(key))
+		{
+			return defaultValue;
+		}
+
+		try
+		{
+			return getTime(key);
+		}
+		catch (StringValueConversionException ignored)
+		{
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * @see org.apache.wicket.util.value.IValueMap#getAsEnum(java.lang.String, java.lang.Class)
+	 */
+	public <T extends Enum<T>> T getAsEnum(final String key, final Class<T> eClass)
+	{
+		return getEnumImpl(key, eClass, null);
+	}
+
+	/**
+	 * @see org.apache.wicket.util.value.IValueMap#getAsEnum(java.lang.String, java.lang.Enum)
+	 */
+	public <T extends Enum<T>> T getAsEnum(final String key, final T defaultValue)
+	{
+		if (defaultValue == null)
+		{
+			throw new IllegalArgumentException("Default value cannot be null");
+		}
+
+		return getEnumImpl(key, defaultValue.getClass(), defaultValue);
+	}
+
+	/**
+	 * @see org.apache.wicket.util.value.IValueMap#getAsEnum(java.lang.String, java.lang.Class,
+	 *      java.lang.Enum)
+	 */
+	public <T extends Enum<T>> T getAsEnum(final String key, final Class<T> eClass,
+		final T defaultValue)
+	{
+		return getEnumImpl(key, eClass, defaultValue);
+	}
+
+	/**
+	 * get enum implementation
+	 * 
+	 * @param key
+	 * @param eClass
+	 * @param defaultValue
+	 * @param <T>
+	 * @return Enum
+	 */
+	@SuppressWarnings( { "unchecked" })
+	private <T extends Enum<T>> T getEnumImpl(final String key, final Class<?> eClass,
+		final T defaultValue)
+	{
+		if (eClass == null)
+		{
+			throw new IllegalArgumentException("eClass value cannot be null");
+		}
+
+		String value = getString(key);
+		if (value == null)
+		{
+			return defaultValue;
+		}
+
+		Method valueOf = null;
+		try
+		{
+			valueOf = eClass.getMethod("valueOf", String.class);
+		}
+		catch (NoSuchMethodException e)
+		{
+			throw new RuntimeException("Could not find method valueOf(String s) for " +
+				eClass.getName(), e);
+		}
+
+		try
+		{
+			return (T)valueOf.invoke(eClass, value);
+		}
+		catch (IllegalAccessException e)
+		{
+			throw new RuntimeException("Could not invoke method valueOf(String s) on " +
+				eClass.getName(), e);
+		}
+		catch (InvocationTargetException e)
+		{
+			// IllegalArgumentException thrown if enum isn't defined - just return default
+			if (e.getCause() instanceof IllegalArgumentException)
+			{
+				return defaultValue;
+			}
+			throw new RuntimeException(e); // shouldn't happen
+		}
+	}
+}

Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/ValueMap.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/package.html
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/package.html?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/package.html (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/package.html Wed Mar 17 00:34:34 2010
@@ -0,0 +1,29 @@
+<!--
+   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.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C/DTD HTML 3.2 Final//NL">
+<html>
+	<head>
+		<title>
+			org.apache.wicket.util.value package
+		</title>
+	</head>
+	<body>
+		<p>
+			This package provides casting utilities.
+		</p>
+	</body>
+</html>
\ No newline at end of file

Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/value/package.html
------------------------------------------------------------------------------
    svn:executable = *

Modified: wicket/trunk/wicket/pom.xml
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/pom.xml?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/pom.xml (original)
+++ wicket/trunk/wicket/pom.xml Wed Mar 17 00:34:34 2010
@@ -39,6 +39,10 @@
 		persisted using your favorite technology. 
 	</description>
 	<dependencies>
+        <dependency>
+            <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket-util</artifactId>
+        </dependency>
 		<dependency>
 			<groupId>javax.portlet</groupId>
 			<artifactId>portlet-api</artifactId>

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java Wed Mar 17 00:34:34 2010
@@ -88,8 +88,8 @@ import org.apache.wicket.settings.Settin
 import org.apache.wicket.util.IProvider;
 import org.apache.wicket.util.convert.ConverterLocator;
 import org.apache.wicket.util.lang.Checks;
-import org.apache.wicket.util.lang.Objects;
 import org.apache.wicket.util.lang.PropertyResolver;
+import org.apache.wicket.util.lang.WicketObjects;
 import org.apache.wicket.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -772,7 +772,7 @@ public abstract class Application implem
 	 */
 	private final void addInitializer(String className)
 	{
-		IInitializer initializer = (IInitializer)Objects.newInstance(className);
+		IInitializer initializer = (IInitializer)WicketObjects.newInstance(className);
 		if (initializer != null)
 		{
 			initializers.add(initializer);

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Component.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Component.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Component.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Component.java Wed Mar 17 00:34:34 2010
@@ -63,7 +63,8 @@ import org.apache.wicket.request.resourc
 import org.apache.wicket.settings.IDebugSettings;
 import org.apache.wicket.util.convert.IConverter;
 import org.apache.wicket.util.lang.Classes;
-import org.apache.wicket.util.lang.Objects;
+import org.apache.wicket.util.lang.WicketObjects;
+import org.apache.wicket.util.string.ComponentStrings;
 import org.apache.wicket.util.string.PrependingStringBuffer;
 import org.apache.wicket.util.string.Strings;
 import org.apache.wicket.util.value.ValueMap;
@@ -694,7 +695,7 @@ public abstract class Component implemen
 		final IDebugSettings debugSettings = Application.get().getDebugSettings();
 		if (debugSettings.isLinePreciseReportingOnNewComponentEnabled())
 		{
-			setMetaData(CONSTRUCTED_AT_KEY, Strings.toString(this, new MarkupException(
+			setMetaData(CONSTRUCTED_AT_KEY, ComponentStrings.toString(this, new MarkupException(
 				"constructed")));
 		}
 
@@ -1848,7 +1849,7 @@ public abstract class Component implemen
 		long size = -1;
 		try
 		{
-			size = Objects.sizeof(this);
+			size = WicketObjects.sizeof(this);
 		}
 		catch (Exception e)
 		{

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/MarkupContainer.java Wed Mar 17 00:34:34 2010
@@ -39,6 +39,7 @@ import org.apache.wicket.model.IComponen
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.IWrapModel;
 import org.apache.wicket.settings.IDebugSettings;
+import org.apache.wicket.util.string.ComponentStrings;
 import org.apache.wicket.util.string.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -984,7 +985,8 @@ public abstract class MarkupContainer ex
 		final IDebugSettings debugSettings = Application.get().getDebugSettings();
 		if (debugSettings.isLinePreciseReportingOnAddComponentEnabled())
 		{
-			child.setMetaData(ADDED_AT_KEY, Strings.toString(child, new MarkupException("added")));
+			child.setMetaData(ADDED_AT_KEY, ComponentStrings.toString(child, new MarkupException(
+				"added")));
 		}
 
 		if (page != null)

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Page.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Page.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Page.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Page.java Wed Mar 17 00:34:34 2010
@@ -45,7 +45,7 @@ import org.apache.wicket.request.cycle.R
 import org.apache.wicket.session.ISessionStore;
 import org.apache.wicket.settings.IDebugSettings;
 import org.apache.wicket.util.lang.Classes;
-import org.apache.wicket.util.lang.Objects;
+import org.apache.wicket.util.lang.WicketObjects;
 import org.apache.wicket.util.string.StringValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -454,7 +454,7 @@ public abstract class Page extends Marku
 	@Override
 	public final long getSizeInBytes()
 	{
-		return Objects.sizeof(this);
+		return WicketObjects.sizeof(this);
 	}
 
 	/**

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/model/Model.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/model/Model.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/model/Model.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/model/Model.java Wed Mar 17 00:34:34 2010
@@ -215,4 +215,17 @@ public class Model<T extends Serializabl
 		Model<?> that = (Model<?>)obj;
 		return Objects.equal(object, that.object);
 	}
+
+	/**
+	 * Supresses generics warning when converting model types
+	 * 
+	 * @param <T>
+	 * @param model
+	 * @return <code>model</code>
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> IModel<T> of(IModel<?> model)
+	{
+		return (IModel<T>)model;
+	}
 }

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java Wed Mar 17 00:34:34 2010
@@ -26,6 +26,7 @@ import org.apache.wicket.Page;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.util.lang.Checks;
 import org.apache.wicket.util.lang.Objects;
+import org.apache.wicket.util.lang.WicketObjects;
 
 /**
  * Wicket's default page store
@@ -360,7 +361,7 @@ public class DefaultPageStore implements
 		Checks.argumentNotNull(sessionId, "sessionId");
 		Checks.argumentNotNull(page, "page");
 
-		byte data[] = Objects.objectToByteArray(page, applicationName);
+		byte data[] = WicketObjects.objectToByteArray(page, applicationName);
 		return new SerializedPage(sessionId, page.getPageId(), data);
 	}
 
@@ -371,7 +372,7 @@ public class DefaultPageStore implements
 	 */
 	protected IManageablePage deserializePage(final byte data[])
 	{
-		return (IManageablePage)Objects.byteArrayToObject(data);
+		return (IManageablePage)WicketObjects.byteArrayToObject(data);
 	}
 
 	/**

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/lang/WicketObjects.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/lang/WicketObjects.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/lang/WicketObjects.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,561 @@
+/*
+ * 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.util.lang;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.util.HashMap;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.application.IClassResolver;
+import org.apache.wicket.settings.IApplicationSettings;
+import org.apache.wicket.util.io.ByteCountingOutputStream;
+import org.apache.wicket.util.io.IObjectStreamFactory;
+import org.apache.wicket.util.io.IObjectStreamFactory.DefaultObjectStreamFactory;
+import org.apache.wicket.util.string.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WicketObjects
+{
+	/** log. */
+	private static final Logger log = LoggerFactory.getLogger(WicketObjects.class);
+
+	private WicketObjects()
+	{
+	}
+
+	/**
+	 * Interface that enables users to plugin the way object sizes are calculated with Wicket.
+	 */
+	public static interface IObjectSizeOfStrategy
+	{
+		/**
+		 * Computes the size of an object. This typically is an estimation, not an absolute accurate
+		 * size.
+		 * 
+		 * @param object
+		 *            Object to compute size of
+		 * @return The size of the object in bytes.
+		 */
+		long sizeOf(Object object);
+	}
+
+	/**
+	 * {@link IObjectSizeOfStrategy} that works by serializing the object to an instance of
+	 * {@link ByteCountingOutputStream}, which records the number of bytes written to it. Hence,
+	 * this gives the size of the object as it would be serialized,including all the overhead of
+	 * writing class headers etc. Not very accurate (the real memory consumption should be lower)
+	 * but the best we can do in a cheap way pre JDK 5.
+	 */
+	public static final class SerializingObjectSizeOfStrategy implements IObjectSizeOfStrategy
+	{
+		/**
+		 * @see org.apache.wicket.util.lang.Objects.IObjectSizeOfStrategy#sizeOf(java.lang.Object)
+		 */
+		public long sizeOf(Object object)
+		{
+			if (object == null)
+			{
+				return 0;
+			}
+			try
+			{
+				final ByteCountingOutputStream out = new ByteCountingOutputStream();
+				new ObjectOutputStream(out).writeObject(object);
+				out.close();
+				return out.size();
+			}
+			catch (IOException e)
+			{
+				if (log.isWarnEnabled())
+				{
+					log.warn("Unable to determine object size: " + object.toString(), e);
+				}
+				return -1;
+			}
+		}
+
+	}
+
+	private static final class ReplaceObjectInputStream extends ObjectInputStream
+	{
+		private final ClassLoader classloader;
+		private final HashMap<String, Component> replacedComponents;
+
+		private ReplaceObjectInputStream(InputStream in,
+			HashMap<String, Component> replacedComponents, ClassLoader classloader)
+			throws IOException
+		{
+			super(in);
+			this.replacedComponents = replacedComponents;
+			this.classloader = classloader;
+			enableResolveObject(true);
+		}
+
+		// This override is required to resolve classes inside in different
+		// bundle, i.e.
+		// The classes can be resolved by OSGI classresolver implementation
+		@Override
+		protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,
+			ClassNotFoundException
+		{
+			String className = desc.getName();
+
+			try
+			{
+				return Class.forName(className, true, classloader);
+			}
+			catch (ClassNotFoundException ex1)
+			{
+				// ignore this exception.
+				log.debug("Class not found by using objects own classloader, trying the IClassResolver");
+			}
+
+			Application application = Application.get();
+			IApplicationSettings applicationSettings = application.getApplicationSettings();
+			IClassResolver classResolver = applicationSettings.getClassResolver();
+
+			Class<?> candidate = null;
+			try
+			{
+				candidate = classResolver.resolveClass(className);
+				if (candidate == null)
+				{
+					candidate = super.resolveClass(desc);
+				}
+			}
+			catch (WicketRuntimeException ex)
+			{
+				if (ex.getCause() instanceof ClassNotFoundException)
+				{
+					throw (ClassNotFoundException)ex.getCause();
+				}
+			}
+			return candidate;
+		}
+
+		@Override
+		protected Object resolveObject(Object obj) throws IOException
+		{
+			Object replaced = replacedComponents.get(obj);
+			if (replaced != null)
+			{
+				return replaced;
+			}
+			return super.resolveObject(obj);
+		}
+	}
+
+	private static final class ReplaceObjectOutputStream extends ObjectOutputStream
+	{
+		private final HashMap<String, Component> replacedComponents;
+
+		private ReplaceObjectOutputStream(OutputStream out,
+			HashMap<String, Component> replacedComponents) throws IOException
+		{
+			super(out);
+			this.replacedComponents = replacedComponents;
+			enableReplaceObject(true);
+		}
+
+		@Override
+		protected Object replaceObject(Object obj) throws IOException
+		{
+			if (obj instanceof Component)
+			{
+				final Component component = (Component)obj;
+				String name = component.getPath();
+				replacedComponents.put(name, component);
+				return name;
+			}
+			return super.replaceObject(obj);
+		}
+	}
+
+	/**
+	 * De-serializes an object from a byte array.
+	 * 
+	 * @param data
+	 *            The serialized object
+	 * @return The object
+	 */
+	public static Object byteArrayToObject(final byte[] data)
+	{
+		ThreadContext old = ThreadContext.get(false);
+		try
+		{
+			final ByteArrayInputStream in = new ByteArrayInputStream(data);
+			ObjectInputStream ois = null;
+			try
+			{
+				ois = objectStreamFactory.newObjectInputStream(in);
+				String applicationName = (String)ois.readObject();
+				if (applicationName != null && !Application.exists())
+				{
+					Application app = Application.get(applicationName);
+					if (app != null)
+					{
+						ThreadContext.setApplication(app);
+					}
+				}
+				return ois.readObject();
+			}
+			finally
+			{
+				if (ois != null)
+				{
+					ois.close();
+				}
+				in.close();
+			}
+		}
+		catch (ClassNotFoundException e)
+		{
+			throw new RuntimeException("Could not deserialize object using `" +
+				objectStreamFactory.getClass().getName() + "` object factory", e);
+		}
+		catch (IOException e)
+		{
+			throw new RuntimeException("Could not deserialize object using `" +
+				objectStreamFactory.getClass().getName() + "` object factory", e);
+		}
+		finally
+		{
+			ThreadContext.restore(old);
+		}
+	}
+
+	/**
+	 * Makes a deep clone of an object by serializing and deserializing it. The object must be fully
+	 * serializable to be cloned. This method will not clone wicket Components, it will just reuse
+	 * those instances so that the complete component tree is not copied over only the model data.
+	 * 
+	 * @param object
+	 *            The object to clone
+	 * @return A deep copy of the object
+	 */
+	public static Object cloneModel(final Object object)
+	{
+		if (object == null)
+		{
+			return null;
+		}
+		else
+		{
+			try
+			{
+				final ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+				final HashMap<String, Component> replacedObjects = Generics.newHashMap();
+				ObjectOutputStream oos = new ReplaceObjectOutputStream(out, replacedObjects);
+				oos.writeObject(object);
+				ObjectInputStream ois = new ReplaceObjectInputStream(new ByteArrayInputStream(
+					out.toByteArray()), replacedObjects, object.getClass().getClassLoader());
+				return ois.readObject();
+			}
+			catch (ClassNotFoundException e)
+			{
+				throw new WicketRuntimeException("Internal error cloning object", e);
+			}
+			catch (IOException e)
+			{
+				throw new WicketRuntimeException("Internal error cloning object", e);
+			}
+		}
+	}
+
+	/**
+	 * The default object stream factory to use. Keep this as a static here opposed to in
+	 * Application, as the Application most likely isn't available in the threads we'll be using
+	 * this with.
+	 */
+	private static IObjectStreamFactory objectStreamFactory = new IObjectStreamFactory.DefaultObjectStreamFactory();
+
+	/**
+	 * Strategy for calculating sizes of objects. Note: I didn't make this an application setting as
+	 * we have enough of those already, and the typical way this probably would be used is that
+	 * install a different one according to the JDK version used, so varying them between
+	 * applications doesn't make a lot of sense.
+	 */
+	private static IObjectSizeOfStrategy objectSizeOfStrategy = new SerializingObjectSizeOfStrategy();
+
+	/**
+	 * Makes a deep clone of an object by serializing and deserializing it. The object must be fully
+	 * serializable to be cloned. No extra debug info is gathered.
+	 * 
+	 * @param object
+	 *            The object to clone
+	 * @return A deep copy of the object
+	 * @see #cloneModel(Object)
+	 */
+	public static Object cloneObject(final Object object)
+	{
+		if (object == null)
+		{
+			return null;
+		}
+		else
+		{
+			try
+			{
+				final ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+				ObjectOutputStream oos = new ObjectOutputStream(out);
+				oos.writeObject(object);
+				ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
+					out.toByteArray()))
+				{
+					// This override is required to resolve classes inside in different bundle, i.e.
+					// The classes can be resolved by OSGI classresolver implementation
+					@Override
+					protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,
+						ClassNotFoundException
+					{
+						String className = desc.getName();
+
+						try
+						{
+							return Class.forName(className, true, object.getClass()
+								.getClassLoader());
+						}
+						catch (ClassNotFoundException ex1)
+						{
+							// ignore this exception.
+							log.debug("Class not found by using objects own classloader, trying the IClassResolver");
+						}
+
+
+						Application application = Application.get();
+						IApplicationSettings applicationSettings = application.getApplicationSettings();
+						IClassResolver classResolver = applicationSettings.getClassResolver();
+
+						Class<?> candidate = null;
+						try
+						{
+							candidate = classResolver.resolveClass(className);
+							if (candidate == null)
+							{
+								candidate = super.resolveClass(desc);
+							}
+						}
+						catch (WicketRuntimeException ex)
+						{
+							if (ex.getCause() instanceof ClassNotFoundException)
+							{
+								throw (ClassNotFoundException)ex.getCause();
+							}
+						}
+						return candidate;
+					}
+				};
+				return ois.readObject();
+			}
+			catch (ClassNotFoundException e)
+			{
+				throw new WicketRuntimeException("Internal error cloning object", e);
+			}
+			catch (IOException e)
+			{
+				throw new WicketRuntimeException("Internal error cloning object", e);
+			}
+		}
+	}
+
+	/**
+	 * Creates a new instance using the current application's class resolver. Returns null if
+	 * className is null.
+	 * 
+	 * @param className
+	 *            The full class name
+	 * @return The new object instance
+	 */
+	public static Object newInstance(final String className)
+	{
+		if (!Strings.isEmpty(className))
+		{
+			try
+			{
+				Class<?> c = Classes.resolveClass(className);
+				if (c == null)
+				{
+					throw new WicketRuntimeException("Unable to create " + className);
+				}
+				return c.newInstance();
+			}
+			catch (ClassCastException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+			catch (InstantiationException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+			catch (IllegalAccessException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Serializes an object into a byte array.
+	 * 
+	 * @param object
+	 *            The object
+	 * 
+	 * @param applicationName
+	 *            The name of application - required when serialization and deserialisation happen
+	 *            outside thread in which application thread local is set
+	 * 
+	 * @return The serialized object
+	 */
+	public static byte[] objectToByteArray(final Object object, String applicationName)
+	{
+		try
+		{
+			final ByteArrayOutputStream out = new ByteArrayOutputStream();
+			ObjectOutputStream oos = null;
+			try
+			{
+				oos = objectStreamFactory.newObjectOutputStream(out);
+				oos.writeObject(applicationName);
+				oos.writeObject(object);
+			}
+			finally
+			{
+				if (oos != null)
+				{
+					oos.close();
+				}
+				out.close();
+			}
+			return out.toByteArray();
+		}
+		catch (Exception e)
+		{
+			log.error("Error serializing object " + object.getClass() + " [object=" + object + "]",
+				e);
+		}
+		return null;
+	}
+
+	/**
+	 * Serializes an object into a byte array.
+	 * 
+	 * @param object
+	 *            The object
+	 * @return The serialized object
+	 */
+	public static byte[] objectToByteArray(final Object object)
+	{
+		try
+		{
+			final ByteArrayOutputStream out = new ByteArrayOutputStream();
+			ObjectOutputStream oos = null;
+			try
+			{
+				oos = objectStreamFactory.newObjectOutputStream(out);
+				if (Application.exists())
+				{
+					oos.writeObject(Application.get().getApplicationKey());
+				}
+				else
+				{
+					oos.writeObject(null);
+				}
+				oos.writeObject(object);
+			}
+			finally
+			{
+				if (oos != null)
+				{
+					oos.close();
+				}
+				out.close();
+			}
+			return out.toByteArray();
+		}
+		catch (Exception e)
+		{
+			log.error("Error serializing object " + object.getClass() + " [object=" + object + "]",
+				e);
+		}
+		return null;
+	}
+
+	/**
+	 * Sets the strategy for determining the sizes of objects.
+	 * 
+	 * @param objectSizeOfStrategy
+	 *            the strategy. Pass null to reset to the default.
+	 */
+	public static void setObjectSizeOfStrategy(IObjectSizeOfStrategy objectSizeOfStrategy)
+	{
+		if (objectSizeOfStrategy == null)
+		{
+			WicketObjects.objectSizeOfStrategy = new SerializingObjectSizeOfStrategy();
+		}
+		else
+		{
+			WicketObjects.objectSizeOfStrategy = objectSizeOfStrategy;
+		}
+		log.info("using " + objectSizeOfStrategy + " for calculating object sizes");
+	}
+
+	/**
+	 * Configure this utility class to use the provided {@link IObjectStreamFactory} instance.
+	 * 
+	 * @param objectStreamFactory
+	 *            The factory instance to use. If you pass in null, the
+	 *            {@link DefaultObjectStreamFactory default} will be set (again). Pass null to reset
+	 *            to the default.
+	 */
+	public static void setObjectStreamFactory(IObjectStreamFactory objectStreamFactory)
+	{
+		if (objectStreamFactory == null)
+		{
+			WicketObjects.objectStreamFactory = new IObjectStreamFactory.DefaultObjectStreamFactory();
+		}
+		else
+		{
+			WicketObjects.objectStreamFactory = objectStreamFactory;
+		}
+		log.info("using " + WicketObjects.objectStreamFactory + " for creating object streams");
+	}
+
+	/**
+	 * Computes the size of an object. Note that this is an estimation, never an absolute accurate
+	 * size.
+	 * 
+	 * @param object
+	 *            Object to compute size of
+	 * @return The size of the object in bytes
+	 */
+	public static long sizeof(final Object object)
+	{
+		return objectSizeOfStrategy.sizeOf(object);
+	}
+}

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/string/ComponentStrings.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/string/ComponentStrings.java?rev=924074&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/string/ComponentStrings.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/string/ComponentStrings.java Wed Mar 17 00:34:34 2010
@@ -0,0 +1,112 @@
+/*
+ * 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.util.string;
+
+import org.apache.wicket.Component;
+
+public class ComponentStrings
+{
+
+	private ComponentStrings()
+	{
+
+	}
+
+	/**
+	 * Creates a location stacktrace string representation for the component for reference when the
+	 * render check fails. This method filters out most of the unnecessary parts of the stack trace.
+	 * The message of the <code>location</code> is used as a verb in the rendered string. Use
+	 * "added", "constructed" or similar verbs as values.
+	 * 
+	 * @param component
+	 *            the component that was constructed or added and failed to render
+	 * @param location
+	 *            the location where the component was created or added in the java code.
+	 * @return a string giving the line precise location where the component was added or created.
+	 */
+	public static String toString(final Component component, final Throwable location)
+	{
+		Class<?> componentClass = component.getClass();
+
+		// try to find the component type, if it is an inner element, then get
+		// the parent component.
+		String componentType = componentClass.getName();
+		if (componentType.indexOf('$') >= 0)
+		{
+			componentType = componentClass.getSuperclass().getName();
+		}
+
+		componentType = componentType.substring(componentType.lastIndexOf('.') + 1);
+
+		// create a user friendly message, using the location's message as a
+		// differentiator for the message (e.g. "component foo was ***added***"
+		// or "component foo was ***created***")
+		AppendingStringBuffer sb = new AppendingStringBuffer("The " + componentType.toLowerCase() +
+			" with id '" + component.getId() + "' that failed to render was " +
+			location.getMessage() + "\n");
+
+		// a list of stacktrace elements that need to be skipped in the location
+		// stack trace
+		String[] skippedElements = new String[] { "org.apache.wicket.MarkupContainer",
+				"org.apache.wicket.Component", "org.apache.wicket.markup" };
+
+		// a list of stack trace elements that stop the traversal of the stack
+		// trace
+		String[] breakingElements = new String[] { "org.apache.wicket.protocol.http.WicketServlet",
+				"org.apache.wicket.protocol.http.WicketFilter", "java.lang.reflect" };
+
+		StackTraceElement[] trace = location.getStackTrace();
+		for (int i = 0; i < trace.length; i++)
+		{
+			String traceString = trace[i].toString();
+			if (shouldSkip(traceString, skippedElements))
+			{
+				// don't print this line, is wicket internal
+				continue;
+			}
+
+			if (!(traceString.startsWith("sun.reflect.") && i > 1))
+			{
+				// filter out reflection API calls from the stack trace
+				if (traceString.indexOf("java.lang.reflect") < 0)
+				{
+					sb.append("     at ");
+					sb.append(traceString);
+					sb.append("\n");
+				}
+				if (shouldSkip(traceString, breakingElements))
+				{
+					break;
+				}
+			}
+		}
+		sb.append("\n");
+		return sb.toString();
+	}
+
+	private static boolean shouldSkip(String text, String[] filters)
+	{
+		for (int i = 0; i < filters.length; i++)
+		{
+			if (text.indexOf(filters[i]) >= 0)
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+}

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/string/ComponentStrings.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: wicket/trunk/wicket/src/test/java/org/apache/wicket/util/lang/ObjectsTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/util/lang/ObjectsTest.java?rev=924074&r1=924073&r2=924074&view=diff
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/util/lang/ObjectsTest.java (original)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/util/lang/ObjectsTest.java Wed Mar 17 00:34:34 2010
@@ -67,7 +67,7 @@ public class ObjectsTest extends WicketT
 	 */
 	public void testCloneNull()
 	{
-		Object clone = Objects.cloneModel(null);
+		Object clone = WicketObjects.cloneModel(null);
 		assertEquals(null, clone);
 	}
 
@@ -78,7 +78,7 @@ public class ObjectsTest extends WicketT
 	{
 		String cloneMe = "Mini-me";
 
-		Object clone = Objects.cloneModel(cloneMe);
+		Object clone = WicketObjects.cloneModel(cloneMe);
 		assertEquals(cloneMe, clone);
 		assertNotSame(cloneMe, clone);
 	}
@@ -92,7 +92,7 @@ public class ObjectsTest extends WicketT
 
 		try
 		{
-			Objects.cloneModel(cloneMe);
+			WicketObjects.cloneModel(cloneMe);
 			fail("Exception expected");
 		}
 		catch (RuntimeException e)
@@ -109,7 +109,7 @@ public class ObjectsTest extends WicketT
 	{
 		PropertyModel<String> pm = new PropertyModel<String>(new TextField<String>("test",
 			new Model<String>("test")), "modelObject");
-		PropertyModel<String> pm2 = (PropertyModel<String>)Objects.cloneModel(pm);
+		PropertyModel<String> pm2 = (PropertyModel<String>)WicketObjects.cloneModel(pm);
 		assertTrue(pm.getObject() == pm2.getObject());
 	}
 
@@ -121,7 +121,7 @@ public class ObjectsTest extends WicketT
 		CloneObject cloneMe = new CloneObject();
 		cloneMe.nr = 1;
 
-		Object clone = Objects.cloneModel(cloneMe);
+		Object clone = WicketObjects.cloneModel(cloneMe);
 		assertEquals(cloneMe, clone);
 		assertNotSame(cloneMe, clone);
 	}