package org.simpleflatmapper.reflect.test.meta; import org.junit.Test; import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition; import org.simpleflatmapper.reflect.meta.*; import org.simpleflatmapper.test.beans.DbObject; import org.simpleflatmapper.reflect.InstantiatorDefinition; import org.simpleflatmapper.reflect.ReflectionService; import org.simpleflatmapper.util.ConstantPredicate; import org.simpleflatmapper.util.Consumer; import org.simpleflatmapper.util.Predicate; import org.simpleflatmapper.util.TypeReference; import java.util.AbstractMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static org.junit.Assert.*; public class MapClassMetaTest { private Predicate<PropertyMeta<?, ?>> isValidPropertyMeta = ConstantPredicate.truePredicate(); @Test public void testForEach() { try { ReflectionService.newInstance().getClassMeta(new TypeReference<Map<String, String>>() {}.getType()).forEachProperties(new Consumer<PropertyMeta<?, ?>>() { @Override public void accept(PropertyMeta<?, ?> dbObjectPropertyMeta) { } }); fail(); } catch (UnsupportedOperationException e) { // expected } } @Test @SuppressWarnings("unchecked") public void testFindPropertyStringDbObject() { final ClassMeta<Map<String, DbObject>> classMeta = ReflectionService.newInstance().getClassMeta(new TypeReference<Map<String, DbObject>>() {}.getType()); final PropertyFinder<Map<String, DbObject>> mapPropertyFinder = classMeta.newPropertyFinder(isValidPropertyMeta); final SubPropertyMeta<?, ?, ?> k_kv_k_id = (SubPropertyMeta<?, ?, ?>) mapPropertyFinder.findProperty(DefaultPropertyNameMatcher.of("k_kv_k_id")); assertNotNull(k_kv_k_id); PropertyMeta<Map<String, DbObject>, Object> k_kv_k_noprop = mapPropertyFinder.findProperty(DefaultPropertyNameMatcher.of("k_kv_k_noprop")); assertTrue(k_kv_k_noprop instanceof MapElementPropertyMeta); // self ref MapElementPropertyMeta<?, ?, ?> idMeta = (MapElementPropertyMeta<?, ?, ?>) k_kv_k_id.getOwnerProperty(); assertEquals("k_kv_k", idMeta.getKey()); final SubPropertyMeta<Map<String, DbObject>, DbObject, Object> k_kv_k_creation_time = (SubPropertyMeta<Map<String, DbObject>, DbObject, Object>) mapPropertyFinder.findProperty(DefaultPropertyNameMatcher.of("k_kv_k_creation_time")); assertNotNull(k_kv_k_creation_time); MapElementPropertyMeta<?, ?, ?> creationTimeMeta = (MapElementPropertyMeta<?, ?, ?>) k_kv_k_creation_time.getOwnerProperty(); assertEquals("k_kv_k", creationTimeMeta.getKey()); } @Test public void testFindPropertyStringString() { final ClassMeta<Map<String, String>> classMeta = ReflectionService.newInstance().getClassMeta(new TypeReference<Map<String, String>>() {}.getType()); final PropertyFinder<Map<String, String>> mapPropertyFinder = classMeta.newPropertyFinder(isValidPropertyMeta); final PropertyMeta<?, ?> k_kv_k_id = mapPropertyFinder.findProperty(DefaultPropertyNameMatcher.of("k_kv_k_id")); assertNotNull(k_kv_k_id); assertTrue("Expect MapElementPropertyMeta " + k_kv_k_id, k_kv_k_id instanceof MapElementPropertyMeta); MapElementPropertyMeta<?, ?, ?> idMeta = (MapElementPropertyMeta<?, ?, ?>) k_kv_k_id; assertEquals("k_kv_k_id", idMeta.getKey()); } @Test public void testFailOnAbstractMap() throws Exception { try { ReflectionService.newInstance().getClassMeta(new TypeReference<AbstractMap<String, String>>() {}.getType()); fail(); } catch(IllegalArgumentException e) { // expected } } @Test public void testFailOnAbstractOnImplWithNoEmptyConstructor() throws Exception { try { ReflectionService.newInstance().getClassMeta(NoEmptyConstructorMap.class); fail(); } catch(IllegalArgumentException e) { // expected } } @Test public void testFailOnUnsupportedConverter() throws Exception { try { ReflectionService.newInstance().getClassMeta(new TypeReference<Map<Map<String, String>, String>>() {}.getType()); fail(); } catch(IllegalArgumentException e) { // expected } } @Test public void testUseHashMapOnMap() throws NoSuchMethodException { typeMetaHasTheSpecifiedClassEmptyConstructor( new TypeReference<Map<String, String>>() {}, HashMap.class); } @Test public void testUseConcurrentHashMapOnConcurrentMap() throws NoSuchMethodException { typeMetaHasTheSpecifiedClassEmptyConstructor( new TypeReference<ConcurrentMap<String, String>>() {}, ConcurrentHashMap.class); } @Test public void testUseSpecifiedImplType() throws NoSuchMethodException { typeMetaHasTheSpecifiedClassEmptyConstructor( new TypeReference<MyHashMap>() {}, MyHashMap.class); } static class MyHashMap extends HashMap<String, String> { } private void typeMetaHasTheSpecifiedClassEmptyConstructor(TypeReference<?> typeReference, Class<?> impl) throws NoSuchMethodException { final ClassMeta<Map<String, String>> classMeta = ReflectionService.newInstance().getClassMeta(typeReference.getType()); assertEquals(typeReference.getType(), classMeta.getType()); hasOneInstantiatorDefinitionWithEmptyConstructorOnImpl(classMeta, impl); } private void hasOneInstantiatorDefinitionWithEmptyConstructorOnImpl(ClassMeta<?> classMeta, Class<?> impl) throws NoSuchMethodException { assertTrue(classMeta instanceof MapClassMeta); final List<InstantiatorDefinition> instantiatorDefinitions = classMeta.getInstantiatorDefinitions(); assertEquals(1, instantiatorDefinitions.size()); final ExecutableInstantiatorDefinition instantiatorDefinition = (ExecutableInstantiatorDefinition) instantiatorDefinitions.get(0); assertEquals(0, instantiatorDefinition.getParameters().length); assertEquals(impl.getDeclaredConstructor(), instantiatorDefinition.getExecutable()); } static class NoEmptyConstructorMap extends HashMap<String, String> { public NoEmptyConstructorMap(int i) { } } }