1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.api.models;
18
19 import static org.forgerock.api.util.ValidationUtil.*;
20
21 import java.lang.reflect.Method;
22 import java.util.Arrays;
23 import java.util.Objects;
24
25 import com.fasterxml.jackson.annotation.JsonProperty;
26 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
27 import org.wrensecurity.guava.common.base.Strings;
28
29 import org.forgerock.api.ApiValidationException;
30 import org.forgerock.api.enums.CountPolicy;
31 import org.forgerock.api.enums.PagingMode;
32 import org.forgerock.api.enums.QueryType;
33
34
35
36
37 @JsonDeserialize(builder = Query.Builder.class)
38 public final class Query extends Operation implements Comparable<Query> {
39
40 private final QueryType type;
41 private final PagingMode[] pagingModes;
42 private final CountPolicy[] countPolicies;
43 private final String queryId;
44 private final String[] queryableFields;
45 private final String[] supportedSortKeys;
46
47 private Query(Builder builder) {
48 super(builder);
49 this.type = builder.type;
50 this.pagingModes = builder.pagingModes;
51 this.countPolicies = builder.countPolicies;
52 this.queryId = builder.queryId;
53 this.queryableFields = builder.queryableFields;
54 this.supportedSortKeys = builder.supportedSortKeys;
55
56 if (type == null) {
57 throw new ApiValidationException("type is required");
58 }
59 if (type == QueryType.ID && isEmpty(queryId)) {
60 throw new ApiValidationException("queryId required for type = ID");
61 }
62 }
63
64
65
66
67
68
69 public QueryType getType() {
70 return type;
71 }
72
73
74
75
76
77
78 public PagingMode[] getPagingModes() {
79 return pagingModes;
80 }
81
82
83
84
85
86
87
88
89 public CountPolicy[] getCountPolicies() {
90 return countPolicies;
91 }
92
93
94
95
96
97
98 public String getQueryId() {
99 return queryId;
100 }
101
102
103
104
105
106
107 public String[] getQueryableFields() {
108 return queryableFields;
109 }
110
111
112
113
114
115
116 public String[] getSupportedSortKeys() {
117 return supportedSortKeys;
118 }
119
120 @Override
121 public boolean equals(Object o) {
122 if (this == o) {
123 return true;
124 }
125 if (o == null || getClass() != o.getClass()) {
126 return false;
127 }
128 if (!super.equals(o)) {
129 return false;
130 }
131 Query query = (Query) o;
132 return type == query.type
133 && Arrays.equals(pagingModes, query.pagingModes)
134 && Arrays.equals(countPolicies, query.countPolicies)
135 && Objects.equals(queryId, query.queryId)
136 && Arrays.equals(queryableFields, query.queryableFields)
137 && Arrays.equals(supportedSortKeys, query.supportedSortKeys);
138 }
139
140 @Override
141 public int hashCode() {
142 return Objects.hash(super.hashCode(), type, pagingModes, countPolicies, queryId, queryableFields,
143 supportedSortKeys);
144 }
145
146
147
148
149
150
151 public static Builder query() {
152 return new Builder();
153 }
154
155
156
157
158
159
160 @Override
161 protected void allocateToResource(Resource.Builder resourceBuilder) {
162 resourceBuilder.query(this);
163 }
164
165
166
167
168
169
170
171
172
173
174 public static Query fromAnnotation(org.forgerock.api.annotations.Query query, Method annotated,
175 ApiDescription descriptor, Class<?> relativeType) {
176 String queryId = query.id();
177 if (query.type() == QueryType.ID && Strings.isNullOrEmpty(queryId)) {
178 if (annotated == null) {
179 throw new IllegalArgumentException("Query is missing ID: " + query);
180 }
181 queryId = annotated.getName();
182 }
183 return query()
184 .detailsFromAnnotation(query.operationDescription(), descriptor, relativeType)
185 .type(query.type())
186 .pagingModes(query.pagingModes())
187 .countPolicies(query.countPolicies())
188 .queryId(queryId)
189 .queryableFields(query.queryableFields())
190 .supportedSortKeys(query.sortKeys())
191 .build();
192 }
193
194
195
196
197
198
199
200
201
202
203
204 @Override
205 public int compareTo(final Query query) {
206
207
208 switch (query.getType()) {
209 case EXPRESSION:
210 if (this.getType() == QueryType.EXPRESSION) {
211 return 0;
212 }
213 return 1;
214 case FILTER:
215 if (this.getType() == QueryType.FILTER) {
216 return 0;
217 }
218 if (this.getType() == QueryType.EXPRESSION) {
219 return -1;
220 }
221 return 1;
222 case ID:
223 if (this.getType() == QueryType.ID) {
224 return this.queryId.compareTo(query.getQueryId());
225 }
226 return -1;
227 default:
228 throw new IllegalStateException("Unsupported QueryType: " + query.getType());
229 }
230
231 }
232
233
234
235
236 public static final class Builder extends Operation.Builder<Builder> {
237
238 private QueryType type;
239 private PagingMode[] pagingModes;
240 private CountPolicy[] countPolicies;
241 private String queryId;
242 private String[] queryableFields;
243 private String[] supportedSortKeys;
244
245
246
247
248
249
250 @Override
251 protected Builder self() {
252 return this;
253 }
254
255
256
257
258
259
260
261 @JsonProperty("type")
262 public Builder type(QueryType type) {
263 this.type = type;
264 return this;
265 }
266
267
268
269
270
271
272
273 @JsonProperty("pagingModes")
274 public Builder pagingModes(PagingMode... pagingMode) {
275 this.pagingModes = pagingMode;
276 return this;
277 }
278
279
280
281
282
283
284
285
286
287 @JsonProperty("countPolicies")
288 public Builder countPolicies(CountPolicy... countPolicy) {
289 this.countPolicies = countPolicy;
290 return this;
291 }
292
293
294
295
296
297
298
299 @JsonProperty("queryId")
300 public Builder queryId(String queryId) {
301 this.queryId = queryId;
302 return this;
303 }
304
305
306
307
308
309
310
311 @JsonProperty("queryableFields")
312 public Builder queryableFields(String... queryableFields) {
313 this.queryableFields = queryableFields;
314 return this;
315 }
316
317
318
319
320
321
322
323 @JsonProperty("supportedSortKeys")
324 public Builder supportedSortKeys(String... supportedSortKeys) {
325 this.supportedSortKeys = supportedSortKeys;
326 return this;
327 }
328
329
330
331
332
333
334 public Query build() {
335 return new Query(this);
336 }
337 }
338
339 }