/* * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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://aws.amazon.com/apache2.0 * * This file 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 com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * Unit test on reflecting domain classes with getter or field annotations. It * also tests the scenario when annotated properties are inherited from the * superclass. */ @SuppressWarnings("unused") public class PojoReflectionTest { private static DynamoDBReflector reflector = new DynamoDBReflector(); /** * Tests reflecting a model class that uses getter annotations. */ @Test public void testGetterAnnotations() { validateModel(PojoWithGetterAnnotations.class); } /** * Tests reflecting a model class that uses field annotations. */ @Test public void testFieldAnnotations() { validateModel(PojoWithFieldAnnotations.class); } /** * Tests reflecting a model class that uses both getter and field * annotations. */ @Test public void testMixedAnnotations() { validateModel(PojoWithMixedAnnotations.class); } /** * Validates that the reflected information from the POJO class mathes the * model defined in both PojoWithGetterAnnotations and * PojoWithFieldAnnotations. */ private void validateModel(Class<?> clazz) { // There should be 7 relevant getters (ignoredAttr is excluded) assertEquals(7, reflector.getRelevantGetters(clazz).size()); for (Method getter : reflector.getRelevantGetters(clazz)) { // Check that getAttributeName returns the expected attribute name assertEquals( expectedAttributeNames.get(getter.getName()), reflector.getAttributeName(getter)); // @DynamoDBAutoGeneratedKey if (getter.getName().equals("getAutogeneratedRangeKey")) { assertTrue(reflector.isAssignableKey(getter)); } // @DynamoDBVersionAttribute if (getter.getName().equals("getVersionedAttr")) { assertTrue(reflector.isVersionAttributeGetter(getter)); } } // Key getters assertEquals("getHashKey", reflector.getPrimaryHashKeyGetter(clazz).getName()); assertEquals("hashKey", reflector.getPrimaryHashKeyName(clazz)); assertEquals("getAutogeneratedRangeKey", reflector.getPrimaryRangeKeyGetter(clazz) .getName()); assertEquals("autogeneratedRangeKey", reflector.getPrimaryRangeKeyName(clazz)); } /** * A POJO model that uses getter annotations. */ @DynamoDBTable(tableName = "table") private static class PojoWithGetterAnnotations { private String hashKey; private String autogeneratedRangeKey; private String indexHashKey; private String indexRangeKey; private String attrWithAttrAnnotation; private String versionedAttr; private String customMarshallingAttr; private String ignoredAttr; @DynamoDBHashKey public String getHashKey() { return hashKey; } public void setHashKey(String hashKey) { this.hashKey = hashKey; } @DynamoDBRangeKey @DynamoDBAutoGeneratedKey public String getAutogeneratedRangeKey() { return autogeneratedRangeKey; } public void setAutogeneratedRangeKey(String autogeneratedRangeKey) { this.autogeneratedRangeKey = autogeneratedRangeKey; } @DynamoDBIndexHashKey(globalSecondaryIndexName = "index") public String getIndexHashKey() { return indexHashKey; } public void setIndexHashKey(String indexHashKey) { this.indexHashKey = indexHashKey; } @DynamoDBIndexRangeKey(globalSecondaryIndexName = "index") public String getIndexRangeKey() { return indexRangeKey; } public void setIndexRangeKey(String indexRangeKey) { this.indexRangeKey = indexRangeKey; } @DynamoDBAttribute(attributeName = "real-attribute-name") public String getAttrWithAttrAnnotation() { return attrWithAttrAnnotation; } public void setAttrWithAttrAnnotation(String attrWithAttrAnnotation) { this.attrWithAttrAnnotation = attrWithAttrAnnotation; } @DynamoDBVersionAttribute public String getVersionedAttr() { return versionedAttr; } public void setVersionedAttr(String versionedAttr) { this.versionedAttr = versionedAttr; } @DynamoDBMarshalling(marshallerClass = RandomUUIDMarshaller.class) public String getCustomMarshallingAttr() { return customMarshallingAttr; } public void setCustomMarshallingAttr(String customMarshallingAttr) { this.customMarshallingAttr = customMarshallingAttr; } @DynamoDBIgnore public String getIgnoredAttr() { return ignoredAttr; } public void setIgnoredAttr(String ignoredAttr) { this.ignoredAttr = ignoredAttr; } } /** * The same model as defined in PojoWithGetterAnnotations, but uses field * annotations instead. */ @DynamoDBTable(tableName = "table") private static class PojoWithFieldAnnotations { @DynamoDBHashKey private String hashKey; @DynamoDBRangeKey @DynamoDBAutoGeneratedKey private String autogeneratedRangeKey; @DynamoDBIndexHashKey(globalSecondaryIndexName = "index") private String indexHashKey; @DynamoDBIndexRangeKey(globalSecondaryIndexName = "index") private String indexRangeKey; @DynamoDBAttribute(attributeName = "real-attribute-name") private String attrWithAttrAnnotation; @DynamoDBVersionAttribute private String versionedAttr; @DynamoDBMarshalling(marshallerClass = RandomUUIDMarshaller.class) private String customMarshallingAttr; @DynamoDBIgnore private String ignoredAttr; public String getHashKey() { return hashKey; } public void setHashKey(String hashKey) { this.hashKey = hashKey; } public String getAutogeneratedRangeKey() { return autogeneratedRangeKey; } public void setAutogeneratedRangeKey(String autogeneratedRangeKey) { this.autogeneratedRangeKey = autogeneratedRangeKey; } public String getIndexHashKey() { return indexHashKey; } public void setIndexHashKey(String indexHashKey) { this.indexHashKey = indexHashKey; } public String getIndexRangeKey() { return indexRangeKey; } public void setIndexRangeKey(String indexRangeKey) { this.indexRangeKey = indexRangeKey; } public String getAttrWithAttrAnnotation() { return attrWithAttrAnnotation; } public void setAttrWithAttrAnnotation(String attrWithAttrAnnotation) { this.attrWithAttrAnnotation = attrWithAttrAnnotation; } public String getVersionedAttr() { return versionedAttr; } public void setVersionedAttr(String versionedAttr) { this.versionedAttr = versionedAttr; } public String getCustomMarshallingAttr() { return customMarshallingAttr; } public void setCustomMarshallingAttr(String customMarshallingAttr) { this.customMarshallingAttr = customMarshallingAttr; } public String getIgnoredAttr() { return ignoredAttr; } public void setIgnoredAttr(String ignoredAttr) { this.ignoredAttr = ignoredAttr; } } /** * The same model as defined in PojoWithGetterAnnotations, but uses both * getter and field annotations. */ @DynamoDBTable(tableName = "table") private static class PojoWithMixedAnnotations { @DynamoDBHashKey private String hashKey; private String autogeneratedRangeKey; @DynamoDBIndexHashKey(globalSecondaryIndexName = "index") private String indexHashKey; private String indexRangeKey; @DynamoDBAttribute(attributeName = "real-attribute-name") private String attrWithAttrAnnotation; private String versionedAttr; @DynamoDBMarshalling(marshallerClass = RandomUUIDMarshaller.class) private String customMarshallingAttr; private String ignoredAttr; public String getHashKey() { return hashKey; } public void setHashKey(String hashKey) { this.hashKey = hashKey; } @DynamoDBRangeKey @DynamoDBAutoGeneratedKey public String getAutogeneratedRangeKey() { return autogeneratedRangeKey; } public void setAutogeneratedRangeKey(String autogeneratedRangeKey) { this.autogeneratedRangeKey = autogeneratedRangeKey; } public String getIndexHashKey() { return indexHashKey; } public void setIndexHashKey(String indexHashKey) { this.indexHashKey = indexHashKey; } @DynamoDBIndexRangeKey(globalSecondaryIndexName = "index") public String getIndexRangeKey() { return indexRangeKey; } public void setIndexRangeKey(String indexRangeKey) { this.indexRangeKey = indexRangeKey; } public String getAttrWithAttrAnnotation() { return attrWithAttrAnnotation; } public void setAttrWithAttrAnnotation(String attrWithAttrAnnotation) { this.attrWithAttrAnnotation = attrWithAttrAnnotation; } @DynamoDBVersionAttribute public String getVersionedAttr() { return versionedAttr; } public void setVersionedAttr(String versionedAttr) { this.versionedAttr = versionedAttr; } public String getCustomMarshallingAttr() { return customMarshallingAttr; } public void setCustomMarshallingAttr(String customMarshallingAttr) { this.customMarshallingAttr = customMarshallingAttr; } @DynamoDBIgnore public String getIgnoredAttr() { return ignoredAttr; } public void setIgnoredAttr(String ignoredAttr) { this.ignoredAttr = ignoredAttr; } } @SuppressWarnings("serial") private static final Map<String, String> expectedAttributeNames = new HashMap<String, String>() { { put("getHashKey", "hashKey"); put("getAutogeneratedRangeKey", "autogeneratedRangeKey"); put("getIndexHashKey", "indexHashKey"); put("getIndexRangeKey", "indexRangeKey"); put("getAttrWithAttrAnnotation", "real-attribute-name"); // w/ // attribute // name // override put("getVersionedAttr", "versionedAttr"); put("getCustomMarshallingAttr", "customMarshallingAttr"); } }; @Test public void testInheritedProperties() { // Base class assertEquals(3, reflector.getRelevantGetters(BaseTablePojo.class).size()); assertEquals("getParentHashKeyWithFieldAnnotation", reflector.getPrimaryHashKeyGetter(BaseTablePojo.class).getName()); assertEquals("parentHashKeyWithFieldAnnotation", reflector.getPrimaryHashKeyName(BaseTablePojo.class)); assertEquals("getParentRangeKeyWithGetterAnnotation", reflector.getPrimaryRangeKeyGetter(BaseTablePojo.class).getName()); assertEquals("parentRangeKeyWithGetterAnnotation", reflector.getPrimaryRangeKeyName(BaseTablePojo.class)); // Subclass pojo inherits the key getters, and defines an attribute that // is ignored in the superclass assertEquals(4, reflector.getRelevantGetters(TablePojoSubclass.class).size()); assertEquals(reflector.getPrimaryHashKeyGetter(BaseTablePojo.class), reflector.getPrimaryHashKeyGetter(TablePojoSubclass.class)); assertEquals("parentHashKeyWithFieldAnnotation", reflector.getPrimaryHashKeyName(TablePojoSubclass.class)); assertEquals(reflector.getPrimaryRangeKeyGetter(BaseTablePojo.class), reflector.getPrimaryRangeKeyGetter(TablePojoSubclass.class)); assertEquals("parentRangeKeyWithGetterAnnotation", reflector.getPrimaryRangeKeyName(TablePojoSubclass.class)); } @DynamoDBTable(tableName = "table") private static class BaseTablePojo { @DynamoDBHashKey private String parentHashKeyWithFieldAnnotation; private String parentRangeKeyWithGetterAnnotation; private String parentAttrWithNoAnnotation; @DynamoDBIgnore private String parentIgnoredAttr; public String getParentHashKeyWithFieldAnnotation() { return parentHashKeyWithFieldAnnotation; } public void setParentHashKeyWithFieldAnnotation( String parentHashKeyWithFieldAnnotation) { this.parentHashKeyWithFieldAnnotation = parentHashKeyWithFieldAnnotation; } @DynamoDBRangeKey public String getParentRangeKeyWithGetterAnnotation() { return parentRangeKeyWithGetterAnnotation; } public void setParentRangeKeyWithGetterAnnotation( String parentRangeKeyWithGetterAnnotation) { this.parentRangeKeyWithGetterAnnotation = parentRangeKeyWithGetterAnnotation; } public String getParentAttrWithNoAnnotation() { return parentAttrWithNoAnnotation; } public void setParentAttrWithNoAnnotation(String parentAttrWithNoAnnotation) { this.parentAttrWithNoAnnotation = parentAttrWithNoAnnotation; } public String getParentIgnoredAttr() { return parentIgnoredAttr; } public void setParentIgnoredAttr(String parentIgnoredAttr) { this.parentIgnoredAttr = parentIgnoredAttr; } } /** * Subclass of BaseTablePojo that inherits all the key attribtues, and * declared the parentIgnoredAttr which is ignored in the superclass. */ @DynamoDBTable(tableName = "table") private static class TablePojoSubclass extends BaseTablePojo { // Not ignored by the subclass private String parentIgnoredAttr; @Override public String getParentIgnoredAttr() { return parentIgnoredAttr; } @Override public void setParentIgnoredAttr(String parentIgnoredAttr) { this.parentIgnoredAttr = parentIgnoredAttr; } } }