1 | package org.springframework.data.elasticsearch.repository.query.parser; |
2 | |
3 | |
4 | import org.springframework.dao.InvalidDataAccessApiUsageException; |
5 | import org.springframework.data.domain.Sort; |
6 | import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; |
7 | import org.springframework.data.elasticsearch.core.query.Criteria; |
8 | import org.springframework.data.elasticsearch.core.query.CriteriaQuery; |
9 | import org.springframework.data.mapping.context.MappingContext; |
10 | import org.springframework.data.mapping.context.PersistentPropertyPath; |
11 | import org.springframework.data.repository.query.ParameterAccessor; |
12 | import org.springframework.data.repository.query.parser.AbstractQueryCreator; |
13 | import org.springframework.data.repository.query.parser.Part; |
14 | import org.springframework.data.repository.query.parser.PartTree; |
15 | |
16 | import java.util.Collection; |
17 | import java.util.Iterator; |
18 | |
19 | public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery,CriteriaQuery>{ |
20 | |
21 | private final MappingContext<?, ElasticsearchPersistentProperty> context; |
22 | |
23 | public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, MappingContext<?, ElasticsearchPersistentProperty> context) { |
24 | super(tree, parameters); |
25 | this.context = context; |
26 | } |
27 | |
28 | public ElasticsearchQueryCreator(PartTree tree, MappingContext<?, ElasticsearchPersistentProperty> context) { |
29 | super(tree); |
30 | this.context = context; |
31 | } |
32 | |
33 | @Override |
34 | protected CriteriaQuery create(Part part, Iterator<Object> iterator) { |
35 | PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty()); |
36 | return new CriteriaQuery(from(part.getType(), |
37 | new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); |
38 | } |
39 | |
40 | @Override |
41 | protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator<Object> iterator) { |
42 | if (base == null) { |
43 | return create(part, iterator); |
44 | } |
45 | PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty()); |
46 | return base.addCriteria(from(part.getType(), |
47 | new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); |
48 | } |
49 | |
50 | @Override |
51 | protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { |
52 | return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); |
53 | } |
54 | |
55 | @Override |
56 | protected CriteriaQuery complete(CriteriaQuery query, Sort sort) { |
57 | if (query == null) { |
58 | return null; |
59 | } |
60 | return query.addSort(sort); |
61 | } |
62 | |
63 | |
64 | private Criteria from(Part.Type type, Criteria instance, Iterator<?> parameters) { |
65 | Criteria criteria = instance; |
66 | if (criteria == null) { |
67 | criteria = new Criteria(); |
68 | } |
69 | switch (type) { |
70 | case TRUE: |
71 | return criteria.is(true); |
72 | case FALSE: |
73 | return criteria.is(false); |
74 | case SIMPLE_PROPERTY: |
75 | return criteria.is(parameters.next()); |
76 | case NEGATING_SIMPLE_PROPERTY: |
77 | return criteria.is(parameters.next()).not(); |
78 | case REGEX: |
79 | return criteria.expression(parameters.next().toString()); |
80 | case LIKE: |
81 | case STARTING_WITH: |
82 | return criteria.startsWith(parameters.next().toString()); |
83 | case ENDING_WITH: |
84 | return criteria.endsWith(parameters.next().toString()); |
85 | case CONTAINING: |
86 | return criteria.contains(parameters.next().toString()); |
87 | case AFTER: |
88 | case GREATER_THAN: |
89 | case GREATER_THAN_EQUAL: |
90 | return criteria.greaterThanEqual(parameters.next()); |
91 | case BEFORE: |
92 | case LESS_THAN: |
93 | case LESS_THAN_EQUAL: |
94 | return criteria.lessThanEqual(parameters.next()); |
95 | case BETWEEN: |
96 | return criteria.between(parameters.next(), parameters.next()); |
97 | case IN: |
98 | return criteria.in(asArray(parameters.next())); |
99 | case NOT_IN: |
100 | return criteria.in(asArray(parameters.next())).not(); |
101 | default: |
102 | throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); |
103 | } |
104 | } |
105 | |
106 | private Object[] asArray(Object o) { |
107 | if (o instanceof Collection) { |
108 | return ((Collection<?>) o).toArray(); |
109 | } else if (o.getClass().isArray()) { |
110 | return (Object[]) o; |
111 | } |
112 | return new Object[] { o }; |
113 | } |
114 | |
115 | } |