
com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties 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 2016-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 com.amazonaws.annotation.SdkInternalApi;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.Reflect;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardAnnotationMaps.FieldMap;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardAnnotationMaps.TableMap;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardParameterTypes.ParamType;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Reflection assistant for {@link DynamoDBMapper}
*/
@SdkInternalApi
final class StandardBeanProperties {
/**
* Beans cache.
*/
private static final ConcurrentMap,Beans>> CACHE = new ConcurrentHashMap,Beans>>();
/**
* Returns the bean mappings for a given class (caches the results).
*/
static final Beans of(final Class clazz) {
if (!CACHE.containsKey(clazz)) {
final Beans beans = StandardBeanProperties.of(clazz, false);
if (beans.annotations().typed() == false) {
return beans; //<- don't cache un-modeled types
}
CACHE.putIfAbsent(clazz, beans);
}
return (Beans)CACHE.get(clazz);
}
/**
* Returns the bean mappings for a given class (does not cache).
*/
static final Beans of(final Class clazz, final boolean inherited) {
return new Beans(StandardAnnotationMaps.of(clazz), map(clazz, inherited));
}
/**
* Cache of {@link Bean} mappings by class type.
*/
static final class Beans extends DynamoDBMapperTableModel.Properties.Immutable {
private final Map> map;
private final TableMap annotations;
/**
* Constructs the bean mappings.
*/
private Beans(final TableMap annotations, final Map> map) {
super(annotations);
this.map = Collections.unmodifiableMap(map);
this.annotations = annotations;
}
/**
* Gets the annotations.
*/
final TableMap annotations() {
return this.annotations;
}
/**
* Gets the bean mappings.
*/
final Map> map() {
return this.map;
}
}
/**
* Holds the reflection bean properties for a given property.
*/
static final class Bean extends DynamoDBMapperFieldModel.Properties.Immutable {
private final FieldMap annotations;
private final Reflect reflect;
private final ParamType type;
private final Method getter;
/**
* Constructs an object property mapping for the specified method.
*/
private Bean(final FieldMap annotations, final Bean declaring, final Method getter, final String name) {
super(new DynamoDBMapperFieldModel.Properties.Buildable(annotations)
.withId(new DynamoDBMapperFieldModel.Id(declaring.id(), name))
.withAttributeName(name)
);
this.reflect = StandardMethodReflects.of(getter, declaring.reflect(), declaring.targetType());
this.type = StandardParameterTypes.of(getter.getGenericReturnType());
this.annotations = annotations;
this.getter = getter;
}
/**
* Constructs an object property mapping for the specified method.
*/
private Bean(final FieldMap annotations, final Method getter) {
super(new DynamoDBMapperFieldModel.Properties.Buildable(annotations)
.withId(new DynamoDBMapperFieldModel.Id(annotations.id(), annotations.attributeName()))
);
this.reflect = StandardMethodReflects.of(getter);
this.type = StandardParameterTypes.of(getter.getGenericReturnType());
this.annotations = annotations;
this.getter = getter;
}
/**
* Gets the annotations.
*/
final FieldMap annotations() {
return this.annotations;
}
/**
* Gets the property's value type.
*/
final Reflect reflect() {
return this.reflect;
}
/**
* Gets the parameter type.
*/
final ParamType type() {
return this.type;
}
/**
* Gets the getter method for this property.
*/
@Deprecated
final Method getter() {
return this.getter;
}
}
/**
* Returns the bean mappings for a given class (does not cache).
*/
private static final Map> map(final Class clazz, final boolean inherited) {
final Map> map = new LinkedHashMap>();
for (final Method m : clazz.getMethods()) {
if (isGetter(m) == false) {
continue;
} else if (!inherited && m.getDeclaringClass() != clazz && !StandardAnnotationMaps.of(m.getDeclaringClass()).typed()) {
continue;
}
final FieldMap annotations = StandardAnnotationMaps.of(clazz, m);
if (annotations.ignored()) {
continue;
}
flatten(new Bean(annotations, m), map);
}
return map;
}
/**
* Flattens or adds the bean to the mapping.
*/
private static final void flatten(final Bean bean, final Map> map) {
if (bean.annotations().flattened() == null) { //<- standard attribute
if (map.put(bean.attributeName(), bean) != null) {
throw new DynamoDBMappingException(bean.id().err("duplicate attribute name"));
}
return;
}
final Bean declaring = (Bean)bean; //<- cast to declaring type
final Map attributes = bean.annotations().attributes();
for (final Method m : declaring.targetType().getMethods()) {
if (isGetter(m) == false) {
continue;
}
final FieldMap annotations = StandardAnnotationMaps.of(declaring.targetType(), m);
String name = annotations.attributeName();
if (annotations.ignored() || (name = attributes.remove(name)) == null) {
continue;
}
flatten(new Bean(annotations, declaring, m, name), map);
}
if (!attributes.isEmpty()) { //<- this should be empty by now
throw new DynamoDBMappingException(bean.id().err("contains unknown flattened attribute(s): " + attributes));
}
}
/**
* Returns true if the method is a valid getter property.
*/
private static final boolean isGetter(final Method method) {
if (method.getName().matches("^(get|is).+") == false) {
return false;
} else if (method.getParameterTypes().length != 0) {
return false;
} else if (method.getReturnType() == Void.TYPE) {
return false;
} else if (method.isBridge()) {
return false;
} else if (method.isSynthetic()) {
return false;
} else if (method.getDeclaringClass() == Object.class) {
return false;
} else {
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy