From 5582d07a1ba9821cc789ea63b71f246e89d13cae Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Tue, 9 Aug 2011 17:23:15 +0200 Subject: [PATCH] id prefixes are now done at the very last moment instead of when an item is added. This provides more logical behavior in the api becuase the ids are not modified. --- .../org/wamblee/xmlrouter/config/Config.java | 6 ++ .../xmlrouter/impl/CompositeConfig.java | 21 +++- .../xmlrouter/impl/CompositeRouterConfig.java | 7 +- .../wamblee/xmlrouter/impl/ConfigImpl.java | 10 +- .../impl/IdentifiablePrefixProxyFactory.java | 83 ++++++++++++++ .../xmlrouter/impl/SingleRouterConfig.java | 12 +-- .../impl/XMLRouterConfigService.java | 4 +- .../xmlrouter/impl/CompositeConfigTest.java | 102 +++++++++++------- .../xmlrouter/impl/ConfigImplTest.java | 19 +--- 9 files changed, 195 insertions(+), 69 deletions(-) create mode 100644 impl/src/main/java/org/wamblee/xmlrouter/impl/IdentifiablePrefixProxyFactory.java diff --git a/config/src/main/java/org/wamblee/xmlrouter/config/Config.java b/config/src/main/java/org/wamblee/xmlrouter/config/Config.java index baa4c8b..aa5c540 100644 --- a/config/src/main/java/org/wamblee/xmlrouter/config/Config.java +++ b/config/src/main/java/org/wamblee/xmlrouter/config/Config.java @@ -29,6 +29,12 @@ import org.wamblee.xmlrouter.common.Id; * Type for which ids are generated. */ public interface Config extends Identifiable { + + /** + * @return The type of contained object. + */ + Class getType(); + /** * Adds an item. No item with the same id may exist. * diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeConfig.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeConfig.java index c9e250e..0c6100d 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeConfig.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeConfig.java @@ -39,16 +39,24 @@ public class CompositeConfig> implements private static final Id ID = new Id("compositeconfig"); private static final String READ_ONLY_INSTANCE = "read only instance"; + + private Class type; private Set> ids; private List> valueIds; private List values; - public CompositeConfig() { + public CompositeConfig(Class aType) { + type = aType; ids = new HashSet>(); valueIds = new ArrayList>(); values = new ArrayList(); } + @Override + public Class getType() { + return type; + } + @Override public Id getId() { return ID; @@ -60,17 +68,22 @@ public class CompositeConfig> implements throw new ConfigException("duplicate id '" + aConfig.getId().toString() + "'"); } + String prefix = aConfig.getId().getId() + "."; for (T item : aConfig.values()) { - if (valueIds.contains(item.getId())) { + Id newId = new Id(prefix + item.getId()); + if (valueIds.contains(newId)) { throw new ConfigException("duplicate id '" + item.getId().toString() + "'"); } } ids.add(aConfig.getId()); + for (T item : aConfig.values()) { - valueIds.add(item.getId()); - values.add(item); + Id newId = new Id(prefix + item.getId()); + valueIds.add(newId); + values.add(IdentifiablePrefixProxyFactory.getProxy(prefix, item, + Identifiable.class, aConfig.getType())); } } diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeRouterConfig.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeRouterConfig.java index eabbf3e..fa01c06 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeRouterConfig.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/CompositeRouterConfig.java @@ -34,9 +34,10 @@ public class CompositeRouterConfig implements ExtendedRouterConfig { public CompositeRouterConfig(Id aId, Collection aConfigs) { - documentTypes = new CompositeConfig(); - transformations = new CompositeConfig(); - filters = new CompositeConfig(); + documentTypes = new CompositeConfig(DocumentType.class); + transformations = new CompositeConfig( + Transformation.class); + filters = new CompositeConfig(Filter.class); for (RouterConfig config : aConfigs) { documentTypes.addConfig(config.documentTypeConfig()); transformations.addConfig(config.transformationConfig()); diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/ConfigImpl.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/ConfigImpl.java index 8088be3..0e1da0b 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/ConfigImpl.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/ConfigImpl.java @@ -37,18 +37,26 @@ import org.wamblee.xmlrouter.config.Identifiable; public abstract class ConfigImpl> implements ExtendedConfig { + private Class type; private Id id; private Map, T> registered; /** * Constructs the object. */ - public ConfigImpl(Id aId) { + public ConfigImpl(Class aType, Id aId) { + notNull("type", aType); notNull("id", aId); + type = aType; id = aId; registered = new HashMap, T>(); } + @Override + public Class getType() { + return type; + } + /** * Copies the config object. * diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/IdentifiablePrefixProxyFactory.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/IdentifiablePrefixProxyFactory.java new file mode 100644 index 0000000..c787c7b --- /dev/null +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/IdentifiablePrefixProxyFactory.java @@ -0,0 +1,83 @@ +/* + * Copyright 2005-2011 the original author or authors. + * + * Licensed 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.wamblee.xmlrouter.impl; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.wamblee.xmlrouter.common.Id; +import org.wamblee.xmlrouter.config.Identifiable; + +/** + * This proxy factory creates proxies for identifiable objects that add a prefix + * to the ids. + * + * @author Erik Brakkee + * + * @param + */ +public class IdentifiablePrefixProxyFactory { + + public static final class IdPrefixInvocationHandler implements + InvocationHandler { + + private String prefix; + private T service; + + public IdPrefixInvocationHandler(String aPrefix, T aService) { + prefix = aPrefix; + service = aService; + } + + @Override + public Object invoke(Object aProxy, final Method aMethod, + final Object[] aArgs) throws Throwable { + try { + if (aMethod.getDeclaringClass().equals(Identifiable.class)) { + if (!aMethod.getName().equals("getId")) { + throw new RuntimeException( + "Programming error, Identifiable interface was modified"); + } + Id id = (Id) aMethod.invoke(service, aArgs); + return new Id(prefix + id.getId()); + } + return aMethod.invoke(service, aArgs); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } + } + + public static T getProxy(String aPrefix, T aService, + Class... aInterfaces) { + InvocationHandler handler = new IdPrefixInvocationHandler(aPrefix, + aService); + Class proxyClass = Proxy.getProxyClass(aService.getClass() + .getClassLoader(), aInterfaces); + T proxy; + try { + proxy = (T) proxyClass.getConstructor( + new Class[] { InvocationHandler.class }).newInstance( + new Object[] { handler }); + return proxy; + } catch (Exception e) { + throw new RuntimeException("Could not create proxy for " + + aService.getClass().getName(), e); + } + } +} diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/SingleRouterConfig.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/SingleRouterConfig.java index deb38f6..4ecaad4 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/SingleRouterConfig.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/SingleRouterConfig.java @@ -34,7 +34,7 @@ public class SingleRouterConfig implements ExtendedRouterConfig { public static final class DocumentConfig extends ConfigImpl { public DocumentConfig(Id aId) { - super(aId); + super(DocumentType.class, aId); } public DocumentConfig(DocumentConfig aConfig) { @@ -43,14 +43,14 @@ public class SingleRouterConfig implements ExtendedRouterConfig { @Override public DocumentType wrap(String aPrefix, DocumentType aT) { - return new RobustDocumentType(aPrefix, aT); + return new RobustDocumentType("", aT); } } public static final class TransformationConfig extends ConfigImpl { public TransformationConfig(Id aId) { - super(aId); + super(Transformation.class, aId); } public TransformationConfig(TransformationConfig aConfig) { @@ -60,13 +60,13 @@ public class SingleRouterConfig implements ExtendedRouterConfig { @Override public Transformation wrap(String aPrefix, Transformation aTransformation) { - return new RobustTransformation(aPrefix, aTransformation); + return new RobustTransformation("", aTransformation); } } public static final class FilterConfig extends ConfigImpl { public FilterConfig(Id aId) { - super(aId); + super(Filter.class, aId); } public FilterConfig(FilterConfig aConfig) { @@ -75,7 +75,7 @@ public class SingleRouterConfig implements ExtendedRouterConfig { @Override public Filter wrap(String aPrefix, Filter aFilter) { - return new RobustFilter(aPrefix, aFilter); + return new RobustFilter("", aFilter); } } diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigService.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigService.java index ff8c6de..da883d2 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigService.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigService.java @@ -44,8 +44,8 @@ public class XMLRouterConfigService implements RouterConfigService { application = aApplication; sequence = new AtomicLong(1L); config = aConfig; - routerConfigs = new ConfigImpl(new Id( - aApplication)) { + routerConfigs = new ConfigImpl(RouterConfig.class, + new Id(aApplication)) { public RouterConfig wrap(final String aPrefix, final RouterConfig aT) { return new RouterConfig() { @Override diff --git a/impl/src/test/java/org/wamblee/xmlrouter/impl/CompositeConfigTest.java b/impl/src/test/java/org/wamblee/xmlrouter/impl/CompositeConfigTest.java index 9905046..cd0879d 100644 --- a/impl/src/test/java/org/wamblee/xmlrouter/impl/CompositeConfigTest.java +++ b/impl/src/test/java/org/wamblee/xmlrouter/impl/CompositeConfigTest.java @@ -17,6 +17,7 @@ package org.wamblee.xmlrouter.impl; import static junit.framework.Assert.*; +import java.util.ArrayList; import java.util.List; import org.junit.Test; @@ -27,22 +28,31 @@ import org.wamblee.xmlrouter.config.Identifiable; public class CompositeConfigTest { - public static class IntClass implements Identifiable { + public static interface StringClassInterface extends + Identifiable { - private int value; + } + + public static class StringClass implements StringClassInterface { - public IntClass(int aValue) { + private String value; + + public StringClass(String aValue) { value = aValue; } + public StringClass(int aValue) { + this(aValue + ""); + } + @Override - public Id getId() { - return new Id(value + ""); + public Id getId() { + return new Id(value + ""); } @Override public int hashCode() { - return ((Integer) value).hashCode(); + return value.hashCode(); } @Override @@ -50,50 +60,52 @@ public class CompositeConfigTest { if (aObj == null) { return false; } - if (!(aObj instanceof IntClass)) { + if (!(aObj instanceof StringClass)) { return false; } - IntClass obj = (IntClass) aObj; - return value == obj.value; + StringClass obj = (StringClass) aObj; + return value.equals(obj.value); } } @Test public void testEmptyConfig() { - Config composite = composite(); + Config composite = composite(); assertTrue(composite.values().isEmpty()); } @Test(expected = RuntimeException.class) public void testAddNotAllowed() { - composite().add(new IntClass(10)); + composite().add(new StringClass(10)); } @Test(expected = RuntimeException.class) public void testRemoveNotAllowed() { - composite().remove(new Id("xxx")); + composite().remove(new Id("xxx")); } @Test public void testAddConfig() { - CompositeConfig composite = composite(); - Config c1 = new ConfigImpl(id("c1")) { + CompositeConfig composite = composite(); + Config c1 = new ConfigImpl( + StringClassInterface.class, id("c1")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; } }; - Config c2 = new ConfigImpl(id("c2")) { + Config c2 = new ConfigImpl( + StringClassInterface.class, id("c2")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; } }; - IntClass i1 = new IntClass(10); - IntClass i2 = new IntClass(20); - IntClass i3 = new IntClass(30); - IntClass i4 = new IntClass(40); + StringClass i1 = new StringClass(10); + StringClass i2 = new StringClass(20); + StringClass i3 = new StringClass(30); + StringClass i4 = new StringClass(40); c1.add(i1); c1.add(i2); @@ -101,30 +113,40 @@ public class CompositeConfigTest { c2.add(i4); composite.addConfig(c1); - List values = composite.values(); - assertEquals(2, values.size()); - assertTrue(values.contains(i1)); - assertTrue(values.contains(i2)); + List values = composite.values(); + List ids = new ArrayList(); + for (StringClassInterface intf : values) { + ids.add(intf.getId().getId()); + } + assertTrue(ids.contains("c1.10")); + assertTrue(ids.contains("c1.20")); composite.addConfig(c2); values = composite.values(); assertEquals(4, values.size()); - assertTrue(values.contains(i1)); - assertTrue(values.contains(i2)); - assertTrue(values.contains(i3)); - assertTrue(values.contains(i4)); + + ids = new ArrayList(); + for (StringClassInterface intf : values) { + ids.add(intf.getId().getId()); + } + assertTrue(ids.contains("c1.10")); + assertTrue(ids.contains("c1.20")); + assertTrue(ids.contains("c2.30")); + assertTrue(ids.contains("c2.40")); } @Test(expected = ConfigException.class) public void testDuplicatesNotAllowed() { - CompositeConfig composite = composite(); - Config c1 = new ConfigImpl(id("c1")) { + CompositeConfig composite = composite(); + Config c1 = new ConfigImpl( + StringClassInterface.class, id("c1")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; } }; - Config c2 = new ConfigImpl(id("c1")) { + Config c2 = new ConfigImpl( + StringClassInterface.class, id("c1")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; @@ -136,22 +158,24 @@ public class CompositeConfigTest { @Test public void testDuplicateItem() { - CompositeConfig composite = composite(); - Config c1 = new ConfigImpl(id("c1")) { + CompositeConfig composite = composite(); + Config c1 = new ConfigImpl( + StringClassInterface.class, id("c.x")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; } }; - Config c2 = new ConfigImpl(id("c2")) { + Config c2 = new ConfigImpl( + StringClassInterface.class, id("c")) { @Override public Identifiable wrap(String aPrefix, Identifiable aT) { return aT; } }; - IntClass i1 = new IntClass(10); - IntClass i2 = new IntClass(10); + StringClass i1 = new StringClass("y"); + StringClass i2 = new StringClass("x.y"); c1.add(i1); c2.add(i2); composite.addConfig(c1); @@ -162,11 +186,13 @@ public class CompositeConfigTest { // ok. } assertEquals(1, composite.values().size()); - assertTrue(composite.values().contains(i1)); + assertEquals("c.x.y", composite.values().iterator().next().getId() + .getId()); } - private CompositeConfig composite() { - return new CompositeConfig(); + private CompositeConfig composite() { + return new CompositeConfig( + StringClassInterface.class); } private Id id(String aId) { diff --git a/impl/src/test/java/org/wamblee/xmlrouter/impl/ConfigImplTest.java b/impl/src/test/java/org/wamblee/xmlrouter/impl/ConfigImplTest.java index aa197ea..8586012 100644 --- a/impl/src/test/java/org/wamblee/xmlrouter/impl/ConfigImplTest.java +++ b/impl/src/test/java/org/wamblee/xmlrouter/impl/ConfigImplTest.java @@ -55,7 +55,7 @@ public class ConfigImplTest { public static final class MyTypeConfig extends ConfigImpl { public MyTypeConfig(Id aId) { - super(aId); + super(MyType.class, aId); } public MyTypeConfig(MyTypeConfig aConfig) { @@ -121,22 +121,11 @@ public class ConfigImplTest { @Test public void testEquals() { - Config config1 = new ConfigImpl(new Id( - CONFIG_TYPE)) { - @Override - public MyType wrap(String aPrefix, MyType aT) { - return new MyTypeWrapper(aPrefix, aT); - } - }; + Config config1 = new MyTypeConfig(new Id(CONFIG_TYPE)); assertFalse(config1.equals(null)); assertFalse(config1.equals("hello")); - Config config2 = new ConfigImpl(new Id( - CONFIG_TYPE)) { - @Override - public MyType wrap(String aPrefix, MyType aT) { - return new MyTypeWrapper(aPrefix, aT); - } - }; + Config config2 = new MyTypeConfig(new Id(CONFIG_TYPE)); + assertEquals(config1, config2); assertEquals(config1.hashCode(), config2.hashCode()); -- 2.31.1