1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.socialsignin.spring.data.dynamodb.repository.query;
17
18 import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperTableModel;
19 import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
20 import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
21 import org.socialsignin.spring.data.dynamodb.query.Query;
22 import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
23 import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBIdIsHashAndRangeKeyEntityInformation;
24 import org.springframework.data.mapping.PropertyPath;
25 import org.springframework.data.repository.query.ParameterAccessor;
26 import org.springframework.data.repository.query.parser.AbstractQueryCreator;
27 import org.springframework.data.repository.query.parser.Part;
28 import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
29 import org.springframework.data.repository.query.parser.PartTree;
30 import org.springframework.util.Assert;
31 import org.springframework.util.ClassUtils;
32 import org.springframework.util.ObjectUtils;
33
34 import java.util.Arrays;
35 import java.util.Iterator;
36 import java.util.Optional;
37
38
39
40
41
42 public abstract class AbstractDynamoDBQueryCreator<T, ID, R>
43 extends
44 AbstractQueryCreator<Query<R>, DynamoDBQueryCriteria<T, ID>> {
45
46 protected final DynamoDBEntityInformation<T, ID> entityMetadata;
47 protected final DynamoDBOperations dynamoDBOperations;
48 protected final Optional<String> projection;
49
50 public AbstractDynamoDBQueryCreator(PartTree tree, DynamoDBEntityInformation<T, ID> entityMetadata,
51 Optional<String> projection, DynamoDBOperations dynamoDBOperations) {
52 super(tree);
53 this.entityMetadata = entityMetadata;
54 this.projection = projection;
55 this.dynamoDBOperations = dynamoDBOperations;
56 }
57
58 public AbstractDynamoDBQueryCreator(PartTree tree, ParameterAccessor parameterAccessor,
59 DynamoDBEntityInformation<T, ID> entityMetadata, Optional<String> projection,
60 DynamoDBOperations dynamoDBOperations) {
61 super(tree, parameterAccessor);
62 this.entityMetadata = entityMetadata;
63 this.projection = projection;
64 this.dynamoDBOperations = dynamoDBOperations;
65 }
66
67 @Override
68 protected DynamoDBQueryCriteria<T, ID> create(Part part, Iterator<Object> iterator) {
69 final DynamoDBMapperTableModel<T> tableModel = dynamoDBOperations.getTableModel(entityMetadata.getJavaType());
70 DynamoDBQueryCriteria<T, ID> criteria = entityMetadata.isRangeKeyAware()
71 ? new DynamoDBEntityWithHashAndRangeKeyCriteria<T, ID>(
72 (DynamoDBIdIsHashAndRangeKeyEntityInformation<T, ID>) entityMetadata, tableModel)
73 : new DynamoDBEntityWithHashKeyOnlyCriteria<>(entityMetadata, tableModel);
74 return addCriteria(criteria, part, iterator);
75 }
76
77 protected DynamoDBQueryCriteria<T, ID> addCriteria(DynamoDBQueryCriteria<T, ID> criteria, Part part,
78 Iterator<Object> iterator) {
79 if (part.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS))
80 throw new UnsupportedOperationException("Case insensitivity not supported");
81
82 Class<?> leafNodePropertyType = part.getProperty().getLeafProperty().getType();
83
84 PropertyPath leafNodePropertyPath = part.getProperty().getLeafProperty();
85 String leafNodePropertyName = leafNodePropertyPath.toDotPath();
86 if (leafNodePropertyName.indexOf(".") != -1) {
87 int index = leafNodePropertyName.lastIndexOf(".");
88 leafNodePropertyName = leafNodePropertyName.substring(index);
89 }
90
91 switch (part.getType()) {
92
93 case IN :
94 Object in = iterator.next();
95 Assert.notNull(in, "Creating conditions on null parameters not supported: please specify a value for '"
96 + leafNodePropertyName + "'");
97 boolean isIterable = ClassUtils.isAssignable(Iterable.class, in.getClass());
98 boolean isArray = ObjectUtils.isArray(in);
99 Assert.isTrue(isIterable || isArray, "In criteria can only operate with Iterable or Array parameters");
100 Iterable<?> iterable = isIterable ? ((Iterable<?>) in) : Arrays.asList(ObjectUtils.toObjectArray(in));
101 return criteria.withPropertyIn(leafNodePropertyName, iterable, leafNodePropertyType);
102 case CONTAINING :
103 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.CONTAINS,
104 iterator.next(), leafNodePropertyType);
105 case STARTING_WITH :
106 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.BEGINS_WITH,
107 iterator.next(), leafNodePropertyType);
108 case BETWEEN :
109 Object first = iterator.next();
110 Object second = iterator.next();
111 return criteria.withPropertyBetween(leafNodePropertyName, first, second, leafNodePropertyType);
112 case AFTER :
113 case GREATER_THAN :
114 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.GT, iterator.next(),
115 leafNodePropertyType);
116 case BEFORE :
117 case LESS_THAN :
118 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.LT, iterator.next(),
119 leafNodePropertyType);
120 case GREATER_THAN_EQUAL :
121 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.GE, iterator.next(),
122 leafNodePropertyType);
123 case LESS_THAN_EQUAL :
124 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.LE, iterator.next(),
125 leafNodePropertyType);
126 case IS_NULL :
127 return criteria.withNoValuedCriteria(leafNodePropertyName, ComparisonOperator.NULL);
128 case IS_NOT_NULL :
129 return criteria.withNoValuedCriteria(leafNodePropertyName, ComparisonOperator.NOT_NULL);
130 case TRUE :
131 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.EQ, Boolean.TRUE,
132 leafNodePropertyType);
133 case FALSE :
134 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.EQ, Boolean.FALSE,
135 leafNodePropertyType);
136 case SIMPLE_PROPERTY :
137 return criteria.withPropertyEquals(leafNodePropertyName, iterator.next(), leafNodePropertyType);
138 case NEGATING_SIMPLE_PROPERTY :
139 return criteria.withSingleValueCriteria(leafNodePropertyName, ComparisonOperator.NE, iterator.next(),
140 leafNodePropertyType);
141 default :
142 throw new IllegalArgumentException("Unsupported keyword " + part.getType());
143 }
144
145 }
146
147 @Override
148 protected DynamoDBQueryCriteria<T, ID> and(Part part, DynamoDBQueryCriteria<T, ID> base,
149 Iterator<Object> iterator) {
150 return addCriteria(base, part, iterator);
151
152 }
153
154 @Override
155 protected DynamoDBQueryCriteria<T, ID> or(DynamoDBQueryCriteria<T, ID> base,
156 DynamoDBQueryCriteria<T, ID> criteria) {
157 throw new UnsupportedOperationException("Or queries not supported");
158 }
159
160 }