Author: tchemit Date: 2009-10-29 02:42:54 +0100 (Thu, 29 Oct 2009) New Revision: 1614 Added: branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorProvider.java branches/jaxx-2.X/jaxx-runtime/src/test/java/jaxx/runtime/decorator/DecoratorProviderTest.java Modified: branches/jaxx-2.X/jaxx-runtime/ branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorUtils.java branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/JXPathDecorator.java Log: - add a DecoratorProvider to store your decorators - deprecate all states in DecoratorUtils (use a DecoratorProvider to store decorators) Property changes on: branches/jaxx-2.X/jaxx-runtime ___________________________________________________________________ Modified: svn:ignore - target *.log *.iml + target *.log Added: branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorProvider.java =================================================================== --- branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorProvider.java (rev 0) +++ branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorProvider.java 2009-10-29 01:42:54 UTC (rev 1614) @@ -0,0 +1,226 @@ +package jaxx.runtime.decorator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * A decorator provider. + * <p/> + * Implements the method {@link #loadDecorators()} to fill the decorators availables. + * <p/> + * Then can obtain decorator via the methods {@code getDecorator(...)} + * <p/> + * User: chemit + * Date: 28 oct. 2009 + * Time: 19:40:48 + */ +public abstract class DecoratorProvider { + + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JXPathDecorator.class); + /** + * Registred decorators. + */ + protected List<DecoratorContext<?>> decorators; + + public DecoratorProvider() { + loadDecorators(); + } + + /** + * Load all decorators of the provider + */ + protected abstract void loadDecorators(); + + /** + * Obtain a decorator for the given object. + * + * @param object object of decorated object + * @param <O> object of decorated object + * @return the decorator or {@code null} if not found + */ + @SuppressWarnings({"unchecked"}) + public <O> Decorator<O> getDecorator(O object) { + return getDecorator(object, null); + } + + /** + * Obtain a decorator given a object and an extra name to qualify the context. + * + * @param object object of decorated object + * @param name extra name to qualify the decorator to use + * @param <O> object of decorated object + * @return the decorator or {@code null} if not found + */ + @SuppressWarnings({"unchecked"}) + public <O> Decorator<O> getDecorator(O object, String name) { + Class<O> k = (Class<O>) object.getClass(); + return getDecorator(k, name); + } + + /** + * Obtain a decorator given a type. + * + * @param type type of decorated object + * @param <O> type of decorated object + * @return the decorator or {@code null} if not found + */ + public <O> Decorator<O> getDecorator(Class<O> type) { + return getDecorator(type, null); + } + + /** + * Obtain a decorator given a type and a extra name. + * + * @param type type of decorated object + * @param name extra name to qualify the decorator to use + * @param <O> type of decorated object + * @return the decorator or {@code null} if not found + */ + public <O> Decorator<O> getDecorator(Class<O> type, String name) { + DecoratorContext<O> d = getDecoratorContext(type, name); + return d == null ? null : d.getDecorator(); + } + + public void reload() { + clear(); + loadDecorators(); + } + + public void clear() { + if (decorators != null) { + decorators.clear(); + } + } + + protected void registerPropertyDecorator(Class<?> klass, String expression) { + registerPropertyDecorator(klass, null, expression); + } + + protected void registerJXPathDecorator(Class<?> klass, String expression) { + registerJXPathDecorator(klass, null, expression); + } + + protected void registerMultiJXPathDecorator(Class<?> klass, String expression, String separator, String separatorReplacement) { + registerMultiJXPathDecorator(klass, null, expression, separator, separatorReplacement); + } + + protected void registerPropertyDecorator(Class<?> klass, String name, String expression) { + Decorator<?> decorator = DecoratorUtils.newPropertyDecorator(klass, expression); + registerDecorator(name, decorator); + } + + protected void registerJXPathDecorator(Class<?> klass, String name, String expression) { + Decorator<?> decorator = DecoratorUtils.newJXPathDecorator(klass, expression); + registerDecorator(name, decorator); + } + + protected void registerMultiJXPathDecorator(Class<?> klass, String name, String expression, String separator, String separatorReplacement) { + Decorator<?> decorator = DecoratorUtils.newMultiJXPathDecorator(klass, expression, separator, separatorReplacement); + registerDecorator(name, decorator); + } + + protected void registerDecorator(Decorator<?> decorator) { + registerDecorator(null, decorator); + } + + /** + * Register a new decorator in the cache of the provider. + * + * @param <T> type of data decorated + * @param context the name decorator + * @param decorator the decorator to register + */ + protected <T> void registerDecorator(String context, Decorator<T> decorator) { + + // obtain the decorator context + DecoratorContext<?> result = getDecoratorContext(decorator.getInternalClass(), context); + + if (result != null) { + throw new IllegalArgumentException("there is an already register decorator with context " + result); + } + + DecoratorContext<T> decoratorContext = new DecoratorContext<T>(context, decorator); + if (log.isDebugEnabled()) { + log.debug(decoratorContext); + } + getDecorators().add(decoratorContext); + } + + protected List<DecoratorContext<?>> getDecorators() { + if (decorators == null) { + decorators = new ArrayList<DecoratorContext<?>>(); + } + return decorators; + } + + @SuppressWarnings({"unchecked"}) + protected <T> DecoratorContext<T> getDecoratorContext(Class<T> type, String context) { + DecoratorContext<T> result = null; + if (decorators != null) { + for (DecoratorContext<?> d : decorators) { + if (type == null) { + if (d.accept(context)) { + result = (DecoratorContext<T>) d; + break; + } + continue; + } + if (d.accept(type, context)) { + result = (DecoratorContext<T>) d; + break; + } + } + } + return result; + } + + public static class DecoratorContext<T> { + + /** + * the context name of the decorator + */ + final String context; + /** + * the decorator + */ + final Decorator<T> decorator; + + public DecoratorContext(String context, Decorator<T> decorator) { + this.context = context; + this.decorator = decorator; + } + + public String getContext() { + return context; + } + + public Decorator<T> getDecorator() { + return decorator; + } + + public Class<T> getType() { + return decorator.getInternalClass(); + } + + public boolean accept(Class<?> type, String context) { + boolean accept = getType().isAssignableFrom(type) && accept(context); + return accept; + } + + public boolean accept(String context) { + return ((this.context == null && context == null) || (this.context != null && this.context.equals(context))); + } + + @Override + public String toString() { + return super.toString() + "<type: " + getType().getName() + ", context :" + context + ">"; + } + } + +} Property changes on: branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorProvider.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Modified: branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorUtils.java =================================================================== --- branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorUtils.java 2009-10-28 07:54:21 UTC (rev 1613) +++ branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/DecoratorUtils.java 2009-10-29 01:42:54 UTC (rev 1614) @@ -20,18 +20,14 @@ */ package jaxx.runtime.decorator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.StringTokenizer; +import jaxx.runtime.decorator.JXPathDecorator.Context; import jaxx.runtime.decorator.JXPathDecorator.JXPathComparator; -import jaxx.runtime.decorator.JXPathDecorator.Context; +import java.util.*; + /** - * * Some usefull methods on {@link Decorator} to create, decorators and obtain decorators. - * + * <p/> * To create a new decorator, use one of the methods : * <ul> * <li>{@link #newPropertyDecorator(Class, String)}</li> @@ -40,7 +36,7 @@ * <li>{@link #newMultiJXPathDecorator(Class, String, String, String)})</li> * </ul> * <p/> - * + * <p/> * To register a new decorator, use the method {@link #register(String, Decorator)}. * <p/> * To obtain a registred decorator, use the method {@link #get(String)} @@ -50,7 +46,7 @@ * To sort a list of data, using a {@link JXPathDecorator}, use the method * {@link #sort(JXPathDecorator, List, int)}. * <p/> - * + * * @author tony * @since 1.7.2 (was previously {@code jaxx.runtime.DecoratorUtils}) */ @@ -58,11 +54,13 @@ /** * Registred decorators. + * @deprecated prefer use a {@link DecoratorProvider} */ + @Deprecated protected static List<DecoratorContext<?>> decorators; /** - * Factory method to instanciate a new {@link PropertyDecorator} for the + * Factory method to instanciate a new {@link PropertyDecorator} for the * given class {@code internlaClass} and a readable property name. * * @param internalClass the class of the objects decorated by the new decorator @@ -104,17 +102,17 @@ } public static <O> MultiJXPathDecorator<O> newMultiJXPathDecorator(Class<O> internalClass, - String expression, - String separator) + String expression, + String separator) throws IllegalArgumentException, NullPointerException { return newMultiJXPathDecorator(internalClass, expression, separator, separator); } public static <O> MultiJXPathDecorator<O> newMultiJXPathDecorator(Class<O> internalClass, - String expression, - String separator, - String separatorReplacement) + String expression, + String separator, + String separatorReplacement) throws IllegalArgumentException, NullPointerException { Context<O>[] contexts = createMultiJXPathContext(expression, separator, separatorReplacement); @@ -122,11 +120,13 @@ return new MultiJXPathDecorator<O>(internalClass, expression, separator, separatorReplacement, contexts); } + @Deprecated public static <T> Decorator<T> get(String context) { Decorator<T> result = get(null, context); return result; } + @Deprecated public static <T> Decorator<T> get(Class<T> type, String context) { DecoratorContext<T> decoratorContext = getDecoratorContext(type, context); Decorator<T> result = decoratorContext == null ? null : decoratorContext.getDecorator(); @@ -136,10 +136,11 @@ /** * Register a new decorator in the cache. * - * @param <T> type of data decorated - * @param context the name decorator + * @param <T> type of data decorated + * @param context the name decorator * @param decorator the decorator to register */ + @Deprecated public static <T> void register(String context, Decorator<T> decorator) { DecoratorContext<T> result = getDecoratorContext(decorator.getInternalClass(), context); @@ -154,6 +155,7 @@ decorators.add(new DecoratorContext<T>(context, decorator)); } + @Deprecated public static void clear() { if (decorators != null) { decorators.clear(); @@ -164,7 +166,7 @@ * Sort a list of data based on the first token property of a given context * in a given decorator. * - * @param <O> type of data to sort + * @param <O> type of data to sort * @param decorator the decorator to use to sort * @param datas the list of data to sort * @param pos the index of context to used in decorator to obtain sorted property. @@ -188,6 +190,7 @@ } @SuppressWarnings({"unchecked"}) + @Deprecated protected static <T> DecoratorContext<T> getDecoratorContext(Class<T> type, String context) { DecoratorContext<T> result = null; if (decorators != null) { @@ -208,9 +211,16 @@ return result; } + @Deprecated public static class DecoratorContext<T> { + /** + * the context name of the decorator + */ final String context; + /** + * the decorator + */ final Decorator<T> decorator; public DecoratorContext(String context, Decorator<T> decorator) { Modified: branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/JXPathDecorator.java =================================================================== --- branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/JXPathDecorator.java 2009-10-28 07:54:21 UTC (rev 1613) +++ branches/jaxx-2.X/jaxx-runtime/src/main/java/jaxx/runtime/decorator/JXPathDecorator.java 2009-10-29 01:42:54 UTC (rev 1614) @@ -24,14 +24,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** - * JXPath decorator based on {@link String#format(String, Object[])} method. + * JXPath decorator based on {@link String#format(String, Object...)} method. * <p/> * To use it, give to him a expression where all jxpath to apply on bean are boxed in <code>${}</code>. * <p/> @@ -46,10 +42,10 @@ * assert "expr = %1$s" == d.toString(d); * </pre> * + * @author chemit * @param <O> type of data to decorate - * @author chemit * @see Decorator - * @since 1.7.2 (was previously {@code jaxx.runtime.JXPathDecorat}) + * @since 1.7.2 (was previously {@code jaxx.runtime.JXPathDecorator}) */ public class JXPathDecorator<O> extends Decorator<O> { @@ -58,11 +54,17 @@ * Logger */ private static final Log log = LogFactory.getLog(JXPathDecorator.class); - /** the computed context of the decorator */ + /** + * the computed context of the decorator + */ protected Context<O> context; - /** nb jxpath tokens to compute */ + /** + * nb jxpath tokens to compute + */ protected int nbToken; - /** the initial expression used to compute the decorator context. */ + /** + * the initial expression used to compute the decorator context. + */ protected String initialExpression; protected JXPathDecorator(Class<O> internalClass, String expression, Context<O> context) throws IllegalArgumentException, NullPointerException { @@ -174,11 +176,13 @@ public static class Context<O> implements java.io.Serializable { /** - * expression to format using {@link String#format(String, Object[])}, all variables are compute + * expression to format using {@link String#format(String, Object...)}, all variables are compute * using using the jxpath tokens. */ protected String expression; - /** list of jxpath tokens to apply on expression */ + /** + * list of jxpath tokens to apply on expression + */ protected String[] tokens; protected transient Comparator<O> comparator; private static final long serialVersionUID = 1L; Added: branches/jaxx-2.X/jaxx-runtime/src/test/java/jaxx/runtime/decorator/DecoratorProviderTest.java =================================================================== --- branches/jaxx-2.X/jaxx-runtime/src/test/java/jaxx/runtime/decorator/DecoratorProviderTest.java (rev 0) +++ branches/jaxx-2.X/jaxx-runtime/src/test/java/jaxx/runtime/decorator/DecoratorProviderTest.java 2009-10-29 01:42:54 UTC (rev 1614) @@ -0,0 +1,153 @@ +package jaxx.runtime.decorator; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +/** + * User: chemit + * Date: 28 oct. 2009 + * Time: 21:28:46 + */ +public class DecoratorProviderTest { + private static final String BY_NAME = "name"; + + static class MyDecoratorProvider extends DecoratorProvider { + + @Override + protected void loadDecorators() { + + registerPropertyDecorator(File.class, "name"); + registerPropertyDecorator(File.class, BY_NAME, "parent"); + + + registerJXPathDecorator(Class.class, "${simpleName}$s"); + registerJXPathDecorator(Class.class, BY_NAME, "${name}$s"); + + registerMultiJXPathDecorator(Data.class, "${name}$s", "-", " "); + registerMultiJXPathDecorator(Data.class, BY_NAME, "${pos}$d", "-", " "); + } + } + + static DecoratorProvider provider; + + @BeforeClass + public static void beforeTest() throws Exception { + provider = new MyDecoratorProvider(); + } + + @Test + public void testGetDecoratorByObject() throws Exception { + + File f = new File("myFile"); + Data d = new Data(0, "name"); + Class<?> k = File.class; + + Decorator<File> fileDecorator = provider.getDecorator(f); + Assert.assertNotNull(fileDecorator); + Assert.assertEquals(File.class, fileDecorator.getInternalClass()); + Assert.assertEquals("myFile", fileDecorator.toString(f)); + + Decorator<?> classDecorator = provider.getDecorator(Class.class); + Assert.assertNotNull(classDecorator); + Assert.assertEquals(Class.class, classDecorator.getInternalClass()); + Assert.assertEquals("File", classDecorator.toString(k)); + + Decorator<Data> dataDecorator = provider.getDecorator(d); + Assert.assertNotNull(dataDecorator); + Assert.assertEquals(Data.class, dataDecorator.getInternalClass()); + Assert.assertEquals("name", dataDecorator.toString(d)); + } + + @Test + public void testGetDecoratorByObjectAndName() throws Exception { + + File f = new File("myFile"); + Data d = new Data(0, "name"); + Class<?> k = File.class; + + Decorator<File> fileDecorator = provider.getDecorator(f, BY_NAME); + Assert.assertNotNull(fileDecorator); + Assert.assertEquals(File.class, fileDecorator.getInternalClass()); + Assert.assertEquals("null", fileDecorator.toString(f)); + + Decorator<Class> classDecorator = provider.getDecorator(Class.class, BY_NAME); + Assert.assertNotNull(classDecorator); + Assert.assertEquals(Class.class, classDecorator.getInternalClass()); + Assert.assertEquals("java.io.File", classDecorator.toString(k)); + + + Decorator<Data> dataDecorator = provider.getDecorator(d, BY_NAME); + Assert.assertNotNull(dataDecorator); + Assert.assertEquals(Data.class, dataDecorator.getInternalClass()); + Assert.assertEquals("0", dataDecorator.toString(d)); + } + + @Test + public void testGetDecoratorByType() throws Exception { + + File f = new File("myFile"); + Data d = new Data(0, "name"); + Class<?> k = File.class; + + Decorator<File> fileDecorator = provider.getDecorator(File.class); + Assert.assertNotNull(fileDecorator); + Assert.assertEquals(File.class, fileDecorator.getInternalClass()); + Assert.assertEquals("myFile", fileDecorator.toString(f)); + + Decorator<Class> classDecorator = provider.getDecorator(Class.class); + Assert.assertNotNull(classDecorator); + Assert.assertEquals(Class.class, classDecorator.getInternalClass()); + Assert.assertEquals("File", classDecorator.toString(k)); + + Decorator<Data> dataDecorator = provider.getDecorator(Data.class); + Assert.assertNotNull(dataDecorator); + Assert.assertEquals(Data.class, dataDecorator.getInternalClass()); + Assert.assertEquals("name", dataDecorator.toString(d)); + } + + @Test + public void testGetDecoratorByTypeAndName() throws Exception { + File f = new File("myFile"); + Data d = new Data(0, "name"); + Class<?> k = File.class; + + Decorator<File> fileDecorator = provider.getDecorator(File.class, BY_NAME); + Assert.assertNotNull(fileDecorator); + Assert.assertEquals(File.class, fileDecorator.getInternalClass()); + Assert.assertEquals("null", fileDecorator.toString(f)); + + Decorator<Class> classDecorator = provider.getDecorator(Class.class, BY_NAME); + Assert.assertNotNull(classDecorator); + Assert.assertEquals(Class.class, classDecorator.getInternalClass()); + Assert.assertEquals("java.io.File", classDecorator.toString(k)); + + + Decorator<Data> dataDecorator = provider.getDecorator(Data.class, BY_NAME); + Assert.assertNotNull(dataDecorator); + Assert.assertEquals(Data.class, dataDecorator.getInternalClass()); + Assert.assertEquals("0", dataDecorator.toString(d)); + } + + + @Test + public void testReload() throws Exception { + + int nb = provider.getDecorators().size(); + Assert.assertTrue(nb > 0); + + provider.reload(); + + Assert.assertEquals(nb, provider.getDecorators().size()); + } + + @Test + public void testClear() throws Exception { + provider.clear(); + + Assert.assertTrue(provider.getDecorators().isEmpty()); + } + +} Property changes on: branches/jaxx-2.X/jaxx-runtime/src/test/java/jaxx/runtime/decorator/DecoratorProviderTest.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL