}
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 (String rangeKeyName : rangeKeyConditions.keySet()) {
rangeKeyNameForThisQuery = rangeKeyName;
if (reflector.hasPrimaryRangeKey(clazz)
&& rangeKeyName.equals(reflector.getPrimaryRangeKeyName(clazz))) {
hasPrimaryRangeKeyCondition = true;
}
Collection<String> annotatedLSI = parsedIndexesInfo.getLsiNamesByIndexRangeKey(rangeKeyName);
if (annotatedLSI != null) {
annotatedLSIsOnRangeKey.addAll(annotatedLSI);
}
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 (String hashKeyName : hashKeyConditions.keySet()) {
if (hashKeyName.equals(primaryHashKeyName)) {
hasPrimaryHashKeyCondition = true;
}
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) {