/*
* 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;
}
}
}