com.amazonaws.services.dynamodbv2.datamodeling.ConversionSchemas Maven / Gradle / Ivy
Show all versions of aws-java-sdk-osgi Show documentation
/*
 * Copyright 2014-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.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.BinaryAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.BinarySetAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.BooleanAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.ListAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.MapAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.NumberAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.NumberSetAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.StringAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.ArgumentMarshaller.StringSetAttributeMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.DynamoDBAttributeType;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.BooleanSetToNumberSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.BooleanToBooleanMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.BooleanToNumberMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ByteArraySetToBinarySetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ByteArrayToBinaryMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ByteBufferSetToBinarySetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ByteBufferToBinaryMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.CalendarSetToStringSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.CalendarToStringMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.CollectionToListMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.CustomMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.DateSetToStringSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.DateToStringMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.MapToMapMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.NumberSetToNumberSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.NumberToNumberMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ObjectSetToStringSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ObjectToMapMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.ObjectToStringMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.S3LinkToStringMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.StringSetToStringSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.StringToStringMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.marshallers.UUIDSetToStringSetMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BigDecimalSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BigDecimalUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BigIntegerSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BigIntegerUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BooleanSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.BooleanUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteArraySetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteArrayUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteBufferSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteBufferUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ByteUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.CalendarSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.CalendarUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.CustomUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.DateSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.DateUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.DoubleSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.DoubleUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.FloatSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.FloatUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.IntegerSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.IntegerUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ListUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.LongSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.LongUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.MapUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.NullableUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ObjectSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ObjectUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.S3LinkUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ShortSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.ShortUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.StringSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.StringUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.UUIDSetUnmarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.unmarshallers.UUIDUnmarshaller;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
/**
 * Pre-defined strategies for mapping between Java types and DynamoDB types.
 */
public final class ConversionSchemas {
    private static final Log LOGGER =
            LogFactory.getLog(ConversionSchemas.class);
    /**
     * The V1 schema mapping, which retains strict backwards compatibility with
     * the original DynamoDB data model. In particular, it marshals Java
     * Booleans as DynamoDB Numbers rather than the newer Boolean type, and does
     * not support marshaling Lists or Maps. It can unmarshal
     * values written in newer formats to ease migration.
     * 
     * Use me if you have other code still using an old version of the SDK that
     * does not understand the new List and Map types and want to ensure that
     * you don't accidentally start writing values using these types.
     */
    public static final ConversionSchema V1 =
            new StandardConversionSchema(
                    "V1ConversionSchema",
                    new V1MarshallerSet(),
                    new StandardUnmarshallerSet());
    /**
     * A V2 conversion schema which retains backwards compatibility with the
     * V1 conversion schema for existing DynamoDB types, but adds the ability
     * to marshall recursive structures using the new List and Map types. This
     * is currently the default conversion schema.
     */
    public static final ConversionSchema V2_COMPATIBLE =
            new StandardConversionSchema(
                    "V2CompatibleConversionSchema",
                    new V2CompatibleMarshallerSet(),
                    new StandardUnmarshallerSet());
    /**
     * The native V2 conversion schema. This schema breaks compatibility with
     * older versions of the mapper that only support the V1 schema by
     * storing booleans as native DynamoDB Booleans rather than as a 1 or 0
     * in a DynamoDB Number. Switching to the V2 schema will prevent older
     * versions of the mapper from reading items you write that contain
     * booleans.
     */
    public static final ConversionSchema V2 =
            new StandardConversionSchema(
                    "V2ConversionSchema",
                    new V2MarshallerSet(),
                    new StandardUnmarshallerSet());
    static final ConversionSchema DEFAULT = V2_COMPATIBLE;
    static class StandardConversionSchema implements ConversionSchema {
        private final String name;
        private final MarshallerSet marshallers;
        private final UnmarshallerSet unmarshallers;
        public StandardConversionSchema(
                String name,
                MarshallerSet marshallers,
                UnmarshallerSet unmarshallers) {
            this.name = name;
            this.marshallers = new CachingMarshallerSet(
                    new AnnotationAwareMarshallerSet(marshallers));
            this.unmarshallers = new CachingUnmarshallerSet(
                    new AnnotationAwareUnmarshallerSet(unmarshallers));
        }
        @Override
        public ItemConverter getConverter(Dependencies dependencies) {
            S3ClientCache s3cc = dependencies.get(S3ClientCache.class);
            return new StandardItemConverter(
                    marshallers,
                    unmarshallers,
                    DynamoDBMappingsRegistry.instance(),
                    s3cc);
        }
        @Override
        public String toString() {
            return name;
        }
    }
    static class StandardItemConverter implements ItemConverter {
        private final MarshallerSet marshallerSet;
        private final UnmarshallerSet unmarshallerSet;
        private final DynamoDBMappingsRegistry registry;
        private final S3ClientCache s3cc;
        public StandardItemConverter(
                MarshallerSet marshallerSet,
                UnmarshallerSet unmarshallerSet,
                DynamoDBMappingsRegistry registry,
                S3ClientCache s3cc) {
            this.marshallerSet = marshallerSet;
            this.unmarshallerSet = unmarshallerSet;
            this.registry = registry;
            this.s3cc = s3cc;
        }
        @Override
        public DynamoDBMapperFieldModel getFieldModel(Method getter) {
            final DynamoDBMappingsRegistry.Mapping mapping = registry.mappingOf(getter);
            ArgumentMarshaller marshaller = getMarshaller(getter);
            DynamoDBAttributeType attributeType = null;
            if (marshaller instanceof StringAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.S;
            } else if (marshaller instanceof NumberAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.N;
            } else if (marshaller instanceof BinaryAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.B;
            } else if (marshaller instanceof StringSetAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.SS;
            } else if (marshaller instanceof NumberSetAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.NS;
            } else if (marshaller instanceof BinarySetAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.BS;
            } else if (marshaller instanceof BooleanAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.BOOL;
            } else if (marshaller instanceof ListAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.L;
            } else if (marshaller instanceof MapAttributeMarshaller) {
                attributeType = DynamoDBAttributeType.M;
            } else {
                throw new DynamoDBMappingException(
                        "Unrecognized marshaller type for " + getter + ": "
                                + marshaller);
            }
            return new DynamoDBMapperFieldModel(mapping.getAttributeName(), attributeType, marshaller);
        }
        @Override
        public AttributeValue convert(Method getter, Object object) {
            if (object == null) {
                return null;
            }
            ArgumentMarshaller marshaller = getMarshaller(getter);
            return marshaller.marshall(object);
        }
        @Override
        public Map convert(Object object) {
            if (object == null) {
                return null;
            }
            Class> clazz = object.getClass();
            Map result =
                    new HashMap();
            final DynamoDBMappingsRegistry.Mappings mappings = registry.mappingsOf(clazz);
            for (final DynamoDBMappingsRegistry.Mapping mapping : mappings.getMappings()) {
                Object getterResult =
                        mapping.getValueOf(object);
                if (getterResult != null) {
                    AttributeValue value = convert(mapping.getter(), getterResult);
                    if (value != null) {
                        result.put(mapping.getAttributeName(), value);
                    }
                }
            }
            return result;
        }
        private ArgumentMarshaller getMarshaller(Method getter) {
            ArgumentMarshaller marshaller =
                    marshallerSet.getMarshaller(getter);
            marshaller = augment(getter.getGenericReturnType(), marshaller);
            return marshaller;
        }
        private ArgumentMarshaller getMemberMarshaller(Type type) {
            ArgumentMarshaller marshaller =
                    marshallerSet.getMemberMarshaller(type);
            marshaller = augment(type, marshaller);
            return marshaller;
        }
        private ArgumentMarshaller augment(
                Type type,
                ArgumentMarshaller marshaller) {
            if (marshaller instanceof CollectionToListMarshaller) {
                return getCollectionToListMarshaller(type);
            }
            if (marshaller instanceof MapToMapMarshaller) {
                return getMapToMapMarshaller(type);
            }
            if (marshaller instanceof ObjectToMapMarshaller) {
                return getObjectToMapMarshaller(type);
            }
            return marshaller;
        }
        private ArgumentMarshaller getCollectionToListMarshaller(Type type) {
            if (!(type instanceof ParameterizedType)) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the "
                        + "Collection type " + type + ", which is not "
                        + "parameterized.");
            }
            ParameterizedType ptype = (ParameterizedType) type;
            Type[] args = ptype.getActualTypeArguments();
            if (args == null || args.length != 1) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the "
                        + "Collection type " + type + "; unexpected number of "
                        + "type arguments.");
            }
            ArgumentMarshaller memberMarshaller =
                    getMemberMarshaller(args[0]);
            return new CollectionToListMarshaller(memberMarshaller);
        }
        private ArgumentMarshaller getMapToMapMarshaller(Type type) {
            if (!(type instanceof ParameterizedType)) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Map "
                        + "type " + type + ", which is not parameterized.");
            }
            ParameterizedType ptype = (ParameterizedType) type;
            Type[] args = ptype.getActualTypeArguments();
            if (args == null || args.length != 2) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Map "
                        + "type " + type + "; unexpected number of type "
                        + "arguments.");
            }
            if (args[0] != String.class) {
                throw new DynamoDBMappingException(
                        "Only Map is supported.");
            }
            ArgumentMarshaller memberMarshaller =
                    getMemberMarshaller(args[1]);
            return new MapToMapMarshaller(memberMarshaller);
        }
        private ArgumentMarshaller getObjectToMapMarshaller(Type type) {
            Type localType = type;
            if (localType instanceof ParameterizedType) {
                localType = ((ParameterizedType) localType).getRawType();
            }
            if (!(localType instanceof Class)) {
                throw new DynamoDBMappingException(
                        "Cannot convert " + type + " to a class");
            }
            Class> clazz = (Class>) localType;
            if (!registry.mappingsOf(clazz).isDocument()) {
                throw new DynamoDBMappingException(
                        "Cannot marshall type " + type
                        + " without a custom marshaler or @DynamoDBDocument "
                        + "annotation.");
            }
            return new ObjectToMapMarshaller(this);
        }
        @Override
        public Object unconvert(
                Method getter,
                Method setter,
                AttributeValue value) {
            ArgumentUnmarshaller unmarshaller = getUnmarshaller(getter, setter);
            return unmarshall(unmarshaller, setter, value);
        }
        @Override
        public  T unconvert(
                Class clazz,
                Map value) {
            T result = createObject(clazz);
            if (value == null || value.isEmpty()) {
                return result;
            }
            final DynamoDBMappingsRegistry.Mappings mappings = registry.mappingsOf(clazz);
            for (final DynamoDBMappingsRegistry.Mapping mapping : mappings.getMappings()) {
                String attributeName = mapping.getAttributeName();
                AttributeValue av = value.get(attributeName);
                if (av != null) {
                    ArgumentUnmarshaller unmarshaller = getUnmarshaller(mapping.getter(), mapping.setter());
                    Object unmarshalled = unmarshall(unmarshaller, mapping.setter(), av);
                    mapping.setValueOf(result, unmarshalled);
                }
            }
            return result;
        }
        private ArgumentUnmarshaller getUnmarshaller(
                Method getter,
                Method setter) {
            ArgumentUnmarshaller unmarshaller =
                    unmarshallerSet.getUnmarshaller(getter, setter);
            unmarshaller = augment(
                    setter.getGenericParameterTypes()[0], unmarshaller);
            return new NullableUnmarshaller(unmarshaller);
        }
        private ArgumentUnmarshaller getMemberUnmarshaller(Type type) {
            ArgumentUnmarshaller unmarshaller =
                    unmarshallerSet.getMemberUnmarshaller(type);
            unmarshaller = augment(type, unmarshaller);
            return new NullableUnmarshaller(unmarshaller);
        }
        private ArgumentUnmarshaller augment(
                Type type,
                ArgumentUnmarshaller unmarshaller) {
            // Inject our s3 client cache if it's an S3LinkUnmarshaller.
            if (unmarshaller instanceof S3LinkUnmarshaller) {
                return new S3LinkUnmarshaller(s3cc);
            }
            // Inject an appropriate member-type unmarshaller if it's a list,
            // object-set, or map unmarshaller.
            if (unmarshaller instanceof ObjectSetUnmarshaller) {
                return getObjectSetUnmarshaller(type);
            }
            if (unmarshaller instanceof ListUnmarshaller) {
                return getListUnmarshaller(type);
            }
            if (unmarshaller instanceof MapUnmarshaller) {
                return getMapUnmarshaller(type);
            }
            // Inject ourselves to recursively unmarshall things if it's an
            // ObjectUnmarshaller.
            if (unmarshaller instanceof ObjectUnmarshaller) {
                return getObjectUnmarshaller(type);
            }
            return unmarshaller;
        }
        private ArgumentUnmarshaller getObjectSetUnmarshaller(Type type) {
            if (!(type instanceof ParameterizedType)) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Set "
                        + "type " + type + ", which is not parameterized.");
            }
            ParameterizedType ptype = (ParameterizedType) type;
            Type[] args = ptype.getActualTypeArguments();
            if (args == null || args.length != 1) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Set "
                        + "type " + type + "; unexpected number of type "
                        + "arguments.");
            }
            ArgumentUnmarshaller memberUnmarshaller =
                    getMemberUnmarshaller(args[0]);
            return new ObjectSetUnmarshaller(memberUnmarshaller);
        }
        private ArgumentUnmarshaller getListUnmarshaller(Type type) {
            if (!(type instanceof ParameterizedType)) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the List "
                        + "type " + type + ", which is not parameterized.");
            }
            ParameterizedType ptype = (ParameterizedType) type;
            Type[] args = ptype.getActualTypeArguments();
            if (args == null || args.length != 1) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the List "
                        + "type " + type + "; unexpected number of type "
                        + "arguments.");
            }
            ArgumentUnmarshaller memberUnmarshaller =
                    getMemberUnmarshaller(args[0]);
            return new ListUnmarshaller(memberUnmarshaller);
        }
        private ArgumentUnmarshaller getMapUnmarshaller(Type type) {
            if (!(type instanceof ParameterizedType)) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Map "
                        + "type " + type + ", which is not parameterized.");
            }
            ParameterizedType ptype = (ParameterizedType) type;
            Type[] args = ptype.getActualTypeArguments();
            if (args == null || args.length != 2) {
                throw new DynamoDBMappingException(
                        "Cannot tell what type of objects belong in the Map "
                        + "type " + type + "; unexpected number of type "
                        + "arguments.");
            }
            if (args[0] != String.class) {
                throw new DynamoDBMappingException(
                        "Only Map is supported.");
            }
            ArgumentUnmarshaller memberUnmarshaller =
                    getMemberUnmarshaller(args[1]);
            return new MapUnmarshaller(memberUnmarshaller);
        }
        private ArgumentUnmarshaller getObjectUnmarshaller(Type type) {
            Type localType = type;
            if (localType instanceof ParameterizedType) {
                localType = ((ParameterizedType) type).getRawType();
            }
            if (!(localType instanceof Class)) {
                throw new DynamoDBMappingException(
                        "Cannot convert " + type + " to a class");
            }
            Class> clazz = (Class>) localType;
            if (!registry.mappingsOf(clazz).isDocument()) {
                throw new DynamoDBMappingException(
                        "Cannot unmarshall to type " + type
                        + " without a custom marshaler or @DynamoDBDocument "
                        + "annotation.");
            }
            return new ObjectUnmarshaller(this, clazz);
        }
        private static Object unmarshall(
                ArgumentUnmarshaller unmarshaller,
                Method setter,
                AttributeValue value) {
            unmarshaller.typeCheck(value, setter);
            try {
                return unmarshaller.unmarshall(value);
            } catch (IllegalArgumentException e) {
                throw new DynamoDBMappingException(
                        "Couldn't unmarshall value " + value + " for " + setter,
                        e);
            } catch (ParseException e) {
                throw new DynamoDBMappingException(
                        "Error attempting to parse date string " + value + " for "
                        + setter,
                        e);
            }
        }
        private static  T createObject(Class clazz) {
            try {
                return clazz.newInstance();
            } catch (InstantiationException e) {
                throw new DynamoDBMappingException(
                        "Failed to instantiate new instance of class", e);
            } catch (IllegalAccessException e) {
                throw new DynamoDBMappingException(
                        "Failed to instantiate new instance of class", e);
            }
        }
    }
    static interface MarshallerSet {
        ArgumentMarshaller getMarshaller(Method getter);
        ArgumentMarshaller getMemberMarshaller(Type memberType);
    }
    static interface UnmarshallerSet {
        ArgumentUnmarshaller getUnmarshaller(Method getter, Method setter);
        ArgumentUnmarshaller getMemberUnmarshaller(Type memberType);
    }
    static final class V2MarshallerSet extends AbstractMarshallerSet {
        public V2MarshallerSet() {
            super(marshallers(), setMarshallers());
        }
        private static List> marshallers() {
            List> list =
                    new ArrayList>();
            // Use the new V2 boolean marshallers.
            addStandardDateMarshallers(list);
            addV2BooleanMarshallers(list);
            addStandardNumberMarshallers(list);
            addStandardStringMarshallers(list);
            addStandardBinaryMarshallers(list);
            addStandardS3LinkMarshallers(list);
            // Add marshallers for the new list and map types.
            list.add(Pair.of(List.class, CollectionToListMarshaller.instance()));
            list.add(Pair.of(Map.class, MapToMapMarshaller.instance()));
            // Make sure I'm last since I'll catch anything.
            list.add(Pair.of(Object.class, ObjectToMapMarshaller.instance()));
            return list;
        }
        private static List> setMarshallers() {
            List> list =
                    new ArrayList>();
            // No more Set -> NS or Set