Repository: cayenne Updated Branches: refs/heads/STABLE-4.0 4cd249778 -> ba750c5b2
CAY-2411 Wrong resolution of ExtendedType with ValueObjectType for inherited class (cherry picked from commit fd0d06e) Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/a16d7c43 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/a16d7c43 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/a16d7c43 Branch: refs/heads/STABLE-4.0 Commit: a16d7c435f86cb25c987d054704d8210ff855ae6 Parents: 4cd2497 Author: Nikita Timofeev <stari...@gmail.com> Authored: Tue Feb 27 16:05:47 2018 +0300 Committer: Nikita Timofeev <stari...@gmail.com> Committed: Tue Feb 27 17:14:47 2018 +0300 ---------------------------------------------------------------------- RELEASE-NOTES.txt | 1 + .../types/DefaultValueObjectTypeRegistry.java | 45 ---------------- .../cayenne/access/types/ExtendedTypeMap.java | 3 -- .../access/types/SubclassTypeFactory.java | 3 ++ .../DefaultValueObjectTypeRegistryTest.java | 8 +-- .../access/types/ExtendedTypeMapEnumsTest.java | 11 ++-- .../access/types/ExtendedTypeMapTest.java | 2 +- .../types/ValueObjectTypeFactoryTest.java | 55 +++++++++++++++++++- 8 files changed, 68 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/RELEASE-NOTES.txt ---------------------------------------------------------------------- diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 030b5f1..49863ba 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -27,6 +27,7 @@ CAY-2389 DbEntity qualifier with DbPath expression translates into wrong SQL CAY-2392 Modeler: Unable to remove DataNode CAY-2401 Modeler: NPE in ObjEntity sync action CAY-2405 Broken prefetch of entity with inheritance and attribute with custom java type +CAY-2411 Wrong resolution of ExtendedType with ValueObjectType for inherited class ---------------------------------- Release: 4.0.B2 http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/cayenne-server/src/main/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistry.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistry.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistry.java index 3dda771..7943ee8 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistry.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistry.java @@ -52,53 +52,8 @@ public class DefaultValueObjectTypeRegistry implements ValueObjectTypeRegistry { public <T> ValueObjectType<T, ?> getValueType(Class<? extends T> valueClass) { ValueObjectType type = typeCache.get(valueClass.getName()); if(type == null) { - type = findBySuperclasses(valueClass); - } else if(type == NULL_DUMMY) { return null; } return type; } - - protected ValueObjectType<?, ?> findBySuperclasses(final Class<?> baseClass) { - ValueObjectType<?,?> type = null; - Class<?> searchClass = baseClass.getSuperclass(); - - while(searchClass != null && !searchClass.equals(Object.class)) { - type = typeCache.get(searchClass.getName()); - if(type != null) { - // cache it for faster search later - typeCache.put(baseClass.getName(), type); - break; - } - searchClass = searchClass.getSuperclass(); - } - // as well cache null result - if(type == null) { - typeCache.put(baseClass.getName(), NULL_DUMMY); - } - return type; - } - - private static final ValueObjectType<?, ?> NULL_DUMMY = new ValueObjectType() { - @Override - public Class<?> getTargetType() { - return null; - } - @Override - public Class<?> getValueType() { - return null; - } - @Override - public Object toJavaObject(Object value) { - return null; - } - @Override - public Object fromJavaObject(Object object) { - return null; - } - @Override - public String toCacheKey(Object object) { - return null; - } - }; } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/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 8d3d31b..3caf3f8 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 @@ -128,9 +128,6 @@ public class ExtendedTypeMap { */ public void registerType(ExtendedType type) { typeMap.put(type.getClassName(), type); - - // factory to handle subclasses of type.className - addFactory(new SubclassTypeFactory(type)); } /** http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/cayenne-server/src/main/java/org/apache/cayenne/access/types/SubclassTypeFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/SubclassTypeFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/SubclassTypeFactory.java index 6938759..182d0c3 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/SubclassTypeFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/SubclassTypeFactory.java @@ -25,6 +25,9 @@ import org.apache.cayenne.util.Util; * of the className in the {@link ExtendedType}. * * @since 3.0 + * @deprecated since 4.1 it is unused, as this factory is faulty assuming that + * we can freely interchange base class and it's subclasses. + * */ class SubclassTypeFactory implements ExtendedTypeFactory { http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/cayenne-server/src/test/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistryTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistryTest.java index 28c7467..d761f34 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistryTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/DefaultValueObjectTypeRegistryTest.java @@ -69,14 +69,14 @@ public class DefaultValueObjectTypeRegistryTest { assertSame(valueObjectType1, valueObjectType); valueObjectType = registry.getValueType(Float.class); - assertSame(valueObjectType2, valueObjectType); + assertNull(valueObjectType); valueObjectType = registry.getValueType(String.class); assertNull(valueObjectType); - assertEquals(4, registry.typeCache.size()); - assertTrue(registry.typeCache.containsKey(String.class.getName())); - assertTrue(registry.typeCache.containsKey(Float.class.getName())); + assertEquals(2, registry.typeCache.size()); + assertFalse(registry.typeCache.containsKey(String.class.getName())); + assertFalse(registry.typeCache.containsKey(Float.class.getName())); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/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 21ac50b..b9e5b73 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 @@ -90,17 +90,16 @@ public class ExtendedTypeMapEnumsTest { ExtendedType byType = map.getRegisteredType(InnerEnum.class); - // this and subsequent tests verify that no memory leak occurs per - // CAY-2066 - assertEquals(1, map.extendedTypeFactories.size()); + // this and subsequent tests verify that no memory leak occurs per CAY-2066 + assertEquals(0, map.extendedTypeFactories.size()); assertSame(byType, map.getRegisteredType(InnerEnum.class)); - assertEquals(1, map.extendedTypeFactories.size()); + assertEquals(0, map.extendedTypeFactories.size()); assertSame(byType, map.getRegisteredType(InnerEnumHolder.class.getName() + "$InnerEnum")); - assertEquals(1, map.extendedTypeFactories.size()); + assertEquals(0, map.extendedTypeFactories.size()); assertSame(byType, map.getRegisteredType(InnerEnumHolder.class.getName() + ".InnerEnum")); - assertEquals(1, map.extendedTypeFactories.size()); + assertEquals(0, map.extendedTypeFactories.size()); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapTest.java index fc68377..769e715 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ExtendedTypeMapTest.java @@ -55,7 +55,7 @@ public class ExtendedTypeMapTest { // List map.registerType(tstType1); assertSame(tstType1, map.getRegisteredType(List.class)); - assertSame(tstType1, map.getRegisteredType(ArrayList.class)); + assertNotSame(tstType1, map.getRegisteredType(ArrayList.class)); map = new ExtendedTypeMap(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/a16d7c43/cayenne-server/src/test/java/org/apache/cayenne/access/types/ValueObjectTypeFactoryTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ValueObjectTypeFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ValueObjectTypeFactoryTest.java index 293cf5f..8151a64 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/ValueObjectTypeFactoryTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/ValueObjectTypeFactoryTest.java @@ -22,18 +22,21 @@ package org.apache.cayenne.access.types; import org.junit.Before; import org.junit.Test; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class ValueObjectTypeFactoryTest { - ExtendedType tstType1, tstType2, tstType3, tstType4; + ExtendedType tstType1, tstType2, tstType3, tstType4, tstType5; ValueObjectTypeFactory factory; @@ -44,6 +47,7 @@ public class ValueObjectTypeFactoryTest { list.add(createMockValueType(String.class, String.class)); list.add(createMockValueType(int.class, int.class)); list.add(createMockValueType(String[].class, String[].class)); + list.add(createMockValueType(TestClass.class, BigDecimal.class)); DefaultValueObjectTypeRegistry registry = new DefaultValueObjectTypeRegistry(list); @@ -63,6 +67,9 @@ public class ValueObjectTypeFactoryTest { when(tstType4.getClassName()).thenReturn(String[].class.getCanonicalName()); extendedTypeMap.registerType(tstType4); + tstType5 = new MockExtendedType(BigDecimal.class); + extendedTypeMap.registerType(tstType5); + factory = new ValueObjectTypeFactory(extendedTypeMap,registry); } @@ -100,4 +107,50 @@ public class ValueObjectTypeFactoryTest { assertNotNull(converter4); assertSame(tstType4, converter4.extendedType); } + + @Test + public void testInheritantType() { + ValueObjectTypeFactory.ExtendedTypeConverter converter5 = (ValueObjectTypeFactory.ExtendedTypeConverter) factory.getType(TestClass.class); + assertNotNull(converter5); + assertSame(tstType5, converter5.extendedType); + } + + /** + * Test case for CAY-2411 + */ + @Test + public void testInheritantValueTypeOverExtendedType() { + // setup + ExtendedTypeMap map; + BigDecimalType bigDecimalType = new BigDecimalType(); + ValueObjectType valueObjectType; + { + map = new ExtendedTypeMap(); + map.registerType(bigDecimalType); + + List<ValueObjectType<?, ?>> list = new ArrayList<>(); + valueObjectType = mock(ValueObjectType.class); + when(valueObjectType.getValueType()).thenReturn(TestClass.class); + when(valueObjectType.getTargetType()).thenReturn(BigDecimal.class); + list.add(valueObjectType); + + DefaultValueObjectTypeRegistry registry = new DefaultValueObjectTypeRegistry(list); + map.addFactory(new ValueObjectTypeFactory(map, registry)); + } + + // test + ExtendedType type1 = map.getRegisteredType(BigDecimal.class); + assertSame(bigDecimalType, type1); + + ExtendedType type2 = map.getRegisteredType(TestClass.class); + assertThat(type2, instanceOf(ValueObjectTypeFactory.ExtendedTypeConverter.class)); + assertSame(valueObjectType, ((ValueObjectTypeFactory.ExtendedTypeConverter)type2).valueObjectType); + } + + private class TestClass extends BigDecimal { + + public TestClass(long val) { + super(val); + } + } }