Author: julien_viet
Date: 2010-01-12 17:48:45 -0500 (Tue, 12 Jan 2010)
New Revision: 1241
Modified:
portal/trunk/webui/core/pom.xml
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/UIComponent.java
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/FormattableValueRenderer.java
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRenderer.java
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRendererRegistry.java
portal/trunk/webui/core/src/test/java/org/exoplatform/webui/core/renderers/ValueRendererRegistryTestCase.java
Log:
fix code to be thread safe and type safe
Modified: portal/trunk/webui/core/pom.xml
===================================================================
--- portal/trunk/webui/core/pom.xml 2010-01-12 17:28:38 UTC (rev 1240)
+++ portal/trunk/webui/core/pom.xml 2010-01-12 22:48:45 UTC (rev 1241)
@@ -19,71 +19,59 @@
-->
-<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
- <parent>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.exoplatform.portal</groupId>
+ <artifactId>exo.portal.webui</artifactId>
+ <version>3.0.0-Beta05-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>exo.portal.webui.core</artifactId>
+ <packaging>jar</packaging>
+ <name>GateIn Portal WebUI Core</name>
+
+ <dependencies>
+ <dependency>
<groupId>org.exoplatform.portal</groupId>
- <artifactId>exo.portal.webui</artifactId>
+ <artifactId>exo.portal.component.web</artifactId>
<version>3.0.0-Beta05-SNAPSHOT</version>
- </parent>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.common</groupId>
+ <artifactId>common-common</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jibx</groupId>
+ <artifactId>maven-jibx-plugin</artifactId>
+ <version>${org.jibx.version}</version>
+ <configuration>
+ <directory>src/main/resources</directory>
+ <includes>
+ <includes>binding.xml</includes>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>bind</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>exo.portal.webui.core</artifactId>
- <packaging>jar</packaging>
- <name>GateIn Portal WebUI Core</name>
-
- <dependencies>
- <dependency>
- <groupId>org.exoplatform.portal</groupId>
- <artifactId>exo.portal.component.web</artifactId>
- <version>3.0.0-Beta05-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.gatein.common</groupId>
- <artifactId>common-common</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.jibx</groupId>
- <artifactId>maven-jibx-plugin</artifactId>
- <version>${org.jibx.version}</version>
- <configuration>
- <directory>src/main/resources</directory>
- <includes>
- <includes>binding.xml</includes>
- </includes>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>bind</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <!-- -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <compilerArgument>-proc:none</compilerArgument>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>org/exoplatform/webui/test/**</exclude>
- </excludes>
- </configuration>
- </plugin>
-
- </plugins>
- </build>
+ <!-- -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgument>-proc:none</compilerArgument>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
Modified:
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/UIComponent.java
===================================================================
---
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/UIComponent.java 2010-01-12
17:28:38 UTC (rev 1240)
+++
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/UIComponent.java 2010-01-12
22:48:45 UTC (rev 1241)
@@ -463,12 +463,12 @@
return null;
}
- public ValueRenderer getRendererFor(Object value)
+ public ValueRenderer<?> getRendererFor(Object value)
{
- return rendererRegistry.getRendererFor(value == null ? null : value.getClass());
+ return rendererRegistry.getRendererFor(value);
}
- public <ValueType> void registerRendererFor(ValueRenderer<ValueType>
renderer, Class<? extends ValueType> valueType)
+ public <V> void registerRendererFor(ValueRenderer<V> renderer, Class<?
extends V> valueType)
{
rendererRegistry.registerRendererFor(renderer, valueType);
}
Modified:
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/FormattableValueRenderer.java
===================================================================
---
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/FormattableValueRenderer.java 2010-01-12
17:28:38 UTC (rev 1240)
+++
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/FormattableValueRenderer.java 2010-01-12
22:48:45 UTC (rev 1241)
@@ -26,26 +26,38 @@
import java.text.Format;
/**
+ *
* @author <a href="mailto:chris.laprun@jboss.com">Chris
Laprun</a>
* @version $Revision$
*/
-public class FormattableValueRenderer extends ValueRenderer<Object>
+public class FormattableValueRenderer<V> extends ValueRenderer<V>
{
- private Format format;
+
private String cssClass;
+ private Format formatPrototype;
+
+ private final ThreadLocal<Format> format = new ThreadLocal<Format>()
+ {
+ @Override
+ public Format get()
+ {
+ return (Format)formatPrototype.clone();
+ }
+ };
+
public FormattableValueRenderer(Format format, String cssClass)
{
- this.format = format;
+ this.formatPrototype = format;
this.cssClass = cssClass;
}
@Override
- public String render(Object value)
+ public String render(V value)
{
- if (format != null)
+ if (formatPrototype != null)
{
- return format.format(value);
+ return format.get().format(value);
}
else
{
@@ -54,7 +66,7 @@
}
@Override
- public String getCSSClassFor(Object value)
+ public String getCSSClassFor(V value)
{
if (cssClass != null)
{
Modified:
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRenderer.java
===================================================================
---
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRenderer.java 2010-01-12
17:28:38 UTC (rev 1240)
+++
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRenderer.java 2010-01-12
22:48:45 UTC (rev 1241)
@@ -29,12 +29,12 @@
* @author <a href="mailto:chris.laprun@jboss.com">Chris
Laprun</a>
* @version $Revision$
*/
-public class ValueRenderer<ValueType>
+public class ValueRenderer<V>
{
public static final String EMPTY = "";
public static final String DEFAULT_CSS_CLASS = "Text";
public static final ValueRenderer<Object> DEFAULT_RENDERER = new
ValueRenderer<Object>();
- public static final ValueRenderer NULL_RENDERER = new ValueRenderer()
+ public static final ValueRenderer<Object> NULL_RENDERER = new
ValueRenderer<Object>()
{
@Override
public String render(Object value)
@@ -50,13 +50,13 @@
};
- public String render(ValueType value)
+ public String render(V value)
{
ParameterValidation.throwIllegalArgExceptionIfNull(value, "Value");
return value.toString();
}
- public String getCSSClassFor(ValueType value)
+ public String getCSSClassFor(V value)
{
return DEFAULT_CSS_CLASS;
}
Modified:
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRendererRegistry.java
===================================================================
---
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRendererRegistry.java 2010-01-12
17:28:38 UTC (rev 1240)
+++
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/core/renderers/ValueRendererRegistry.java 2010-01-12
22:48:45 UTC (rev 1241)
@@ -28,9 +28,7 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
/**
* @author <a href="mailto:chris.laprun@jboss.com">Chris
Laprun</a>
@@ -38,12 +36,12 @@
*/
public class ValueRendererRegistry
{
- private static Map<Class, ValueRenderer> DEFAULT_RENDERERS;
- private Map<Class, ValueRenderer> renderers;
+ private static Map<Class<?>, ValueRenderer<?>> DEFAULT_RENDERERS;
+ private Map<Class<?>, ValueRenderer<?>> renderers;
static
{
- FormattableValueRenderer numberRenderer = new FormattableValueRenderer(null,
"number");
+ FormattableValueRenderer<Number> numberRenderer = new
FormattableValueRenderer<Number>(null, "number");
registerDefaultRendererFor(numberRenderer, Number.class);
registerDefaultRendererFor(numberRenderer, Byte.class);
registerDefaultRendererFor(numberRenderer, Double.class);
@@ -52,15 +50,30 @@
registerDefaultRendererFor(numberRenderer, Long.class);
registerDefaultRendererFor(numberRenderer, Short.class);
- FormattableValueRenderer dateRenderer = new FormattableValueRenderer(new
SimpleDateFormat("HH:mm:ss yyyy-MM-dd"), "Datetime");
+ FormattableValueRenderer<Date> dateRenderer = new
FormattableValueRenderer<Date>(new SimpleDateFormat("HH:mm:ss
yyyy-MM-dd"), "Datetime");
registerDefaultRendererFor(dateRenderer, Date.class);
registerDefaultRendererFor(dateRenderer, java.sql.Date.class);
registerDefaultRendererFor(dateRenderer, Time.class);
registerDefaultRendererFor(dateRenderer, Timestamp.class);
}
+ public <V> ValueRenderer<? super V> getRendererFor(V value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ else
+ {
+ Class<?> valueType = value.getClass();
+ // This is almost OK
+ @SuppressWarnings("unchecked")
+ ValueRenderer<? super V> renderer = (ValueRenderer<? super
V>)getRendererFor(valueType);
+ return renderer;
+ }
+ }
- public <ValueType> ValueRenderer<ValueType> getRendererFor(Class<?
extends ValueType> valueType)
+ public <V> ValueRenderer<? super V> getRendererFor(Class<V>
valueType)
{
if (valueType == null)
{
@@ -68,7 +81,7 @@
}
// first check local renderers
- ValueRenderer renderer = getRendererIn(valueType, renderers);
+ ValueRenderer<? super V> renderer = getRendererIn(valueType, renderers);
if (renderer == null)
{
// then globally registered ones
@@ -77,15 +90,24 @@
// if we haven't found a match, check inheritance and return first match
if (renderer == null)
{
- for (Map.Entry<Class, ValueRenderer> entry :
DEFAULT_RENDERERS.entrySet())
+ for (Map.Entry<Class<?>, ValueRenderer<?>> entry :
DEFAULT_RENDERERS.entrySet())
{
- Class type = entry.getKey();
+ Class<?> type = entry.getKey();
if (type.isAssignableFrom(valueType))
{
- renderer = entry.getValue();
+ // the valueType class is assignable to the type class which mean that
+ // the type class is a super class of the valueType class
+ // This cast is OK
+ @SuppressWarnings("unchecked")
+ ValueRenderer<? super V> tmp = (ValueRenderer<? super V>)
entry.getValue();
+ renderer = tmp;
+ // OK
+ @SuppressWarnings("unchecked")
+ Class<? extends V> asSubclassOfV = (Class<? extends
V>)type;
+
// add the found renderers to the default ones so that further look-ups
will be faster
- registerDefaultRendererFor(renderer, type);
+ registerDefaultRendererFor(renderer, asSubclassOfV);
break;
}
@@ -103,32 +125,40 @@
return renderer;
}
- public static <ValueType> void
registerDefaultRendererFor(ValueRenderer<ValueType> renderer, Class<? extends
ValueType> type)
+ public static <V> void registerDefaultRendererFor(ValueRenderer<? super V>
renderer, Class<? extends V> type)
{
DEFAULT_RENDERERS = registerIn(renderer, type, DEFAULT_RENDERERS);
}
- public <ValueType> void registerRendererFor(ValueRenderer<ValueType>
renderer, Class<? extends ValueType> type)
+ public <V> void registerRendererFor(ValueRenderer<V> renderer, Class<?
extends V> type)
{
renderers = registerIn(renderer, type, renderers);
}
- private static <ValueType> Map<Class, ValueRenderer>
registerIn(ValueRenderer<ValueType> renderer, Class<? extends ValueType> type,
Map<Class, ValueRenderer> renderers)
+ private static <V> Map<Class<?>, ValueRenderer<?>>
registerIn(
+ ValueRenderer<? super V> renderer,
+ Class<? extends V> type,
+ Map<Class<?>, ValueRenderer<?>> renderers)
{
ParameterValidation.throwIllegalArgExceptionIfNull(type, "Value class");
ParameterValidation.throwIllegalArgExceptionIfNull(renderer,
"Renderer");
if (renderers == null)
{
- renderers = new HashMap<Class, ValueRenderer>(7);
+ renderers = new HashMap<Class<?>, ValueRenderer<?>>(7);
}
+ else
+ {
+ // Copy on write for thread safety
+ renderers = new HashMap<Class<?>,
ValueRenderer<?>>(renderers);
+ }
renderers.put(type, renderer);
return renderers;
}
- private static ValueRenderer getRendererIn(Class valueType, Map<Class,
ValueRenderer> renderers)
+ private static <V> ValueRenderer<? super V> getRendererIn(Class<V>
valueType, Map<Class<?>, ValueRenderer<?>> renderers)
{
if (renderers == null)
{
@@ -136,7 +166,10 @@
}
else
{
- return renderers.get(valueType);
+ // this cast is OK
+ @SuppressWarnings("unchecked")
+ ValueRenderer<? super V> renderer = (ValueRenderer<? super V>)
renderers.get(valueType);
+ return renderer;
}
}
}
Modified:
portal/trunk/webui/core/src/test/java/org/exoplatform/webui/core/renderers/ValueRendererRegistryTestCase.java
===================================================================
---
portal/trunk/webui/core/src/test/java/org/exoplatform/webui/core/renderers/ValueRendererRegistryTestCase.java 2010-01-12
17:28:38 UTC (rev 1240)
+++
portal/trunk/webui/core/src/test/java/org/exoplatform/webui/core/renderers/ValueRendererRegistryTestCase.java 2010-01-12
22:48:45 UTC (rev 1241)
@@ -35,18 +35,16 @@
public class ValueRendererRegistryTestCase extends TestCase
{
private ValueRendererRegistry registry;
- private ValueRenderer renderer;
@Override
protected void setUp() throws Exception
{
registry = new ValueRendererRegistry();
- renderer = null;
}
public void testGetDefaultRenderer()
{
- renderer = registry.getRendererFor(Object.class);
+ ValueRenderer<? super Object> renderer =
registry.getRendererFor(Object.class);
assertEquals(ValueRenderer.DEFAULT_RENDERER, renderer);
assertEquals(ValueRenderer.DEFAULT_CSS_CLASS, renderer.getCSSClassFor(new
Object()));
}
@@ -55,10 +53,10 @@
{
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
String css = "testDate";
- registry.registerRendererFor(new FormattableValueRenderer(dateFormat, css),
TestDate.class);
+ registry.registerRendererFor(new FormattableValueRenderer<Date>(dateFormat,
css), TestDate.class);
TestDate date = new TestDate(2010, 1, 12, 13, 37, 0);
- renderer = registry.getRendererFor(date.getClass());
+ ValueRenderer<? super TestDate> renderer = registry.getRendererFor(date);
assertNotNull(renderer);
assertEquals(dateFormat.format(date), renderer.render(date));
assertEquals(css, renderer.getCSSClassFor(date));
@@ -66,7 +64,7 @@
public void testRenderNullValue()
{
- renderer = registry.getRendererFor(null);
+ ValueRenderer<? super Object> renderer = registry.getRendererFor(null);
assertNotNull(renderer);
assertEquals(ValueRenderer.EMPTY, renderer.render(null));
assertEquals(ValueRenderer.EMPTY, renderer.getCSSClassFor(null));
@@ -74,17 +72,17 @@
public void testSupportsPreviousUIGridScenario()
{
- renderer = registry.getRendererFor(Integer.class);
+ ValueRenderer<? super Integer> renderer =
registry.getRendererFor(Integer.class);
assertNotNull(renderer);
assertEquals("100", renderer.render(100));
assertEquals("number", renderer.getCSSClassFor(100));
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss
yyyy-MM-dd");
TestDate date = new TestDate(2010, 1, 12, 13, 37, 0);
- renderer = registry.getRendererFor(date.getClass());
+ ValueRenderer<? super TestDate> renderer2 = registry.getRendererFor(date);
assertNotNull(renderer);
- assertEquals(dateFormat.format(date), renderer.render(date));
- assertEquals("Datetime", renderer.getCSSClassFor(date));
+ assertEquals(dateFormat.format(date), renderer2.render(date));
+ assertEquals("Datetime", renderer2.getCSSClassFor(date));
}
private static class TestDate extends Date