
com.amazonaws.services.dynamodbv2.datamodeling.StandardConverterRules 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 static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.B;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.BOOL;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.BS;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.L;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.M;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.N;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.NULL;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.NS;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.S;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType.SS;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Scalar.BOOLEAN;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Scalar.BYTE_BUFFER;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Scalar.DEFAULT;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Scalar.STRING;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Vector.LIST;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Vector.MAP;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Vector.SET;
import com.amazonaws.annotation.SdkInternalApi;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.DynamoDBAttributeType;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.Properties;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.Reflect;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverterFactory.OverrideFactory;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardAttributeTypes.AttributeType;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties.Bean;
import com.amazonaws.services.dynamodbv2.datamodeling.StandardParameterTypes.ParamType;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Pre-defined strategies for mapping between Java types and DynamoDB types.
*/
@SdkInternalApi
final class StandardConverterRules {
private static final Log LOG = LogFactory.getLog(StandardConverterRules.class);
/**
* Creates a new set of conversion rules based on the configuration.
*/
static final RuleFactory of(final DynamoDBMapperConfig config, final DynamoDBMapperModelFactory.Factory factory, final S3ClientCache s3cc) {
final Rules rules = new Rules(StandardTypeConverters.factory());
rules.with(String.class, S3Link.class, new S3Link.Factory(s3cc));
if (config.getConversionSchema() == ConversionSchemas.V1) {
rules.with(rules.new NativeBool(true));
rules.with(rules.new SimpleScalar(S));
rules.with(rules.new SimpleScalar(N));
rules.with(rules.new SimpleScalar(B));
rules.with(rules.new SimpleScalarSet(SS));
rules.with(rules.new SimpleScalarSet(NS));
rules.with(rules.new SimpleScalarSet(BS));
rules.with(rules.new ObjectToStringSet());
} else if (config.getConversionSchema() == ConversionSchemas.V2) {
rules.with(rules.new NativeBool(false));
rules.with(rules.new SimpleScalar(S));
rules.with(rules.new SimpleScalar(N));
rules.with(rules.new SimpleScalar(B));
rules.with(rules.new NativeBoolSet());
rules.with(rules.new SimpleScalarSet(SS));
rules.with(rules.new SimpleScalarSet(NS));
rules.with(rules.new SimpleScalarSet(BS));
rules.with(rules.new ObjectSetOrList());
rules.with(rules.new ObjectStringKeyMap());
rules.with(rules.new ObjectDocumentMap(config, factory));
} else {
rules.with(rules.new NativeBool(true));
rules.with(rules.new SimpleScalar(S));
rules.with(rules.new SimpleScalar(N));
rules.with(rules.new SimpleScalar(B));
rules.with(rules.new SimpleScalarSet(SS));
rules.with(rules.new SimpleScalarSet(NS));
rules.with(rules.new SimpleScalarSet(BS));
rules.with(rules.new ObjectToStringSet());
rules.with(rules.new ObjectSetOrList());
rules.with(rules.new ObjectStringKeyMap());
rules.with(rules.new ObjectDocumentMap(config, factory));
}
return rules;
}
/**
* Groups the conversion rules to be evaluated.
*/
private static final class Rules extends OverrideFactory implements RuleFactory {
private final Set> rules = new LinkedHashSet>();
/**
* Constructs a new conversion evaluator with the specified scalar
* type-converter factory.
*/
private Rules(final DynamoDBTypeConverterFactory converters) {
super(converters);
}
/**
* Adds a conversion rule.
*/
private Rules with(final Rule> rule) {
this.rules.add((Rule)rule);
return this;
}
/**
* Returns the first conversion rule matching the specified type;
* scalar attribute type may be specified to override the standard
* source conversion, otherwise, it should be left as null.
*/
private Rule getRule(final ParamType type, final Properties,V> props) {
if (props.typeConverter() != null) {
return new CustomTypeConverted(props);
}
for (final Rule rule : rules) {
if (rule.isAssignableFrom(type, props)) {
return rule;
}
}
return new NotSupported();
}
/**
* {@inheritDoc}
*/
@Override
public Rule getRule(final Bean,V> bean) {
return getRule(bean.type(), bean);
}
/**
* Custom type-converted conversion.
*/
private final class CustomTypeConverted implements Rule {
private final DynamoDBTypeConverter target;
private final ParamType sourceType;
private final Rule rule;
private CustomTypeConverted(final Properties,V> props) {
this.target = props.typeConverter();
this.sourceType = StandardParameterTypes.of(target);
this.rule = getRule(sourceType, new Properties.Buildable(props).withTypeConverter(null));
}
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
return true;
}
@Override
public DynamoDBTypeConverter newConverter(final ParamType type) {
final DynamoDBTypeConverter source = rule.newConverter(sourceType);
return join(source, target);
}
@Override
public DynamoDBAttributeType getAttributeType() {
return rule.getAttributeType();
}
}
/**
* Native boolean conversion.
*/
private final class NativeBool implements Rule {
private final boolean onlyIfOverride;
private NativeBool(final boolean onlyIfOverride) {
this.onlyIfOverride = onlyIfOverride;
}
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return !onlyIfOverride && SET.is(type.type()) == false && BOOLEAN.is(type.type());
}
return props.attributeType() == getAttributeType();
}
@Override
public DynamoDBTypeConverter newConverter(final ParamType type) {
return BOOL.join(BOOLEAN.join(type.type()));
}
@Override
public DynamoDBAttributeType getAttributeType() {
return BOOL.attributeType();
}
}
/**
* Scalar conversions.
*/
private final class SimpleScalar implements Rule {
private final AttributeType attribute;
private final Class sourceType;
private SimpleScalar(final AttributeType attribute) {
this.sourceType = (attribute == B ? BYTE_BUFFER : STRING).type();
this.attribute = attribute;
}
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return SET.is(type.type()) == false && type.scalar().is(attribute.scalarAttributeType());
}
return props.attributeType() == getAttributeType();
}
@Override
public DynamoDBTypeConverter newConverter(final ParamType type) {
final DynamoDBTypeConverter,V> target = getConverter(sourceType, type.type());
return attribute.join(target);
}
@Override
public DynamoDBAttributeType getAttributeType() {
return attribute.attributeType();
}
}
/**
* Scalar set conversions.
*/
private final class SimpleScalarSet implements Rule> {
private final AttributeType attribute;
private final Class sourceType;
private SimpleScalarSet(final AttributeType attribute) {
this.sourceType = (attribute == BS ? BYTE_BUFFER : STRING).type();
this.attribute = attribute;
}
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return SET.is(type.type()) && type.param(0).scalar().is(attribute.scalarAttributeType());
}
return props.attributeType() == getAttributeType();
}
@Override
public DynamoDBTypeConverter> newConverter(final ParamType> type) {
final DynamoDBTypeConverter,V> target = getConverter(sourceType, type.param(0).type());
return attribute.join(SET.join(target));
}
@Override
public DynamoDBAttributeType getAttributeType() {
return attribute.attributeType();
}
}
/**
* V1 Object set conversions.
*/
private final class ObjectToStringSet implements Rule> {
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return SET.is(type.type());
}
return false;
}
@Override
public DynamoDBTypeConverter> newConverter(final ParamType> type) {
LOG.warn("Marshaling a set of non-String objects to a DynamoDB StringSet. " +
"You won't be able to read these objects back out of DynamoDB unless " +
"you REALLY know what you're doing: it's probably a bug. If you DO know " +
"what you're doing feel to ignore this warning, but consider using a " +
"custom @DynamoDBTypeConverted/DynamoDBTypeConverter for this instead.");
return SS.join(SET.join(STRING.join(DEFAULT.type())));
}
@Override
public DynamoDBAttributeType getAttributeType() {
return SS.attributeType();
}
}
/**
* Native bool {@link Set} conversions.
*/
private final class NativeBoolSet implements Rule> {
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return SET.is(type.type()) && BOOLEAN.is(type.param(0).type());
}
return false;
}
@Override
public DynamoDBTypeConverter> newConverter(final ParamType> type) {
return join(new DynamoDBTypeConverter>() {
public final AttributeValue convert(final List o) {
return L.convert(o);
}
public final List unconvert(final AttributeValue o) {
if (o.getL() == null && o.getNS() != null) {
return LIST.convert(o.getNS(), BOOL.join(BOOLEAN.join(String.class)));
}
return (List)L.unconvert(o);
}
}, SET.join(NULL.join(BOOL.join(BOOLEAN.join(type.param(0).type())))));
}
@Override
public DynamoDBAttributeType getAttributeType() {
return L.attributeType();
}
}
/**
* Any {@link List} conversions.
*/
private final class ObjectSetOrList implements Rule> {
@Override
public boolean isAssignableFrom(final ParamType> type, final Properties,?> props) {
if (props.attributeType() == null) {
return (SET.is(type.type()) || LIST.is(type.type())) && type.param(0) != null;
}
return false;
}
@Override
public DynamoDBTypeConverter> newConverter(final ParamType> type) {
final Rule rule = getRule(type.param(0), Properties.Immutable.empty());
final DynamoDBTypeConverter target = NULL.join(rule.newConverter(type.param(0)));
return L.join(SET.is(type.type()) ? SET.join(target) : LIST.join(target));
}
@Override
public DynamoDBAttributeType getAttributeType() {
return L.attributeType();
}
}
/**
* Any {@link Map} conversions.
*/
private final class ObjectStringKeyMap implements Rule
© 2015 - 2025 Weber Informatics LLC | Privacy Policy