use of com.amazonaws.mobileconnectors.dynamodbv2.document.internal.Key in project aws-sdk-android by aws-amplify.
the class Table method deleteItem.
private Document deleteItem(Key key, DeleteItemOperationConfig config) {
final DeleteItemRequest request = new DeleteItemRequest(tableName, key);
if (config != null) {
request.setReturnValues(config.getReturnValue());
}
Table.appendDynamoDBDocumentUserAgentString(request);
final DeleteItemResult result = this.client.deleteItem(request);
final Document returnDocument = this.fromAttributeMap(result.getAttributes());
returnDocument.commit();
return returnDocument;
}
use of com.amazonaws.mobileconnectors.dynamodbv2.document.internal.Key in project aws-sdk-android by aws-amplify.
the class Table method makeKey.
private Key makeKey(Primitive hashKey, Primitive rangeKey) {
final Key key = new Key();
if (this.hashKeys.size() != 1) {
throw new IllegalStateException("no hashkeys in table");
}
final String hashKeyName = this.hashKeys.get(0);
final KeyDescription keyDescription = this.keys.get(hashKeyName);
if (keyDescription.getType() != hashKey.getType()) {
throw new IllegalStateException("hash key type does not match the one in table definition");
}
final AttributeValue av = hashKey.convertToAttributeValue();
key.put(hashKeyName, av);
if (rangeKey == null && this.rangeKeys.size() > 0) {
throw new IllegalStateException("range key not specificed for a table with range keys");
} else if (rangeKey != null) {
final String rangeKeyName = this.rangeKeys.get(0);
final KeyDescription kd = this.keys.get(rangeKeyName);
if (kd.getType() != rangeKey.getType()) {
throw new IllegalStateException("range key type does not match that of table definition");
}
final AttributeValue rangeKeyAttributeValue = rangeKey.convertToAttributeValue();
key.put(rangeKeyName, rangeKeyAttributeValue);
}
return key;
}
use of com.amazonaws.mobileconnectors.dynamodbv2.document.internal.Key in project aws-sdk-android by aws-amplify.
the class JsonUtils method toEntry.
private static DynamoDBEntry toEntry(JsonElement data) {
if (data == null || data.isJsonNull()) {
return DynamoDBNull.NULL;
}
if (data.isJsonObject()) {
final Document doc = new Document();
for (final Entry<String, JsonElement> entry : data.getAsJsonObject().entrySet()) {
final String key = entry.getKey();
final JsonElement element = entry.getValue();
doc.put(key, toEntry(element));
}
return doc;
}
if (data.isJsonArray()) {
final DynamoDBList list = new DynamoDBList();
final JsonArray array = data.getAsJsonArray();
for (final Iterator<JsonElement> iterator = array.iterator(); iterator.hasNext(); ) {
final JsonElement type = iterator.next();
list.add(toEntry(type));
}
return list;
}
final JsonPrimitive primitive = data.getAsJsonPrimitive();
if (primitive.isBoolean()) {
return new DynamoDBBool(primitive.getAsBoolean());
}
if (primitive.isString()) {
return new Primitive(primitive.getAsString());
}
if (primitive.isNumber()) {
return new Primitive(primitive.getAsNumber());
}
throw new JsonParseException("unable to parse json for key " + data.toString());
}
use of com.amazonaws.mobileconnectors.dynamodbv2.document.internal.Key in project aws-sdk-android by aws-amplify.
the class DynamoDBMapper method processKeyConditions.
/**
* Utility method for checking the validity of both hash and range key
* conditions. It also tries to infer the correct index name from the POJO
* annotation, if such information is not directly specified by the user.
*
* @param clazz The domain class of the queried items.
* @param queryRequest The QueryRequest object to be sent to service.
* @param hashKeyConditions All the hash key EQ conditions extracted from
* the POJO object. The mapper will choose one of them that could
* be applied together with the user-specified (if any) index
* name and range key conditions. Or it throws error if more than
* one conditions are applicable for the query.
* @param rangeKeyConditions The range conditions specified by the user. We
* currently only allow at most one range key condition.
*/
@SuppressWarnings("checkstyle:methodlength")
private void processKeyConditions(Class<?> clazz, QueryRequest queryRequest, Map<String, Condition> hashKeyConditions, Map<String, Condition> rangeKeyConditions) {
// There should be least one hash key condition.
if (hashKeyConditions == null || hashKeyConditions.isEmpty()) {
throw new IllegalArgumentException("Illegal query expression: No hash key condition is found in the query");
}
// We don't allow multiple range key conditions.
if (rangeKeyConditions != null && rangeKeyConditions.size() > 1) {
throw new IllegalArgumentException("Illegal query expression: Conditions on multiple range keys (" + rangeKeyConditions.keySet().toString() + ") are found in the query. DynamoDB service only accepts up to ONE range key condition.");
}
final boolean hasRangeKeyCondition = (rangeKeyConditions != null) && (!rangeKeyConditions.isEmpty());
final String userProvidedIndexName = queryRequest.getIndexName();
final String primaryHashKeyName = reflector.getPrimaryHashKeyName(clazz);
final TableIndexesInfo parsedIndexesInfo = schemaParser.parseTableIndexes(clazz, reflector);
// First collect the names of all the global/local secondary indexes
// that could be applied to this query.
// If the user explicitly specified an index name, we also need to
// 1) check the index is applicable for both hash and range key
// conditions
// 2) choose one hash key condition if there are more than one of them
boolean hasPrimaryHashKeyCondition = false;
final Map<String, Set<String>> annotatedGSIsOnHashKeys = new HashMap<String, Set<String>>();
String hashKeyNameForThisQuery = null;
boolean hasPrimaryRangeKeyCondition = false;
final Set<String> annotatedLSIsOnRangeKey = new HashSet<String>();
final Set<String> annotatedGSIsOnRangeKey = new HashSet<String>();
// Range key condition
String rangeKeyNameForThisQuery = null;
if (hasRangeKeyCondition) {
for (final String rangeKeyName : rangeKeyConditions.keySet()) {
rangeKeyNameForThisQuery = rangeKeyName;
if (reflector.hasPrimaryRangeKey(clazz) && rangeKeyName.equals(reflector.getPrimaryRangeKeyName(clazz))) {
hasPrimaryRangeKeyCondition = true;
}
final Collection<String> annotatedLSI = parsedIndexesInfo.getLsiNamesByIndexRangeKey(rangeKeyName);
if (annotatedLSI != null) {
annotatedLSIsOnRangeKey.addAll(annotatedLSI);
}
final Collection<String> annotatedGSI = parsedIndexesInfo.getGsiNamesByIndexRangeKey(rangeKeyName);
if (annotatedGSI != null) {
annotatedGSIsOnRangeKey.addAll(annotatedGSI);
}
}
if (!hasPrimaryRangeKeyCondition && annotatedLSIsOnRangeKey.isEmpty() && annotatedGSIsOnRangeKey.isEmpty()) {
throw new DynamoDBMappingException("The query contains a condition on a range key (" + rangeKeyNameForThisQuery + ") " + "that is not annotated with either @DynamoDBRangeKey or @DynamoDBIndexRangeKey.");
}
}
final boolean userProvidedLSIWithRangeKeyCondition = (userProvidedIndexName != null) && (annotatedLSIsOnRangeKey.contains(userProvidedIndexName));
final boolean hashOnlyLSIQuery = (userProvidedIndexName != null) && (!hasRangeKeyCondition) && parsedIndexesInfo.getAllLsiNames().contains(userProvidedIndexName);
final boolean userProvidedLSI = userProvidedLSIWithRangeKeyCondition || hashOnlyLSIQuery;
final boolean userProvidedGSIWithRangeKeyCondition = (userProvidedIndexName != null) && (annotatedGSIsOnRangeKey.contains(userProvidedIndexName));
final boolean hashOnlyGSIQuery = (userProvidedIndexName != null) && (!hasRangeKeyCondition) && parsedIndexesInfo.getAllGsiNames().contains(userProvidedIndexName);
final boolean userProvidedGSI = userProvidedGSIWithRangeKeyCondition || hashOnlyGSIQuery;
if (userProvidedLSI && userProvidedGSI) {
throw new DynamoDBMappingException("Invalid query: " + "Index \"" + userProvidedIndexName + "\" " + "is annotateded as both a LSI and a GSI for attribute.");
}
// Hash key conditions
for (final String hashKeyName : hashKeyConditions.keySet()) {
if (hashKeyName.equals(primaryHashKeyName)) {
hasPrimaryHashKeyCondition = true;
}
final Collection<String> annotatedGSINames = parsedIndexesInfo.getGsiNamesByIndexHashKey(hashKeyName);
annotatedGSIsOnHashKeys.put(hashKeyName, annotatedGSINames == null ? new HashSet<String>() : new HashSet<String>(annotatedGSINames));
// Additional validation if the user provided an index name.
if (userProvidedIndexName != null) {
boolean foundHashKeyConditionValidWithUserProvidedIndex = false;
if (userProvidedLSI && hashKeyName.equals(primaryHashKeyName)) {
// found an applicable hash key condition (primary hash +
// LSI range)
foundHashKeyConditionValidWithUserProvidedIndex = true;
} else if (userProvidedGSI && annotatedGSINames != null && annotatedGSINames.contains(userProvidedIndexName)) {
// found an applicable hash key condition (GSI hash + range)
foundHashKeyConditionValidWithUserProvidedIndex = true;
}
if (foundHashKeyConditionValidWithUserProvidedIndex) {
if (hashKeyNameForThisQuery != null) {
throw new IllegalArgumentException("Ambiguous query expression: More than one hash key EQ conditions (" + hashKeyNameForThisQuery + ", " + hashKeyName + ") are applicable to the specified index (" + userProvidedIndexName + "). " + "Please provide only one of them in the query expression.");
} else {
// found an applicable hash key condition
hashKeyNameForThisQuery = hashKeyName;
}
}
}
}
// Collate all the key conditions
final Map<String, Condition> keyConditions = new HashMap<String, Condition>();
// With user-provided index name
if (userProvidedIndexName != null) {
if (hasRangeKeyCondition && (!userProvidedLSI) && (!userProvidedGSI)) {
throw new IllegalArgumentException("Illegal query expression: No range key condition is applicable to the specified index (" + userProvidedIndexName + "). ");
}
if (hashKeyNameForThisQuery == null) {
throw new IllegalArgumentException("Illegal query expression: No hash key condition is applicable to the specified index (" + userProvidedIndexName + "). ");
}
keyConditions.put(hashKeyNameForThisQuery, hashKeyConditions.get(hashKeyNameForThisQuery));
if (hasRangeKeyCondition) {
keyConditions.putAll(rangeKeyConditions);
}
} else // Infer the index name by finding the index shared by both hash and
// range key annotations.
{
if (hasRangeKeyCondition) {
String inferredIndexName = null;
hashKeyNameForThisQuery = null;
if (hasPrimaryHashKeyCondition && hasPrimaryRangeKeyCondition) {
// Found valid query: primary hash + range key conditions
hashKeyNameForThisQuery = primaryHashKeyName;
} else {
// condition.
for (final String hashKeyName : annotatedGSIsOnHashKeys.keySet()) {
boolean foundValidQueryExpressionWithInferredIndex = false;
String indexNameInferredByThisHashKey = null;
if (hashKeyName.equals(primaryHashKeyName)) {
if (annotatedLSIsOnRangeKey.size() == 1) {
// Found valid query (Primary hash + LSI range
// conditions)
foundValidQueryExpressionWithInferredIndex = true;
indexNameInferredByThisHashKey = annotatedLSIsOnRangeKey.iterator().next();
}
}
final Set<String> annotatedGSIsOnHashKey = annotatedGSIsOnHashKeys.get(hashKeyName);
// We don't need the data in annotatedGSIsOnHashKeys
// afterwards,
// so it's safe to do the intersection in-place.
annotatedGSIsOnHashKey.retainAll(annotatedGSIsOnRangeKey);
if (annotatedGSIsOnHashKey.size() == 1) {
// GSI)
if (foundValidQueryExpressionWithInferredIndex) {
hashKeyNameForThisQuery = hashKeyName;
inferredIndexName = indexNameInferredByThisHashKey;
}
foundValidQueryExpressionWithInferredIndex = true;
indexNameInferredByThisHashKey = annotatedGSIsOnHashKey.iterator().next();
}
if (foundValidQueryExpressionWithInferredIndex) {
if (hashKeyNameForThisQuery != null) {
throw new IllegalArgumentException("Ambiguous query expression: Found multiple valid queries: " + "(Hash: \"" + hashKeyNameForThisQuery + "\", Range: \"" + rangeKeyNameForThisQuery + "\", Index: \"" + inferredIndexName + "\") and " + "(Hash: \"" + hashKeyName + "\", Range: \"" + rangeKeyNameForThisQuery + "\", Index: \"" + indexNameInferredByThisHashKey + "\").");
} else {
hashKeyNameForThisQuery = hashKeyName;
inferredIndexName = indexNameInferredByThisHashKey;
}
}
}
}
if (hashKeyNameForThisQuery != null) {
keyConditions.put(hashKeyNameForThisQuery, hashKeyConditions.get(hashKeyNameForThisQuery));
keyConditions.putAll(rangeKeyConditions);
queryRequest.setIndexName(inferredIndexName);
} else {
throw new IllegalArgumentException("Illegal query expression: Cannot infer the index name from the query expression.");
}
} else {
// No range key condition is specified.
if (hashKeyConditions.size() > 1) {
if (hasPrimaryHashKeyCondition) {
keyConditions.put(primaryHashKeyName, hashKeyConditions.get(primaryHashKeyName));
} else {
throw new IllegalArgumentException("Ambiguous query expression: More than one index hash key EQ conditions (" + hashKeyConditions.keySet() + ") are applicable to the query. " + "Please provide only one of them in the query expression, or specify the appropriate index name.");
}
} else {
// Only one hash key condition
final String hashKeyName = annotatedGSIsOnHashKeys.keySet().iterator().next();
if (!hasPrimaryHashKeyCondition) {
if (annotatedGSIsOnHashKeys.get(hashKeyName).size() == 1) {
// Set the index if the index hash key is only
// annotated with one GSI.
queryRequest.setIndexName(annotatedGSIsOnHashKeys.get(hashKeyName).iterator().next());
} else if (annotatedGSIsOnHashKeys.get(hashKeyName).size() > 1) {
throw new IllegalArgumentException("Ambiguous query expression: More than one GSIs (" + annotatedGSIsOnHashKeys.get(hashKeyName) + ") are applicable to the query. " + "Please specify one of them in your query expression.");
} else {
throw new IllegalArgumentException("Illegal query expression: No GSI is found in the @DynamoDBIndexHashKey annotation for attribute " + "\"" + hashKeyName + "\".");
}
}
keyConditions.putAll(hashKeyConditions);
}
}
}
queryRequest.setKeyConditions(keyConditions);
}
use of com.amazonaws.mobileconnectors.dynamodbv2.document.internal.Key in project aws-sdk-android by aws-amplify.
the class DynamoDBTableSchemaParser method getKeyAttributeDefinition.
private static AttributeDefinition getKeyAttributeDefinition(Method keyGetter, ItemConverter converter) {
final DynamoDBMapperFieldModel fieldModel = converter.getFieldModel(keyGetter);
final String keyAttrName = fieldModel.getDynamoDBAttributeName();
final DynamoDBAttributeType keyType = fieldModel.getDynamoDBAttributeType();
if (keyType == DynamoDBAttributeType.S || keyType == DynamoDBAttributeType.N || keyType == DynamoDBAttributeType.B) {
return new AttributeDefinition(keyAttrName, keyType.toString());
}
throw new DynamoDBMappingException("The key attribute must be in a scalar type " + "(String, Number or Binary).");
}
Aggregations