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);
}