Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2015-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.model.KeyType.HASH;
import static com.amazonaws.services.dynamodbv2.model.KeyType.RANGE;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.retry.RetryUtils;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.BatchLoadRetryStrategy;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.BatchWriteRetryStrategy;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.ConsistentReads;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.SaveBehavior;
import com.amazonaws.services.dynamodbv2.model.AttributeAction;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;
import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest;
import com.amazonaws.services.dynamodbv2.model.BatchGetItemResult;
import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest;
import com.amazonaws.services.dynamodbv2.model.BatchWriteItemResult;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.ConditionalOperator;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest;
import com.amazonaws.services.dynamodbv2.model.DeleteRequest;
import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest;
import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;
import com.amazonaws.services.dynamodbv2.model.PutRequest;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.QueryResult;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;
import com.amazonaws.services.dynamodbv2.model.ScanRequest;
import com.amazonaws.services.dynamodbv2.model.ScanResult;
import com.amazonaws.services.dynamodbv2.model.Select;
import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest;
import com.amazonaws.services.dynamodbv2.model.UpdateItemResult;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;
import com.amazonaws.services.s3.model.Region;
import com.amazonaws.util.VersionInfoUtils;
/**
* Object mapper for domain-object interaction with DynamoDB.
*
* To use, define a domain class that represents an item in a DynamoDB table and
* annotate it with the annotations found in the
* com.amazonaws.services.dynamodbv2.datamodeling package. In order to allow the
* mapper to correctly persist the data, each modeled property in the domain
* class should be accessible via getter and setter methods, and each property
* annotation should be either applied to the getter method or the class field.
* A minimal example using getter annotations:
*
*
* @DynamoDBTable(tableName = "TestTable")
* public class TestClass {
*
* private Long key;
* private double rangeKey;
* private Long version;
*
* private Set<Integer> integerSetAttribute;
*
* @DynamoDBHashKey
* public Long getKey() {
* return key;
* }
*
* public void setKey(Long key) {
* this.key = key;
* }
*
* @DynamoDBRangeKey
* public double getRangeKey() {
* return rangeKey;
* }
*
* public void setRangeKey(double rangeKey) {
* this.rangeKey = rangeKey;
* }
*
* @DynamoDBAttribute(attributeName = "integerSetAttribute")
* public Set<Integer> getIntegerAttribute() {
* return integerSetAttribute;
* }
*
* public void setIntegerAttribute(Set<Integer> integerAttribute) {
* this.integerSetAttribute = integerAttribute;
* }
*
* @DynamoDBVersionAttribute
* public Long getVersion() {
* return version;
* }
*
* public void setVersion(Long version) {
* this.version = version;
* }
* }
*
*
* Save instances of annotated classes to DynamoDB, retrieve them, and delete
* them using the {@link DynamoDBMapper} class, as in the following example.
*
*
* If you don't have your DynamoDB table set up yet, you can use
* {@link DynamoDBMapper#generateCreateTableRequest(Class)} to construct the
* {@link CreateTableRequest} for the table represented by your annotated class.
*
*
* AmazonDynamoDB dynamoDBClient = new AmazonDynamoDBClient();
* DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
* CreateTableRequest req = mapper.generateCreateTableRequest(TestClass.class);
* // Table provision throughput is still required since it cannot be specified in your POJO
* req.setProvisionedThroughput(new ProvisionedThroughput(5L, 5L));
* // Fire off the CreateTableRequest using the low-level client
* dynamoDBClient.createTable(req);
*
*
* When using the save, load, and delete methods, {@link DynamoDBMapper} will
* throw {@link DynamoDBMappingException}s to indicate that domain classes are
* incorrectly annotated or otherwise incompatible with this class. Service
* exceptions will always be propagated as {@link AmazonClientException}, and
* DynamoDB-specific subclasses such as {@link ConditionalCheckFailedException}
* will be used when possible.
*
* This class is thread-safe and can be shared between threads. It's also very
* lightweight, so it doesn't need to be.
*
* @see DynamoDBTable
* @see DynamoDBHashKey
* @see DynamoDBRangeKey
* @see DynamoDBAutoGeneratedKey
* @see DynamoDBAttribute
* @see DynamoDBVersionAttribute
* @see DynamoDBIgnore
* @see DynamoDBMarshalling
* @see DynamoDBMapperConfig
*/
public class DynamoDBMapper extends AbstractDynamoDBMapper {
private final S3ClientCache s3cc;
private final AmazonDynamoDB db;
private final DynamoDBMapperConfig config;
private final DynamoDBMapperModelFactory.Factory models;
private final AttributeTransformer transformer;
/**
* The max back off time for batch get. The configuration for batch write
* has been moved to DynamoDBMapperConfig
*/
static final long MAX_BACKOFF_IN_MILLISECONDS = 1000 * 3;
/** The max number of items allowed in a BatchWrite request */
static final int MAX_ITEMS_PER_BATCH = 25;
/**
* This retry count is applicable only when every batch get item request
* results in no data retrieved from server and the un processed keys is
* same as request items
*/
static final int BATCH_GET_MAX_RETRY_COUNT_ALL_KEYS = 5;
/**
* User agent for requests made using the {@link DynamoDBMapper}.
*/
private static final String USER_AGENT =
DynamoDBMapper.class.getName() + "/" + VersionInfoUtils.getVersion();
private static final String USER_AGENT_BATCH_OPERATION =
DynamoDBMapper.class.getName() + "_batch_operation/" + VersionInfoUtils.getVersion();
private static final String NO_RANGE_KEY = new String();
private static final Log log = LogFactory.getLog(DynamoDBMapper.class);
/**
* Fail fast when trying to create a subclass of the DynamoDBMapper that
* attempts to override one of the old {@code transformAttributes} methods.
*/
private static void failFastOnIncompatibleSubclass(Class> clazz) {
while (clazz != DynamoDBMapper.class) {
Class>[] classOverride = new Class>[] {
Class.class,
Map.class
};
Class>[] nameOverride = new Class>[] {
String.class,
String.class,
Map.class
};
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals("transformAttributes")) {
Class>[] params = method.getParameterTypes();
if (Arrays.equals(params, classOverride)
|| Arrays.equals(params, nameOverride)) {
throw new IllegalStateException(
"The deprecated transformAttributes method is "
+ "no longer supported as of 1.9.0. Use an "
+ "AttributeTransformer to inject custom "
+ "attribute transformation logic.");
}
}
}
clazz = clazz.getSuperclass();
}
}
/**
* Constructs a new mapper with the service object given, using the default
* configuration.
*
* @param dynamoDB
* The service object to use for all service calls.
* @see DynamoDBMapperConfig#DEFAULT
*/
public DynamoDBMapper(final AmazonDynamoDB dynamoDB) {
this(dynamoDB, DynamoDBMapperConfig.DEFAULT, null, null);
}
/**
* Constructs a new mapper with the service object and configuration given.
*
* @param dynamoDB
* The service object to use for all service calls.
* @param config
* The default configuration to use for all service calls. It can
* be overridden on a per-operation basis.
*/
public DynamoDBMapper(
final AmazonDynamoDB dynamoDB,
final DynamoDBMapperConfig config) {
this(dynamoDB, config, null, null);
}
/**
* Constructs a new mapper with the service object and S3 client cache
* given, using the default configuration.
*
* @param ddb
* The service object to use for all service calls.
* @param s3CredentialProvider
* The credentials provider for accessing S3.
* Relevant only if {@link S3Link} is involved.
* @see DynamoDBMapperConfig#DEFAULT
*/
public DynamoDBMapper(
final AmazonDynamoDB ddb,
final AWSCredentialsProvider s3CredentialProvider) {
this(ddb, DynamoDBMapperConfig.DEFAULT, s3CredentialProvider);
}
/**
* Constructs a new mapper with the given service object, configuration,
* and transform hook.
*
* @param dynamoDB
* the service object to use for all service calls
* @param config
* the default configuration to use for all service calls. It
* can be overridden on a per-operation basis
* @param transformer
* The custom attribute transformer to invoke when serializing or
* deserializing an object.
*/
public DynamoDBMapper(
final AmazonDynamoDB dynamoDB,
final DynamoDBMapperConfig config,
final AttributeTransformer transformer) {
this(dynamoDB, config, transformer, null);
}
/**
* Constructs a new mapper with the service object, configuration, and S3
* client cache given.
*
* @param dynamoDB
* The service object to use for all service calls.
* @param config
* The default configuration to use for all service calls. It can
* be overridden on a per-operation basis.
* @param s3CredentialProvider
* The credentials provider for accessing S3.
* Relevant only if {@link S3Link} is involved.
*/
public DynamoDBMapper(
final AmazonDynamoDB dynamoDB,
final DynamoDBMapperConfig config,
final AWSCredentialsProvider s3CredentialProvider) {
this(dynamoDB, config, null, validate(s3CredentialProvider));
}
/**
* Throws an exception if the given credentials provider is {@code null}.
*/
private static AWSCredentialsProvider validate(
final AWSCredentialsProvider provider) {
if (provider == null) {
throw new IllegalArgumentException(
"s3 credentials provider must not be null");
}
return provider;
}
/**
* Constructor with all parameters.
*
* @param dynamoDB
* The service object to use for all service calls.
* @param config
* The default configuration to use for all service calls. It can
* be overridden on a per-operation basis.
* @param transformer
* The custom attribute transformer to invoke when serializing or
* deserializing an object.
* @param s3CredentialProvider
* The credentials provider for accessing S3.
* Relevant only if {@link S3Link} is involved.
*/
public DynamoDBMapper(
final AmazonDynamoDB dynamoDB,
final DynamoDBMapperConfig config,
final AttributeTransformer transformer,
final AWSCredentialsProvider s3CredentialsProvider) {
failFastOnIncompatibleSubclass(getClass());
this.db = dynamoDB;
this.config = config;
this.transformer = transformer;
if (s3CredentialsProvider == null) {
this.s3cc = null;
} else {
this.s3cc = new S3ClientCache(s3CredentialsProvider);
}
this.models = StandardModelFactories.of(new ConversionSchema.Dependencies()
.with(S3ClientCache.class, this.s3cc));
}
private DynamoDBMapperTableModel getTableModel(Class clazz, DynamoDBMapperConfig config) {
return this.models.getModelFactory(config).getTableModel(clazz);
}
@Override
public T load(Class clazz, Object hashKey, DynamoDBMapperConfig config) {
return load(clazz, hashKey, null, config);
}
@Override
public T load(Class clazz, Object hashKey) {
return load(clazz, hashKey, null, config);
}
@Override
public T load(Class clazz, Object hashKey, Object rangeKey) {
return load(clazz, hashKey, rangeKey, config);
}
@Override
public T load(T keyObject) {
return load(keyObject, this.config);
}
@Override
public T load(T keyObject, DynamoDBMapperConfig config) {
@SuppressWarnings("unchecked")
Class clazz = (Class) keyObject.getClass();
config = mergeConfig(config);
final DynamoDBMapperTableModel model = getTableModel(clazz, config);
String tableName = getTableName(clazz, keyObject, config);
GetItemRequest rq = new GetItemRequest()
.withRequestMetricCollector(config.getRequestMetricCollector());
Map key = model.mapKey(keyObject);
rq.setKey(key);
rq.setTableName(tableName);
rq.setConsistentRead(config.getConsistentReads() == ConsistentReads.CONSISTENT);
GetItemResult item = db.getItem(applyUserAgent(rq));
Map itemAttributes = item.getItem();
if ( itemAttributes == null ) {
return null;
}
T object = privateMarshallIntoObject(
toParameters(itemAttributes, clazz, tableName, config));
return object;
}
@Override
public T load(Class clazz, Object hashKey, Object rangeKey, DynamoDBMapperConfig config) {
config = mergeConfig(config);
final DynamoDBMapperTableModel model = getTableModel(clazz, config);
T keyObject = model.newKey(hashKey, rangeKey);
return load(keyObject, config);
}
/**
* Returns a map of attribute name to EQ condition for the key prototype
* object given. This method considers attributes annotated with either
* {@link DynamoDBHashKey} or {@link DynamoDBIndexHashKey}.
*
* @param obj
* The prototype object that includes the hash key value.
* @return A map of hash key attribute name to EQ condition for the key
* prototype object, or an empty map if obj is null.
*/
private Map getHashKeyEqualsConditions(
DynamoDBMapperTableModel model,
T obj) {
Map conditions = new HashMap();
if (obj == null) {
return conditions;
}
for (final DynamoDBMapperFieldModel field : model.fields()) {
if (field.anyKey(HASH)) {
final Object getterReturnResult = field.get(obj);
if (getterReturnResult != null) {
conditions.put(field.name(), field.eq(getterReturnResult));
}
}
}
return conditions;
}
/**
* Returns the table name for the class given.
*/
protected final String getTableName(final Class> clazz,
final DynamoDBMapperConfig config) {
return internalGetTableName(clazz, null, config);
}
/**
* Returns the table name for the class or object given.
*/
protected final String getTableName(final Class> clazz,
final Object object,
final DynamoDBMapperConfig config) {
return internalGetTableName(clazz, object, config);
}
static String internalGetTableName(final Class> clazz,
final Object object,
final DynamoDBMapperConfig config) {
// Resolve by object, if possible and desired
DynamoDBMapperConfig.ObjectTableNameResolver objectResolver = config.getObjectTableNameResolver();
if (object != null && objectResolver != null) {
return objectResolver.getTableName(object, config);
}
// Resolve by class
return config.getTableNameResolver(true).getTableName(clazz, config);
}
@Override
public T marshallIntoObject(Class clazz, Map itemAttributes) {
String tableName = getTableName(clazz, config);
return privateMarshallIntoObject(
toParameters(itemAttributes, clazz, tableName, config));
}
/**
* The one true implementation of marshallIntoObject.
*/
private T privateMarshallIntoObject(
AttributeTransformer.Parameters parameters) {
Class clazz = parameters.getModelClass();
Map values = untransformAttributes(parameters);
final DynamoDBMapperTableModel model = getTableModel(clazz, parameters.getMapperConfig());
return model.unconvert(values);
}
@Override
public List marshallIntoObjects(Class clazz, List