/* * Copyright 2017 MongoDB, Inc. * * 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.bson.codecs.pojo; import org.bson.codecs.pojo.annotations.Property; import org.bson.codecs.pojo.entities.ConcreteCollectionsModel; import org.bson.codecs.pojo.entities.GenericHolderModel; import org.bson.codecs.pojo.entities.InvalidMapModel; import org.bson.codecs.pojo.entities.NestedGenericHolderModel; import org.bson.codecs.pojo.entities.SimpleGenericsModel; import org.bson.codecs.pojo.entities.UpperBoundsModel; import org.bson.codecs.pojo.entities.UpperBoundsConcreteModel; import org.junit.Test; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @SuppressWarnings("rawtypes") public final class ClassModelBuilderTest { @Test public void testDefaults() { Class<SimpleGenericsModel> clazz = SimpleGenericsModel.class; ClassModelBuilder<SimpleGenericsModel> builder = ClassModel.builder(clazz); assertEquals(4, builder.getFields().size()); for (Field field : clazz.getDeclaredFields()) { assertEquals(field.getName(), builder.getField(field.getName()).getDocumentFieldName()); } Map<String, TypeParameterMap> fieldNameToTypeParameterMap = new HashMap<String, TypeParameterMap>(); fieldNameToTypeParameterMap.put("myIntegerField", TypeParameterMap.builder().build()); fieldNameToTypeParameterMap.put("myGenericField", TypeParameterMap.builder().addIndex(0).build()); fieldNameToTypeParameterMap.put("myListField", TypeParameterMap.builder().addIndex(0, 1).build()); fieldNameToTypeParameterMap.put("myMapField", TypeParameterMap.builder().addIndex(1, 2).build()); assertEquals(fieldNameToTypeParameterMap, builder.getFieldNameToTypeParameterMap()); assertEquals(2, builder.getConventions().size()); assertTrue(builder.getAnnotations().isEmpty()); assertEquals(clazz, builder.getType()); assertNull(builder.getIdField()); assertFalse(builder.useDiscriminator()); assertNull(builder.getDiscriminator()); } @Test public void testCanReflectObjectClass() { Class<Object> clazz = Object.class; ClassModelBuilder<Object> builder = ClassModel.builder(clazz); assertEquals(0, builder.getFields().size()); assertTrue(builder.getFieldNameToTypeParameterMap().isEmpty()); assertEquals(2, builder.getConventions().size()); assertTrue(builder.getAnnotations().isEmpty()); assertEquals(clazz, builder.getType()); assertNull(builder.getIdField()); assertFalse(builder.useDiscriminator()); assertNull(builder.getDiscriminator()); } @Test public void testMappedBoundedClasses() { ClassModelBuilder<? extends UpperBoundsModel> builder = ClassModel.builder(UpperBoundsModel.class); assertEquals(Number.class, builder.getField("myGenericField").getTypeData().getType()); builder = ClassModel.builder(UpperBoundsConcreteModel.class); assertEquals(Long.class, builder.getField("myGenericField").getTypeData().getType()); } @Test public void testNestedGenericHolderModel() { ClassModelBuilder<NestedGenericHolderModel> builder = ClassModel.builder(NestedGenericHolderModel.class); assertEquals(GenericHolderModel.class, builder.getField("nested").getTypeData().getType()); assertEquals(TypeData.builder(GenericHolderModel.class).addTypeParameter(TypeData.builder(String.class).build()).build(), builder.getField("nested").getTypeData()); } @Test public void testFieldsMappedClassTypes() { ClassModelBuilder<ConcreteCollectionsModel> builder = ClassModel.builder(ConcreteCollectionsModel.class); assertEquals(ArrayList.class, builder.getField("collection").getTypeData().getType()); assertEquals(ArrayList.class, builder.getField("list").getTypeData().getType()); assertEquals(LinkedList.class, builder.getField("linked").getTypeData().getType()); assertEquals(HashMap.class, builder.getField("map").getTypeData().getType()); assertEquals(ConcurrentHashMap.class, builder.getField("concurrent").getTypeData().getType()); } @Test public void testOverrides() throws NoSuchFieldException { ClassModelBuilder<SimpleGenericsModel> builder = ClassModel.<SimpleGenericsModel>builder(SimpleGenericsModel.class) .annotations(TEST_ANNOTATIONS) .conventions(TEST_CONVENTIONS) .discriminatorKey("_cls") .discriminator("myColl") .enableDiscriminator(true) .idField("myIntegerField") .instanceCreatorFactory(TEST_INSTANCE_CREATOR_FACTORY); assertEquals(TEST_ANNOTATIONS, builder.getAnnotations()); assertEquals(TEST_CONVENTIONS, builder.getConventions()); assertEquals("myIntegerField", builder.getIdField()); assertEquals(SimpleGenericsModel.class, builder.getType()); assertTrue(builder.useDiscriminator()); assertEquals("_cls", builder.getDiscriminatorKey()); assertEquals("myColl", builder.getDiscriminator()); assertEquals(TEST_INSTANCE_CREATOR_FACTORY, builder.getInstanceCreatorFactory()); } @Test public void testCanRemoveField() { ClassModelBuilder<SimpleGenericsModel> builder = ClassModel.builder(SimpleGenericsModel.class) .idField("ID"); assertEquals(4, builder.getFields().size()); builder.removeField("myIntegerField"); assertEquals(3, builder.getFields().size()); builder.removeField("myIntegerField"); assertEquals(3, builder.getFields().size()); } @Test(expected = IllegalStateException.class) public void testValidationIdField() { ClassModel.builder(SimpleGenericsModel.class).idField("ID").build(); } @Test(expected = IllegalStateException.class) public void testValidationDuplicateDocumentFieldName() { ClassModelBuilder<SimpleGenericsModel> builder = ClassModel.builder(SimpleGenericsModel.class); builder.getField("myIntegerField").documentFieldName("myGenericField"); builder.build(); } @Test(expected = IllegalStateException.class) public void testIllegalMapKey() { ClassModel.builder(InvalidMapModel.class).build(); } private static final List<Annotation> TEST_ANNOTATIONS = Collections.<Annotation>singletonList( new Property() { @Override public Class<? extends Annotation> annotationType() { return Property.class; } @Override public String name() { return ""; } @Override public boolean useDiscriminator() { return true; } }); private static final List<Convention> TEST_CONVENTIONS = Collections.<Convention>singletonList( new Convention() { @Override public void apply(final ClassModelBuilder<?> builder) { } }); private static final InstanceCreatorFactory<SimpleGenericsModel> TEST_INSTANCE_CREATOR_FACTORY = new InstanceCreatorFactory<SimpleGenericsModel>() { @Override public InstanceCreator<SimpleGenericsModel> create() { return null; } }; }