
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAnnotationRegistry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-java-sdk-dynamodb Show documentation
Show all versions of aws-java-sdk-dynamodb Show documentation
The AWS Java SDK for Amazon DynamoDB module holds the client classes that are used for communicating with Amazon DynamoDB Service
/*
* Copyright 2011-2016 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.services.dynamodbv2.datamodeling;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.amazonaws.annotation.SdkInternalApi;
/**
* Map of DynamoDB annotations.
*/
@SdkInternalApi
final class DynamoDBAnnotationRegistry {
/**
* The logging utility.
*/
private static final Log log = LogFactory.getLog(DynamoDBAnnotationRegistry.class);
/**
* Gets all the DynamoDB annotations for a given class.
* @param clazz The class.
* @return The map of annotation type to annotation instance.
*/
final AnnotationMap annotationsOf(final Class> clazz) {
final AnnotationMap annotations = new AnnotationMap();
annotations.putAll(clazz.getAnnotations());
annotations.removeInvalidAnnotations();
return annotations;
}
/**
* Gets all the DynamoDB annotations; method annotations override the field level annotations.
* @param method The method.
* @param field The field.
* @return The map of annotation type to annotation instance.
*/
final AnnotationMap annotationsOf(final Method method, final Field field) {
final AnnotationMap annotations = new AnnotationMap();
if (field != null) {
annotations.putAll(field.getAnnotations());
}
annotations.putAll(method.getAnnotations());
annotations.removeInvalidAnnotations();
return annotations;
}
/**
* Map of annotation type to annotation instance.
*/
static final class AnnotationMap {
/**
* Map of annotation type to annotation instance.
*/
private final Map,Annotation> annotations;
/**
* Constructs an instance of {@code AnnotationMap}.
*/
private AnnotationMap() {
this.annotations = new HashMap,Annotation>();
}
/**
* Gets the annotations.
* @return The annotations.
*/
private final Map,Annotation> getAnnotations() {
return this.annotations;
}
/**
* Put all the DynamoDB annotations.
* @param annotations The array of annotations.
*/
private final void putAll(final Annotation[] annotations) {
if (annotations != null && annotations.length > 0) {
for (final Annotation annotation : annotations) {
if (annotation != null && annotation.annotationType().isAnnotationPresent(DynamoDB.class)) {
getAnnotations().put(annotation.annotationType(), annotation);
}
}
}
}
/**
* Removes any conflicting annotations.
* Note, we may consider throwing exceptions here instead in the future.
*/
private final void removeInvalidAnnotations() {
// Note, the fact this code exists indicates more thought should be placed
// into how we are exposing features as annotations. It may not be clear
// which annotations are compatible to our integrators without extensive
// documentation. The code should stand alone, or try it's best.
if (isAutoGeneratedKey()) {
if (!isHashKey() && !isRangeKey() && !isIndexHashKey() && !isIndexRangeKey()) {
log.warn(annotationOf(DynamoDBAutoGeneratedKey.class) + " is only compatible with keys");
getAnnotations().remove(DynamoDBAutoGeneratedKey.class);
} else {
if (isVersion()) {
log.warn(annotationOf(DynamoDBVersionAttribute.class) + " is not compatible with " + annotationOf(DynamoDBAutoGeneratedKey.class));
getAnnotations().remove(DynamoDBVersionAttribute.class);
}
if (isAutoGeneratedTimestamp()) {
throw new DynamoDBMappingException(annotationOf(DynamoDBAutoGeneratedTimestamp.class) +
" is not compatible with " + annotationOf(DynamoDBAutoGeneratedKey.class));
}
}
} else if (isVersion()) {
if (isAutoGeneratedTimestamp()) {
throw new DynamoDBMappingException(annotationOf(DynamoDBAutoGeneratedTimestamp.class) +
" is not compatible with " + annotationOf(DynamoDBVersionAttribute.class));
}
} else if (isAutoGeneratedTimestamp()) {
if (isHashKey() || isRangeKey()) {
throw new DynamoDBMappingException(annotationOf(DynamoDBAutoGeneratedTimestamp.class) +
" is not compatible with primary keys");
}
}
}
/**
* Gets the annotation of the specified type.
* @param clazz The annotation type.
* @return The annotation or null if not applicable.
*/
private final T annotationOf(final Class clazz) {
return (T)getAnnotations().get(clazz);
}
/**
* Determines if the {@code DynamoDBAttribute} is present.
* @return True if present, false otherwise.
*/
final boolean isAttribute() {
return getAnnotations().containsKey(DynamoDBAttribute.class);
}
/**
* Determines if the {@code DynamoDBAutoGeneratedKey} is present.
* @return True if present, false otherwise.
*/
final boolean isAutoGeneratedKey() {
return getAnnotations().containsKey(DynamoDBAutoGeneratedKey.class);
}
/**
* Determines if the {@code DynamoDBAutoGeneratedTimestamp} is present.
* @return True if present, false otherwise.
*/
final boolean isAutoGeneratedTimestamp() {
return getAnnotations().containsKey(DynamoDBAutoGeneratedTimestamp.class);
}
/**
* Determines if the {@code DynamoDBDocument} is present.
* @return True if present, false otherwise.
*/
final boolean isDocument() {
return getAnnotations().containsKey(DynamoDBDocument.class);
}
/**
* Determines if the {@code DynamoDBHashKey} is present.
* @return True if present, false otherwise.
*/
final boolean isHashKey() {
return getAnnotations().containsKey(DynamoDBHashKey.class);
}
/**
* Determines if the {@code DynamoDBIgnore} is present.
* @return True if present, false otherwise.
*/
final boolean isIgnore() {
return getAnnotations().containsKey(DynamoDBIgnore.class);
}
/**
* Determines if the {@code DynamoDBIndexHashKey} is present.
* @return True if present, false otherwise.
*/
final boolean isIndexHashKey() {
return getAnnotations().containsKey(DynamoDBIndexHashKey.class);
}
/**
* Determines if the {@code DynamoDBIndexRangeKey} is present.
* @return True if present, false otherwise.
*/
final boolean isIndexRangeKey() {
return getAnnotations().containsKey(DynamoDBIndexRangeKey.class);
}
/**
* Determines if the {@code DynamoDBMarshalling} is present.
* @return True if present, false otherwise.
*/
final boolean isMarshalling() {
return getAnnotations().containsKey(DynamoDBMarshalling.class);
}
/**
* Determines if the {@code DynamoDBNativeBoolean} is present.
* @return True if present, false otherwise.
*/
final boolean isNativeBoolean() {
return getAnnotations().containsKey(DynamoDBNativeBoolean.class);
}
/**
* Determines if the {@code DynamoDBRangeKey} is present.
* @return True if present, false otherwise.
*/
final boolean isRangeKey() {
return getAnnotations().containsKey(DynamoDBRangeKey.class);
}
/**
* Determines if the {@code DynamoDBTable} is present.
* @return True if present, false otherwise.
*/
final boolean isTable() {
return getAnnotations().containsKey(DynamoDBTable.class);
}
/**
* Determines if the {@code DynamoDBVersionAttribute} is present.
* @return True if present, false otherwise.
*/
final boolean isVersion() {
return getAnnotations().containsKey(DynamoDBVersionAttribute.class);
}
/**
* Gets the attribute name defaulting if required.
* @return The attribute name.
*/
final String getAttributeName() {
if (isHashKey()) {
final DynamoDBHashKey annotation = annotationOf(DynamoDBHashKey.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
if (isIndexHashKey()) {
final DynamoDBIndexHashKey annotation = annotationOf(DynamoDBIndexHashKey.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
if (isRangeKey()) {
final DynamoDBRangeKey annotation = annotationOf(DynamoDBRangeKey.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
if (isIndexRangeKey()) {
final DynamoDBIndexRangeKey annotation = annotationOf(DynamoDBIndexRangeKey.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
if (isAttribute()) {
final DynamoDBAttribute annotation = annotationOf(DynamoDBAttribute.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
if (isVersion()) {
final DynamoDBVersionAttribute annotation = annotationOf(DynamoDBVersionAttribute.class);
if (!annotation.attributeName().isEmpty()) {
return annotation.attributeName();
}
}
return null;
}
/**
* Gets the global secondary index names if applicable.
* @return The names.
*/
final Collection getGlobalSecondaryIndexNamesOfIndexHashKey() {
final DynamoDBIndexHashKey annotation = annotationOf(DynamoDBIndexHashKey.class);
if (annotation == null) {
return Collections.emptySet();
}
return resolveIndexNames(annotation, annotation.globalSecondaryIndexName(), annotation.globalSecondaryIndexNames());
}
/**
* Gets the global secondary index names if applicable.
* @return The names.
*/
final Collection getGlobalSecondaryIndexNamesOfIndexRangeKey() {
final DynamoDBIndexRangeKey annotation = annotationOf(DynamoDBIndexRangeKey.class);
if (annotation == null) {
return Collections.emptySet();
}
return resolveIndexNames(annotation, annotation.globalSecondaryIndexName(), annotation.globalSecondaryIndexNames());
}
/**
* Gets the local secondary index names if applicable.
* @return The names.
*/
final Collection getLocalSecondaryIndexNamesOfIndexRangeKey() {
final DynamoDBIndexRangeKey annotation = annotationOf(DynamoDBIndexRangeKey.class);
if (annotation == null) {
return Collections.emptySet();
}
return resolveIndexNames(annotation, annotation.localSecondaryIndexName(), annotation.localSecondaryIndexNames());
}
/**
* Gets the auto-generate strategy.
* @return The auto-generate strategy, null if not specified.
*/
final DynamoDBAutoGenerateStrategy getAutoGenerateStrategy() {
final DynamoDBAutoGeneratedTimestamp annotation = annotationOf(DynamoDBAutoGeneratedTimestamp.class);
if (annotation == null) {
return null;
}
return annotation.strategy();
}
/**
* Gets the marshaller class.
* @return The marshaller class, null if not specified.
*/
final Class extends DynamoDBMarshaller>> getMarshallerClass() {
final DynamoDBMarshalling annotation = annotationOf(DynamoDBMarshalling.class);
if (annotation == null) {
return null;
}
return annotation.marshallerClass();
}
/**
* Gets the table name.
* @return The table name, null if not specified.
*/
final String getTableName() {
final DynamoDBTable annotation = annotationOf(DynamoDBTable.class);
if (annotation == null) {
return null;
}
return annotation.tableName();
}
/**
* Resolves between which name/names to use.
* @param annotation The annotation.
* @param name The singular name.
* @param names The multiple names.
* @return The names, null if they could not be resolved.
*/
private static final Collection resolveIndexNames(final Annotation annotation, final String name, final String[] names) {
if (name == null || name.isEmpty()) {
if (names == null || names.length == 0) {
return Collections.emptySet();
} else {
return Arrays.asList(names);
}
} else if (names == null || names.length == 0) {
return Collections.singleton(name);
} else {
throw new DynamoDBMappingException(annotation + " contain both index name and names");
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy