Repository: cayenne Updated Branches: refs/heads/master 6ad05a090 -> 0e0da8064
CAY-2066 Fixes for inner enums handling in ExtendedTypeMap * unit test that demonstrates the problem * a fix that canonicalizes class names used in the map this closes PR #90 commit 6d40a72f0158757146ccdbf64bbf6f32b5df53e8 Author: Andrus Adamchik <and...@objectstyle.com> Date: Sat Mar 5 04:17:58 2016 -0800 ExtendedTypeMap unit test cleanup Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/0e0da806 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/0e0da806 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/0e0da806 Branch: refs/heads/master Commit: 0e0da8064cde5499b48858bf9b47dc5169f5782c Parents: 6ad05a0 Author: Andrus Adamchik <and...@objectstyle.com> Authored: Sat Mar 5 16:07:27 2016 -0800 Committer: Andrus Adamchik <and...@objectstyle.com> Committed: Sat Mar 5 16:07:27 2016 -0800 ---------------------------------------------------------------------- .../apache/cayenne/access/types/EnumType.java | 4 +- .../cayenne/access/types/ExtendedTypeMap.java | 33 ++++- .../access/types/ExtendedTypeMapEnumsTest.java | 129 +++++++++++-------- docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 + 4 files changed, 107 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e0da806/cayenne-server/src/main/java/org/apache/cayenne/access/types/EnumType.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/EnumType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/EnumType.java index 55cc89e..1261a26 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/EnumType.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/EnumType.java @@ -40,6 +40,7 @@ public class EnumType<T extends Enum<T>> implements ExtendedType { protected Class<T> enumClass; protected Object[] values; + protected String canonicalName; public EnumType(Class<T> enumClass) { if (enumClass == null) { @@ -47,6 +48,7 @@ public class EnumType<T extends Enum<T>> implements ExtendedType { } this.enumClass = enumClass; + this.canonicalName = enumClass.getCanonicalName(); try { Method m = enumClass.getMethod("values"); @@ -61,7 +63,7 @@ public class EnumType<T extends Enum<T>> implements ExtendedType { @Override public String getClassName() { - return enumClass.getName(); + return canonicalName; } @Override http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e0da806/cayenne-server/src/main/java/org/apache/cayenne/access/types/ExtendedTypeMap.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/ExtendedTypeMap.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/ExtendedTypeMap.java index 08c51db..387fe77 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/ExtendedTypeMap.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/ExtendedTypeMap.java @@ -49,6 +49,7 @@ public class ExtendedTypeMap { classesForPrimitives.put("int", Integer.class.getName()); } + protected Map<String, String> typeAliases; protected final Map<String, ExtendedType> typeMap; protected ExtendedType defaultType; @@ -67,6 +68,7 @@ public class ExtendedTypeMap { public ExtendedTypeMap() { this.defaultType = new ObjectType(); this.typeMap = new ConcurrentHashMap<>(); + this.typeAliases = new ConcurrentHashMap<>(classesForPrimitives); this.extendedTypeFactories = new CopyOnWriteArrayList<>(); this.internalTypeFactories = new CopyOnWriteArrayList<>(); @@ -168,13 +170,9 @@ public class ExtendedTypeMap { return getDefaultType(); } - String nonPrimitive = classesForPrimitives.get(javaClassName); - if (nonPrimitive != null) { - javaClassName = nonPrimitive; - } + javaClassName = canonicalizedTypeName(javaClassName); ExtendedType type = getExplictlyRegisteredType(javaClassName); - if (type != null) { return type; } @@ -276,4 +274,29 @@ public class ExtendedTypeMap { return null; } + + /** + * For the class name returns a name "canonicalized" for the purpose of + * ExtendedType lookup. + * + * @since 4.0 + */ + protected String canonicalizedTypeName(String className) { + + String canonicalized = typeAliases.get(className); + if (canonicalized == null) { + + int index = className.indexOf('$'); + if (index >= 0) { + canonicalized = className.replace('$', '.'); + } else { + canonicalized = className; + } + + typeAliases.put(className, canonicalized); + + } + + return canonicalized; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e0da806/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapEnumsTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapEnumsTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapEnumsTest.java index 37b8afc..21ac50b 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapEnumsTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapEnumsTest.java @@ -19,8 +19,6 @@ package org.apache.cayenne.access.types; -import org.junit.Test; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; @@ -28,58 +26,81 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import org.apache.cayenne.access.types.InnerEnumHolder.InnerEnum; +import org.junit.Before; +import org.junit.Test; + public class ExtendedTypeMapEnumsTest { - @Test - public void testCreateType1_5() { - ExtendedTypeMap map = new ExtendedTypeMap(); - - assertNull(map.createType(Object.class.getName())); - - ExtendedType type = map.createType(MockEnum.class.getName()); - assertTrue(type instanceof EnumType); - assertEquals(MockEnum.class, ((EnumType) type).enumClass); - - ExtendedType type2 = map.createType(MockEnum2.class.getName()); - assertNotSame(type, type2); - } - - @Test - public void testCreateType1_5InnerEnum() { - ExtendedTypeMap map = new ExtendedTypeMap(); - - ExtendedType type = map.createType(InnerEnumHolder.InnerEnum.class.getName()); - assertTrue(type instanceof EnumType); - assertEquals(InnerEnumHolder.InnerEnum.class, ((EnumType) type).enumClass); - - // use a string name with $ - ExtendedType type1 = map.createType(InnerEnumHolder.class.getName() - + "$InnerEnum"); - assertNotNull(type1); - assertSame(type.getClassName(), type1.getClassName()); - - // use a string name with . - ExtendedType type2 = map.createType(InnerEnumHolder.class.getName() - + ".InnerEnum"); - assertNotNull(type2); - assertSame(type.getClassName(), type2.getClassName()); - } - - @Test - public void testGetDefaultType1_4() { - ExtendedTypeMap map = new ExtendedTypeMap(); - map.internalTypeFactories.clear(); - - assertNull(map.createType(Object.class.getName())); - assertNull(map.createType(MockEnum.class.getName())); - assertNull(map.createType(MockEnum2.class.getName())); - } - - @Test - public void testGetType() { - ExtendedTypeMap map = new ExtendedTypeMap(); - ExtendedType type = map.getRegisteredType(MockEnum.class.getName()); - assertNotNull(type); - assertTrue(type instanceof EnumType); - } + private ExtendedTypeMap map; + + @Before + public void before() { + this.map = new ExtendedTypeMap(); + } + + @Test + public void testCreateType_NoFactory() { + assertNull(map.createType(Object.class.getName())); + } + + @Test + public void testCreateType_Enum() { + + ExtendedType type1 = map.createType(MockEnum.class.getName()); + assertTrue(type1 instanceof EnumType); + assertEquals(MockEnum.class, ((EnumType<?>) type1).enumClass); + + ExtendedType type2 = map.createType(MockEnum2.class.getName()); + assertNotSame(type1, type2); + } + + @Test + public void testCreateType_InnerEnum() { + + ExtendedType type = map.createType(InnerEnumHolder.InnerEnum.class.getName()); + assertTrue(type instanceof EnumType); + assertEquals(InnerEnumHolder.InnerEnum.class, ((EnumType<?>) type).enumClass); + + // use a string name with $ + ExtendedType type1 = map.createType(InnerEnumHolder.class.getName() + "$InnerEnum"); + assertNotNull(type1); + assertEquals(type.getClassName(), type1.getClassName()); + + // use a string name with . + ExtendedType type2 = map.createType(InnerEnumHolder.class.getName() + ".InnerEnum"); + assertNotNull(type2); + assertEquals(type.getClassName(), type2.getClassName()); + } + + @Test + public void testGetRegisteredType() { + ExtendedType type = map.getRegisteredType(MockEnum.class); + assertNotNull(type); + assertTrue(type instanceof EnumType); + + assertSame(type, map.getRegisteredType(MockEnum.class)); + assertSame(type, map.getRegisteredType(MockEnum.class.getName())); + } + + @Test + public void testGetRegisteredType_InnerEnum() { + + assertEquals(0, map.extendedTypeFactories.size()); + + ExtendedType byType = map.getRegisteredType(InnerEnum.class); + + // this and subsequent tests verify that no memory leak occurs per + // CAY-2066 + assertEquals(1, map.extendedTypeFactories.size()); + + assertSame(byType, map.getRegisteredType(InnerEnum.class)); + assertEquals(1, map.extendedTypeFactories.size()); + + assertSame(byType, map.getRegisteredType(InnerEnumHolder.class.getName() + "$InnerEnum")); + assertEquals(1, map.extendedTypeFactories.size()); + + assertSame(byType, map.getRegisteredType(InnerEnumHolder.class.getName() + ".InnerEnum")); + assertEquals(1, map.extendedTypeFactories.size()); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e0da806/docs/doc/src/main/resources/RELEASE-NOTES.txt ---------------------------------------------------------------------- diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt index e1118b2..c595659 100644 --- a/docs/doc/src/main/resources/RELEASE-NOTES.txt +++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt @@ -23,6 +23,7 @@ CAY-2065 Pluggable serialization and connectivity layers for ROP Bug Fixes: CAY-2064 Issue with BeanAccessor for classes with complex inheritance +CAY-2066 Fixes for inner enums handling in ExtendedTypeMap ---------------------------------- Release: 4.0.M3