1 | /* |
2 | * Copyright 2013 the original author or authors. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | package org.springframework.data.elasticsearch.repository.query.parser; |
17 | |
18 | |
19 | import org.springframework.dao.InvalidDataAccessApiUsageException; |
20 | import org.springframework.data.domain.Sort; |
21 | import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; |
22 | import org.springframework.data.elasticsearch.core.query.Criteria; |
23 | import org.springframework.data.elasticsearch.core.query.CriteriaQuery; |
24 | import org.springframework.data.mapping.context.MappingContext; |
25 | import org.springframework.data.mapping.context.PersistentPropertyPath; |
26 | import org.springframework.data.repository.query.ParameterAccessor; |
27 | import org.springframework.data.repository.query.parser.AbstractQueryCreator; |
28 | import org.springframework.data.repository.query.parser.Part; |
29 | import org.springframework.data.repository.query.parser.PartTree; |
30 | |
31 | import java.util.Collection; |
32 | import java.util.Iterator; |
33 | |
34 | /** |
35 | * ElasticsearchQueryCreator |
36 | * |
37 | * @author Rizwan Idrees |
38 | * @author Mohsin Husen |
39 | */ |
40 | public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery,CriteriaQuery>{ |
41 | |
42 | private final MappingContext<?, ElasticsearchPersistentProperty> context; |
43 | |
44 | public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, MappingContext<?, ElasticsearchPersistentProperty> context) { |
45 | super(tree, parameters); |
46 | this.context = context; |
47 | } |
48 | |
49 | public ElasticsearchQueryCreator(PartTree tree, MappingContext<?, ElasticsearchPersistentProperty> context) { |
50 | super(tree); |
51 | this.context = context; |
52 | } |
53 | |
54 | @Override |
55 | protected CriteriaQuery create(Part part, Iterator<Object> iterator) { |
56 | PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty()); |
57 | return new CriteriaQuery(from(part.getType(), |
58 | new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); |
59 | } |
60 | |
61 | @Override |
62 | protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator<Object> iterator) { |
63 | if (base == null) { |
64 | return create(part, iterator); |
65 | } |
66 | PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty()); |
67 | return base.addCriteria(from(part.getType(), |
68 | new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); |
69 | } |
70 | |
71 | @Override |
72 | protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { |
73 | return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); |
74 | } |
75 | |
76 | @Override |
77 | protected CriteriaQuery complete(CriteriaQuery query, Sort sort) { |
78 | if (query == null) { |
79 | return null; |
80 | } |
81 | return query.addSort(sort); |
82 | } |
83 | |
84 | |
85 | private Criteria from(Part.Type type, Criteria instance, Iterator<?> parameters) { |
86 | Criteria criteria = instance; |
87 | if (criteria == null) { |
88 | criteria = new Criteria(); |
89 | } |
90 | switch (type) { |
91 | case TRUE: |
92 | return criteria.is(true); |
93 | case FALSE: |
94 | return criteria.is(false); |
95 | case SIMPLE_PROPERTY: |
96 | return criteria.is(parameters.next()); |
97 | case NEGATING_SIMPLE_PROPERTY: |
98 | return criteria.is(parameters.next()).not(); |
99 | case REGEX: |
100 | return criteria.expression(parameters.next().toString()); |
101 | case LIKE: |
102 | case STARTING_WITH: |
103 | return criteria.startsWith(parameters.next().toString()); |
104 | case ENDING_WITH: |
105 | return criteria.endsWith(parameters.next().toString()); |
106 | case CONTAINING: |
107 | return criteria.contains(parameters.next().toString()); |
108 | case AFTER: |
109 | case GREATER_THAN: |
110 | case GREATER_THAN_EQUAL: |
111 | return criteria.greaterThanEqual(parameters.next()); |
112 | case BEFORE: |
113 | case LESS_THAN: |
114 | case LESS_THAN_EQUAL: |
115 | return criteria.lessThanEqual(parameters.next()); |
116 | case BETWEEN: |
117 | return criteria.between(parameters.next(), parameters.next()); |
118 | case IN: |
119 | return criteria.in(asArray(parameters.next())); |
120 | case NOT_IN: |
121 | return criteria.in(asArray(parameters.next())).not(); |
122 | default: |
123 | throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); |
124 | } |
125 | } |
126 | |
127 | private Object[] asArray(Object o) { |
128 | if (o instanceof Collection) { |
129 | return ((Collection<?>) o).toArray(); |
130 | } else if (o.getClass().isArray()) { |
131 | return (Object[]) o; |
132 | } |
133 | return new Object[] { o }; |
134 | } |
135 | |
136 | } |