com.nimbusds.infinispan.persistence.dynamodb.query.SimpleMatchQueryExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of infinispan-cachestore-dynamodb Show documentation
Show all versions of infinispan-cachestore-dynamodb Show documentation
Infinispan module for persisting data to an AWS DynamoDB table
package com.nimbusds.infinispan.persistence.dynamodb.query;
import java.util.Map;
import java.util.function.Consumer;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.nimbusds.infinispan.persistence.common.InfinispanEntry;
import com.nimbusds.infinispan.persistence.common.query.MatchQuery;
import com.nimbusds.infinispan.persistence.common.query.Query;
import com.nimbusds.infinispan.persistence.common.query.SimpleMatchQuery;
import com.nimbusds.infinispan.persistence.common.query.UnsupportedQueryException;
import net.jcip.annotations.ThreadSafe;
/**
* Simple match DynamoDB query executor. Accepts queries of type
* {@link SimpleMatchQuery} and {@link MatchQuery} (converts it to
* {@link SimpleMatchQuery by taking the first match pair}, where both key name
* and value must be of type {@link String}.
*/
@ThreadSafe
public class SimpleMatchQueryExecutor implements DynamoDBQueryExecutor {
/**
* The initialisation context.
*/
private DynamoDBQueryExecutorInitContext initCtx;
@Override
public void init(final DynamoDBQueryExecutorInitContext initCtx) {
if (initCtx == null) {
throw new IllegalArgumentException("The init context must not be null");
}
this.initCtx = initCtx;
}
/**
* Returns the DynamoDB query spec for the specified simple match
* query.
*
* @param simpleMatchQuery The simple match query. Must not be
* {@code null}.
*
* @return The DynamoDB query spec.
*/
static QuerySpec toQuerySpec(final SimpleMatchQuery simpleMatchQuery) {
return new QuerySpec()
.withKeyConditionExpression("#k = :value")
.withNameMap(new NameMap()
.with("#k", simpleMatchQuery.getKey()))
.withValueMap(new ValueMap()
.withString(":value", simpleMatchQuery.getValue()));
}
/**
* Returns the DynamoDB scan spec for the specified simple match
* query.
*
* @param simpleMatchQuery The simple match query. Must not be
* {@code null}.
*
* @return The DynamoDB scan spec.
*/
static ScanSpec toScanSpec(final SimpleMatchQuery simpleMatchQuery) {
return new ScanSpec()
.withFilterExpression("#k = :value")
.withNameMap(new NameMap()
.with("#k", simpleMatchQuery.getKey()))
.withValueMap(new ValueMap()
.withString(":value", simpleMatchQuery.getValue()))
.withConsistentRead(false);
}
/**
* Converts the specified match query to a simple match query.
*
* @param matchQuery The match query.
*
* @return The simple match query.
*/
static SimpleMatchQuery toSimpleMatchQuery(final MatchQuery matchQuery) {
if (matchQuery instanceof SimpleMatchQuery) {
return (SimpleMatchQuery)matchQuery;
}
Map.Entry entry = matchQuery.getMatchMap().entrySet().iterator().next();
return new SimpleMatchQuery<>(entry.getKey(), entry.getValue());
}
@Override
@SuppressWarnings("unchecked")
public void executeQuery(final Query query, final Consumer> consumer) {
if (! (query instanceof MatchQuery)) {
throw new UnsupportedQueryException(query);
}
MatchQuery matchQuery = (MatchQuery)query;
if (matchQuery.getMatchMap().isEmpty()) {
throw new UnsupportedQueryException(query);
}
SimpleMatchQuery simpleMatchQuery = toSimpleMatchQuery(matchQuery);
Index index = initCtx.getDynamoDBIndex(simpleMatchQuery.getKey());
if (index != null) {
// Query via GSI
ItemCollection items = index.query(toQuerySpec(simpleMatchQuery));
items.forEach(item -> consumer.accept(initCtx.getDynamoDBItemTransformer().toInfinispanEntry(item)));
} else {
// Fall back to scan with filter expression
ItemCollection scanOutcome = initCtx.getDynamoDBTable().scan(toScanSpec(simpleMatchQuery));
scanOutcome.forEach(item -> consumer.accept(initCtx.getDynamoDBItemTransformer().toInfinispanEntry(item)));
}
}
}