All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.services.dynamodb.datamodeling.DynamoDBReflector Maven / Gradle / Ivy

Go to download

The Amazon Web Services SDK for Java provides Java APIs for building software on AWS' cost-effective, scalable, and reliable infrastructure products. The AWS Java SDK allows developers to code against APIs for all of Amazon's infrastructure web services (Amazon S3, Amazon EC2, Amazon SQS, Amazon Relational Database Service, Amazon AutoScaling, etc).

The newest version!
/*
 * Copyright 2011-2014 Amazon Technologies, 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://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.dynamodb.datamodeling;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import java.nio.ByteBuffer;

import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.util.DateUtils;

/**
 * Reflection assistant for {@link DynamoDBMapper}
 * @deprecated Use {@link com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBReflector} instead.
 */
@Deprecated
public class DynamoDBReflector {

    /*
     * Several caches for performance. Collectively, they can make this class
     * over twice as fast.
     */
    private final Map, Collection> getterCache = new HashMap, Collection>();
    private final Map, Method> hashKeyGetterCache = new HashMap, Method>();
    private final Map, Method> rangeKeyGetterCache = new HashMap, Method>();

    /*
     * All caches keyed by a Method use the getter for a particular mapped
     * property
     */
    private final Map setterCache = new HashMap();
    private final Map attributeNameCache = new HashMap();
    private final Map argumentUnmarshallerCache = new HashMap();
    private final Map argumentMarshallerCache = new HashMap();
    private final Map versionArgumentMarshallerCache = new HashMap();
    private final Map keyArgumentMarshallerCache = new HashMap();
    private final Map versionAttributeGetterCache = new HashMap();
    private final Map autoGeneratedKeyGetterCache = new HashMap();

    /**
     * Returns the set of getter methods which are relevant when marshalling or
     * unmarshalling an object.
     */
    Collection getRelevantGetters(Class clazz) {
        synchronized (getterCache) {
            if ( !getterCache.containsKey(clazz) ) {
                List relevantGetters = new LinkedList();
                for ( Method m : clazz.getMethods() ) {
                    if ( isRelevantGetter(m) ) {
                        relevantGetters.add(m);
                    }
                }
                getterCache.put(clazz, relevantGetters);
            }
        }
        return getterCache.get(clazz);
    }

    /**
     * Returns whether the method given is a getter method we should serialize /
     * deserialize to the service. The method must begin with "get" or "is",
     * have no arguments, belong to a class that declares its table, and not be
     * marked ignored.
     */
    private boolean isRelevantGetter(Method m) {
        return (m.getName().startsWith("get") || m.getName().startsWith("is")) && m.getParameterTypes().length == 0
                && m.getDeclaringClass().getAnnotation(DynamoDBTable.class) != null
                && !m.isAnnotationPresent(DynamoDBIgnore.class);
    }

    /**
     * Returns the annotated {@link DynamoDBRangeKey} getter for the class
     * given, or null if the class doesn't have one.
     */
     Method getRangeKeyGetter(Class clazz) {
        synchronized (rangeKeyGetterCache) {
            if ( !rangeKeyGetterCache.containsKey(clazz) ) {
                Method rangeKeyMethod = null;
                for ( Method method : getRelevantGetters(clazz) ) {
                    if ( method.getParameterTypes().length == 0 && method.isAnnotationPresent(DynamoDBRangeKey.class)) {
                        rangeKeyMethod = method;
                        break;
                    }
                }
                rangeKeyGetterCache.put(clazz, rangeKeyMethod);
            }
        }
        return rangeKeyGetterCache.get(clazz);
    }

    /**
     * Returns the annotated {@link DynamoDBHashKey} getter for the class given,
     * throwing an exception if there isn't one.
     */
     Method getHashKeyGetter(Class clazz) {
        synchronized (hashKeyGetterCache) {
            if ( !hashKeyGetterCache.containsKey(clazz) ) {
                for ( Method method : getRelevantGetters(clazz) ) {
                    if ( method.getParameterTypes().length == 0 && method.isAnnotationPresent(DynamoDBHashKey.class)) {
                        hashKeyGetterCache.put(clazz, method);
                        break;
                    }
                }
            }
        }

        Method hashKeyMethod = hashKeyGetterCache.get(clazz);
        if ( hashKeyMethod == null ) {
            throw new DynamoDBMappingException("Public, zero-parameter hash key property must be annotated with "
                    + DynamoDBHashKey.class);
        }
        return hashKeyMethod;
    }

    /**
     * Returns the {@link DynamoDBTable} annotation of the class given, throwing
     * a runtime exception if it isn't annotated.
     */
     DynamoDBTable getTable(Class clazz) {
        DynamoDBTable table = clazz.getAnnotation(DynamoDBTable.class);
        if ( table == null )
            throw new DynamoDBMappingException("Class " + clazz + " must be annotated with " + DynamoDBTable.class);
        return table;
    }

    /**
     * Returns whether or not this getter has a custom marshaller
     */
    private boolean isCustomMarshaller(Method getter) {
        return getter.isAnnotationPresent(DynamoDBMarshalling.class);
    }

    /**
     * Returns the argument unmarshaller used to unmarshall the getter / setter
     * pair given.
     * 

* Determining how to unmarshall a response, especially a numeric one, * requires checking it against all supported types. This is expensive, so * we cache a lookup table of getter method to argument unmarhsaller which * can be reused. * * @param toReturn * The typed domain object being unmarshalled for the client * @param getter * The getter method being considered * @param setter * The corresponding setter method being considered */ ArgumentUnmarshaller getArgumentUnmarshaller(final T toReturn, final Method getter, final Method setter) { synchronized (argumentUnmarshallerCache) { if ( !argumentUnmarshallerCache.containsKey(getter) ) { Class[] parameterTypes = setter.getParameterTypes(); Class paramType = parameterTypes[0]; if ( parameterTypes.length != 1 ) { throw new DynamoDBMappingException("Expected exactly one agument to " + setter); } ArgumentUnmarshaller unmarshaller = null; if ( isCustomMarshaller(getter) ) { unmarshaller = new SUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return getCustomMarshalledValue(toReturn, getter, value); } }; } else { // If we're dealing with a collection, we need to get the // underlying type out of it boolean isCollection = false; if ( Set.class.isAssignableFrom(paramType) ) { isCollection = true; Type genericType = setter.getGenericParameterTypes()[0]; if ( genericType instanceof ParameterizedType ) { if (((ParameterizedType) genericType).getActualTypeArguments()[0].toString().equals("byte[]")) { paramType = byte[].class; } else { paramType = (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0]; } } } else if ( Collection.class.isAssignableFrom(paramType) ) { throw new DynamoDBMappingException("Only java.util.Set collection types are permitted for " + DynamoDBAttribute.class); } if ( double.class.isAssignableFrom(paramType) || Double.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Double.parseDouble(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Double.parseDouble(value.getN()); } }; } } else if ( BigDecimal.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(new BigDecimal(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return new BigDecimal(value.getN()); } }; } } else if ( BigInteger.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { ((Set) argument).add(new BigInteger(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return new BigInteger(value.getN()); } }; } } else if ( int.class.isAssignableFrom(paramType) || Integer.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Integer.parseInt(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Integer.parseInt(value.getN()); } }; } } else if ( float.class.isAssignableFrom(paramType) || Float.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Float.parseFloat(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Float.parseFloat(value.getN()); } }; } } else if ( byte.class.isAssignableFrom(paramType) || Byte.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Byte.parseByte(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Byte.parseByte(value.getN()); } }; } } else if ( long.class.isAssignableFrom(paramType) || Long.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Long.parseLong(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Long.parseLong(value.getN()); } }; } } else if ( short.class.isAssignableFrom(paramType) || Short.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(Short.parseShort(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return Short.parseShort(value.getN()); } }; } } else if ( boolean.class.isAssignableFrom(paramType) || Boolean.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new NSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getNS() ) { argument.add(parseBoolean(s)); } return argument; } }; } else { unmarshaller = new NUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return parseBoolean(value.getN()); } }; } } else if ( Date.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new SSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { Set argument = new HashSet(); for ( String s : value.getSS() ) { argument.add(new DateUtils().parseIso8601Date(s)); } return argument; } }; } else { unmarshaller = new SUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { return new DateUtils().parseIso8601Date(value.getS()); } }; } } else if ( Calendar.class.isAssignableFrom(paramType) ) { if ( isCollection ) { unmarshaller = new SSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { Set argument = new HashSet(); for ( String s : value.getSS() ) { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new DateUtils().parseIso8601Date(s)); argument.add(cal); } return argument; } }; } else { unmarshaller = new SUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new DateUtils().parseIso8601Date(value.getS())); return cal; } }; } } else if (ByteBuffer.class.isAssignableFrom(paramType)) { if ( isCollection ) { unmarshaller = new BSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { Set argument = new HashSet(); for (ByteBuffer b : value.getBS()) { argument.add(b); } return argument; } }; } else { unmarshaller = new BUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { return value.getB(); } }; } } else if (byte[].class.isAssignableFrom(paramType)) { if ( isCollection ) { unmarshaller = new BSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { Set argument = new HashSet(); for (ByteBuffer b : value.getBS()) { byte[] bytes = null; if (b.hasArray()) { bytes = b.array(); } else { bytes = new byte[b.limit()]; b.get(bytes, 0, bytes.length); } argument.add(bytes); } return argument; } }; } else { unmarshaller = new BUnmarshaller() { @Override public Object unmarshall(AttributeValue value) throws ParseException { ByteBuffer byteBuffer = value.getB(); byte[] bytes = null; if (byteBuffer.hasArray()) { bytes = byteBuffer.array(); } else { bytes = new byte[byteBuffer.limit()]; byteBuffer.get(bytes, 0, bytes.length); } return bytes; } }; } } /* * After checking all other supported types, enforce a * String match */ else if ( !String.class.isAssignableFrom(paramType) ) { throw new DynamoDBMappingException("Expected a String, but was " + paramType); } else { if ( isCollection ) { unmarshaller = new SSUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { Set argument = new HashSet(); for ( String s : value.getSS() ) { argument.add(s); } return argument; } }; } else { unmarshaller = new SUnmarshaller() { @Override public Object unmarshall(AttributeValue value) { return value.getS(); } }; } } } argumentUnmarshallerCache.put(getter, unmarshaller); } } return argumentUnmarshallerCache.get(getter); } /** * Marshalls the custom value given into the proper return type. */ @SuppressWarnings({ "rawtypes", "unchecked" }) private T getCustomMarshalledValue(T toReturn, Method getter, AttributeValue value) { DynamoDBMarshalling annotation = getter.getAnnotation(DynamoDBMarshalling.class); Class> marshallerClass = annotation.marshallerClass(); DynamoDBMarshaller marshaller; try { marshaller = marshallerClass.newInstance(); } catch ( InstantiationException e ) { throw new DynamoDBMappingException("Couldn't instantiate marshaller of class " + marshallerClass, e); } catch ( IllegalAccessException e ) { throw new DynamoDBMappingException("Couldn't instantiate marshaller of class " + marshallerClass, e); } return (T) marshaller.unmarshall(getter.getReturnType(), value.getS()); } /** * Returns an attribute value for the getter method with a custom marshaller */ @SuppressWarnings({ "rawtypes", "unchecked" }) private AttributeValue getCustomerMarshallerAttributeValue(Method getter, Object getterReturnResult) { DynamoDBMarshalling annotation = getter.getAnnotation(DynamoDBMarshalling.class); Class> marshallerClass = annotation.marshallerClass(); DynamoDBMarshaller marshaller; try { marshaller = marshallerClass.newInstance(); } catch ( InstantiationException e ) { throw new DynamoDBMappingException("Failed to instantiate custom marshaller for class " + marshallerClass, e); } catch ( IllegalAccessException e ) { throw new DynamoDBMappingException("Failed to instantiate custom marshaller for class " + marshallerClass, e); } String stringValue = marshaller.marshall(getterReturnResult); return new AttributeValue().withS(stringValue); } /** * Returns a marshaller that knows how to provide an AttributeValue for the * result of the getter given. */ ArgumentMarshaller getArgumentMarshaller(final Method getter) { synchronized (argumentMarshallerCache) { if ( !argumentMarshallerCache.containsKey(getter) ) { ArgumentMarshaller marshaller = null; if ( isCustomMarshaller(getter) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return getCustomerMarshallerAttributeValue(getter, obj); } }; } else { Class returnType = getter.getReturnType(); if ( Set.class.isAssignableFrom(returnType) ) { Type genericType = getter.getGenericReturnType(); if ( genericType instanceof ParameterizedType ) { if ( ((ParameterizedType) genericType).getActualTypeArguments()[0].toString().equals("byte[]") ) { returnType = byte[].class; } else { returnType = (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0]; } } if ( Date.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List timestamps = new LinkedList(); for ( Object o : (Set) obj ) { timestamps.add(new DateUtils().formatIso8601Date((Date) o)); } return new AttributeValue().withSS(timestamps); } }; } else if ( Calendar.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List timestamps = new LinkedList(); for ( Object o : (Set) obj ) { timestamps.add(new DateUtils().formatIso8601Date(((Calendar) o).getTime())); } return new AttributeValue().withSS(timestamps); } }; } else if ( boolean.class.isAssignableFrom(returnType) || Boolean.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List booleanAttributes = new ArrayList(); for ( Object b : (Set) obj ) { if ( b == null || !(Boolean) b ) { booleanAttributes.add("0"); } else { booleanAttributes.add("1"); } } return new AttributeValue().withNS(booleanAttributes); } }; } else if ( returnType.isPrimitive() || Number.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List attributes = new ArrayList(); for ( Object o : (Set) obj ) { attributes.add(String.valueOf(o)); } return new AttributeValue().withNS(attributes); } }; } else if (ByteBuffer.class.isAssignableFrom(returnType)) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List attributes = new ArrayList(); for ( Object o : (Set) obj ) { attributes.add((ByteBuffer) o); } return new AttributeValue().withBS(attributes); } }; } else if (byte[].class.isAssignableFrom(returnType)) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List attributes = new ArrayList(); for ( Object o : (Set) obj ) { attributes.add(ByteBuffer.wrap((byte[])o)); } return new AttributeValue().withBS(attributes); } }; } else { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { List attributes = new ArrayList(); for ( Object o : (Set) obj ) { attributes.add(String.valueOf(o)); } return new AttributeValue().withSS(attributes); } }; } } else if ( Collection.class.isAssignableFrom(returnType) ) { throw new DynamoDBMappingException("Non-set collections aren't supported: " + (getter.getDeclaringClass() + "." + getter.getName())); } else { if ( Date.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return new AttributeValue().withS(new DateUtils().formatIso8601Date((Date) obj)); } }; } else if ( Calendar.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return new AttributeValue().withS(new DateUtils() .formatIso8601Date(((Calendar) obj).getTime())); } }; } else if ( boolean.class.isAssignableFrom(returnType) || Boolean.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( obj == null || !(Boolean) obj ) { return new AttributeValue().withN("0"); } else { return new AttributeValue().withN("1"); } } }; } else if ( returnType.isPrimitive() || Number.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return new AttributeValue().withN(String.valueOf(obj)); } }; } else if ( returnType == String.class ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( ((String) obj).length() == 0 ) return null; return new AttributeValue().withS(String.valueOf(obj)); } }; } else if ( returnType == ByteBuffer.class ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return new AttributeValue().withB((ByteBuffer)obj); } }; } else if ( returnType == byte[].class) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { return new AttributeValue().withB(ByteBuffer.wrap((byte[])obj)); } }; } else { throw new DynamoDBMappingException("Unsupported type: " + returnType + " for " + getter); } } } argumentMarshallerCache.put(getter, marshaller); } } return argumentMarshallerCache.get(getter); } /** * Attempts to parse the string given as a boolean and return its value. * Throws an exception if the value is anything other than 0 or 1. */ private boolean parseBoolean(String s) { if ( "1".equals(s) ) { return true; } else if ( "0".equals(s) ) { return false; } else { throw new IllegalArgumentException("Expected 1 or 0 for boolean value, was " + s); } } /** * Returns the attribute name corresponding to the given getter method. */ String getAttributeName(Method getter) { synchronized (attributeNameCache) { if ( !attributeNameCache.containsKey(getter) ) { // First check for a hash key annotation DynamoDBHashKey hashKeyAnnotation = getter.getAnnotation(DynamoDBHashKey.class); if ( hashKeyAnnotation != null && hashKeyAnnotation.attributeName() != null && hashKeyAnnotation.attributeName().length() > 0 ) return hashKeyAnnotation.attributeName(); // Then a range key DynamoDBRangeKey rangeKey = getter.getAnnotation(DynamoDBRangeKey.class); if ( rangeKey != null && rangeKey.attributeName() != null && rangeKey.attributeName().length() > 0 ) return rangeKey.attributeName(); // Then an attribute DynamoDBAttribute attribute = getter.getAnnotation(DynamoDBAttribute.class); if ( attribute != null && attribute.attributeName() != null && attribute.attributeName().length() > 0 ) return attribute.attributeName(); // Finally a version attribute DynamoDBVersionAttribute version = getter.getAnnotation(DynamoDBVersionAttribute.class); if ( version != null && version.attributeName() != null && version.attributeName().length() > 0 ) return version.attributeName(); // Default to method name String attributeName = null; if ( getter.getName().startsWith("get") ) { attributeName = getter.getName().substring("get".length()); } else if ( getter.getName().startsWith("is") ) { attributeName = getter.getName().substring("is".length()); } else { throw new DynamoDBMappingException("Getter must begin with 'get' or 'is'"); } // Lowercase the first letter of the name attributeName = attributeName.substring(0, 1).toLowerCase() + attributeName.substring(1); attributeNameCache.put(getter, attributeName); } } return attributeNameCache.get(getter); } /** * Returns the setter corresponding to the getter given, or null if no such * setter exists. */ Method getSetter(Method getter) { synchronized (setterCache) { if ( !setterCache.containsKey(getter) ) { String attributeName = null; if ( getter.getName().startsWith("get") ) { attributeName = getter.getName().substring("get".length()); } else if ( getter.getName().startsWith("is") ) { attributeName = getter.getName().substring("is".length()); } else { // should be impossible to reach this exception throw new RuntimeException("Getter method must start with 'is' or 'get'"); } String setterName = "set" + attributeName; Method setter = null; try { setter = getter.getDeclaringClass().getMethod(setterName, getter.getReturnType()); } catch ( NoSuchMethodException e ) { throw new DynamoDBMappingException("Expected a public, one-argument method called " + setterName + " on class " + getter.getDeclaringClass(), e); } catch ( SecurityException e ) { throw new DynamoDBMappingException("No access to public, one-argument method called " + setterName + " on class " + getter.getDeclaringClass(), e); } setterCache.put(getter, setter); } } return setterCache.get(getter); } /** * Returns a marshaller that knows how to provide an AttributeValue for the * getter method given. Also increments the value of the getterReturnResult * given. */ ArgumentMarshaller getVersionedArgumentMarshaller(final Method getter, Object getterReturnResult) { synchronized (versionArgumentMarshallerCache) { if ( !versionArgumentMarshallerCache.containsKey(getter) ) { ArgumentMarshaller marshaller = null; final Class returnType = getter.getReturnType(); if ( BigInteger.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( obj == null ) obj = BigInteger.ZERO; Object newValue = ((BigInteger) obj).add(BigInteger.ONE); return getArgumentMarshaller(getter).marshall(newValue); } }; } else if ( Integer.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( obj == null ) obj = new Integer(0); Object newValue = ((Integer) obj).intValue() + 1; return getArgumentMarshaller(getter).marshall(newValue); } }; } else if ( Byte.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( obj == null ) obj = new Byte((byte) 0); Object newValue = (byte) ((((Byte) obj).byteValue() + 1) % Byte.MAX_VALUE); return getArgumentMarshaller(getter).marshall(newValue); } }; } else if ( Long.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { if ( obj == null ) obj = new Long(0); Object newValue = ((Long) obj).longValue() + 1L; return getArgumentMarshaller(getter).marshall(newValue); } }; } else { throw new DynamoDBMappingException("Unsupported parameter type for " + DynamoDBVersionAttribute.class + ": " + returnType + ". Must be a whole-number type."); } versionArgumentMarshallerCache.put(getter, marshaller); } } return versionArgumentMarshallerCache.get(getter); } /** * Returns a marshaller for the auto-generated key returned by the getter given. */ ArgumentMarshaller getAutoGeneratedKeyArgumentMarshaller(final Method getter) { synchronized (keyArgumentMarshallerCache) { if ( !keyArgumentMarshallerCache.containsKey(getter) ) { ArgumentMarshaller marshaller = null; Class returnType = getter.getReturnType(); if ( String.class.isAssignableFrom(returnType) ) { marshaller = new ArgumentMarshaller() { @Override public AttributeValue marshall(Object obj) { String newValue = UUID.randomUUID().toString(); return getArgumentMarshaller(getter).marshall(newValue); } }; } else { throw new DynamoDBMappingException("Unsupported type for " + getter + ": " + returnType + ". Only Strings are supported when auto-generating keys."); } keyArgumentMarshallerCache.put(getter, marshaller); } } return keyArgumentMarshallerCache.get(getter); } /** * Returns whether the method given is an annotated, no-args getter of a * version attribute. */ boolean isVersionAttributeGetter(Method getter) { synchronized (versionAttributeGetterCache) { if ( !versionAttributeGetterCache.containsKey(getter) ) { versionAttributeGetterCache.put( getter, getter.getName().startsWith("get") && getter.getParameterTypes().length == 0 && getter.isAnnotationPresent(DynamoDBVersionAttribute.class)); } } return versionAttributeGetterCache.get(getter); } /** * Returns whether the method given is an assignable key getter. */ boolean isAssignableKey(Method getter) { synchronized (autoGeneratedKeyGetterCache) { if ( !autoGeneratedKeyGetterCache.containsKey(getter) ) { autoGeneratedKeyGetterCache.put( getter, getter.isAnnotationPresent(DynamoDBAutoGeneratedKey.class) && (getter.isAnnotationPresent(DynamoDBHashKey.class) || getter .isAnnotationPresent(DynamoDBRangeKey.class))); } } return autoGeneratedKeyGetterCache.get(getter); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy