package org.socialsignin.spring.data.dynamodb.core;
import java.util.List;
import java.util.Map;
import org.socialsignin.spring.data.dynamodb.mapping.event.AfterDeleteEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.AfterLoadEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.AfterQueryEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.AfterSaveEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.AfterScanEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.BeforeDeleteEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.BeforeSaveEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.DynamoDBMappingEvent;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.KeyPair;
import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList;
import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedScanList;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.QueryResult;
import com.amazonaws.services.dynamodbv2.model.Select;
public class DynamoDBTemplate implements DynamoDBOperations,ApplicationContextAware {
protected DynamoDBMapper dynamoDBMapper;
private AmazonDynamoDB amazonDynamoDB;
private DynamoDBMapperConfig dynamoDBMapperConfig;
private ApplicationEventPublisher eventPublisher;
public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB,DynamoDBMapperConfig dynamoDBMapperConfig)
{
this.amazonDynamoDB = amazonDynamoDB;
setDynamoDBMapperConfig(dynamoDBMapperConfig);
}
public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB)
{
this.amazonDynamoDB = amazonDynamoDB;
setDynamoDBMapperConfig(null);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.eventPublisher = applicationContext;
}
public void setDynamoDBMapperConfig(DynamoDBMapperConfig dynamoDBMapperConfig)
{
this.dynamoDBMapperConfig = dynamoDBMapperConfig;
dynamoDBMapper = dynamoDBMapperConfig == null ? new DynamoDBMapper(amazonDynamoDB) : new DynamoDBMapper(
amazonDynamoDB, dynamoDBMapperConfig);
if (dynamoDBMapperConfig == null)
{
this.dynamoDBMapperConfig = DynamoDBMapperConfig.DEFAULT;
}
}
@Override
public <T> int count(Class<T> domainClass,
DynamoDBQueryExpression<T> queryExpression) {
return dynamoDBMapper.count(domainClass, queryExpression);
}
@Override
public <T> PaginatedQueryList<T> query(Class<T> domainClass,
DynamoDBQueryExpression<T> queryExpression) {
PaginatedQueryList<T> results = dynamoDBMapper.query(domainClass, queryExpression);
maybeEmitEvent(new AfterQueryEvent<T>(results));
return results;
}
@Override
public <T> int count(Class<T> domainClass,
DynamoDBScanExpression scanExpression) {
return dynamoDBMapper.count(domainClass, scanExpression);
}
@Override
public <T> T load(Class<T> domainClass, Object hashKey, Object rangeKey) {
T entity = dynamoDBMapper.load(domainClass, hashKey,rangeKey);
if (entity != null)
{
maybeEmitEvent(new AfterLoadEvent<Object>(entity));
}
return entity;
}
@Override
public <T> T load(Class<T> domainClass, Object hashKey) {
T entity = dynamoDBMapper.load(domainClass, hashKey);
if (entity != null)
{
maybeEmitEvent(new AfterLoadEvent<Object>(entity));
}
return entity;
}
@Override
public <T> PaginatedScanList<T> scan(Class<T> domainClass,
DynamoDBScanExpression scanExpression) {
PaginatedScanList<T> results = dynamoDBMapper.scan(domainClass, scanExpression);
maybeEmitEvent(new AfterScanEvent<T>(results));
return results;
}
@Override
public Map<String, List<Object>> batchLoad(Map<Class<?>, List<KeyPair>> itemsToGet) {
Map<String,List<Object>> results = dynamoDBMapper.batchLoad(itemsToGet);
for (List<Object> resultList : results.values())
{
for (Object entity : resultList)
{
maybeEmitEvent(new AfterLoadEvent<Object>(entity));
}
}
return results;
}
@Override
public void save(Object entity) {
maybeEmitEvent(new BeforeSaveEvent<Object>(entity));
dynamoDBMapper.save(entity);
maybeEmitEvent(new AfterSaveEvent<Object>(entity));
}
@Override
public void batchSave(List<?> entities) {
for (Object entity : entities)
{
maybeEmitEvent(new BeforeSaveEvent<Object>(entity));
}
dynamoDBMapper.batchSave(entities);
for (Object entity : entities)
{
maybeEmitEvent(new AfterSaveEvent<Object>(entity));
}
}
@Override
public void delete(Object entity) {
maybeEmitEvent(new BeforeDeleteEvent<Object>(entity));
dynamoDBMapper.delete(entity);
maybeEmitEvent(new AfterDeleteEvent<Object>(entity));
}
@Override
public void batchDelete(List<?> entities) {
for (Object entity : entities)
{
maybeEmitEvent(new BeforeDeleteEvent<Object>(entity));
}
dynamoDBMapper.batchDelete(entities);
for (Object entity : entities)
{
maybeEmitEvent(new AfterDeleteEvent<Object>(entity));
}
}
@Override
public <T> PaginatedQueryList<T> query(Class<T> clazz,
QueryRequest queryRequest) {
QueryResult queryResult = amazonDynamoDB.query(queryRequest);
return new PaginatedQueryList<T>(dynamoDBMapper, clazz, amazonDynamoDB, queryRequest, queryResult,
dynamoDBMapperConfig.getPaginationLoadingStrategy(), dynamoDBMapperConfig);
}
@Override
public <T> int count(Class<T> clazz, QueryRequest mutableQueryRequest) {
mutableQueryRequest.setSelect(Select.COUNT);
// Count queries can also be truncated for large datasets
int count = 0;
QueryResult queryResult = null;
do {
queryResult = amazonDynamoDB.query(mutableQueryRequest);
count += queryResult.getCount();
mutableQueryRequest.setExclusiveStartKey(queryResult.getLastEvaluatedKey());
} while (queryResult.getLastEvaluatedKey() != null);
return count;
}
@Override
public String getOverriddenTableName(String tableName) {
if (dynamoDBMapperConfig.getTableNameOverride() != null) {
if (dynamoDBMapperConfig.getTableNameOverride().getTableName() != null) {
tableName = dynamoDBMapperConfig.getTableNameOverride().getTableName();
} else {
tableName = dynamoDBMapperConfig.getTableNameOverride().getTableNamePrefix() + tableName;
}
}
return tableName;
}
protected <T> void maybeEmitEvent(DynamoDBMappingEvent<T> event) {
if (null != eventPublisher) {
eventPublisher.publishEvent(event);
}
}
}