Skip to content

Commit 7e9f12c

Browse files
committed
Merge branch 'geo_location'
2 parents 5a34a90 + bb81fa7 commit 7e9f12c

24 files changed

+1720
-733
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.annotations;
17+
18+
import java.lang.annotation.*;
19+
20+
/**
21+
* @author Artur Konczak
22+
*/
23+
@Retention(RetentionPolicy.RUNTIME)
24+
@Target(ElementType.FIELD)
25+
@Documented
26+
public @interface GeoPointField {
27+
28+
}

src/main/java/org/springframework/data/elasticsearch/client/TransportClientFactoryBean.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
4646
private Boolean clientIgnoreClusterName;
4747
private String clientPingTimeout;
4848
private String clientNodesSamplerInterval;
49+
private Boolean clientIgnoreClusterName;
50+
private String clientPingTimeout;
51+
private String clientNodesSamplerInterval;
4952
private TransportClient client;
5053
private Properties properties;
5154
static final String COLON = ":";
@@ -118,6 +121,8 @@ public void setClusterName(String clusterName) {
118121
this.clusterName = clusterName;
119122
}
120123

124+
}
125+
121126
public void setClientTransportSniff(Boolean clientTransportSniff) {
122127
this.clientTransportSniff = clientTransportSniff;
123128
}
@@ -146,6 +151,30 @@ public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
146151
this.clientIgnoreClusterName = clientIgnoreClusterName;
147152
}
148153

154+
public String getClientNodesSamplerInterval() {
155+
return clientNodesSamplerInterval;
156+
}
157+
158+
public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) {
159+
this.clientNodesSamplerInterval = clientNodesSamplerInterval;
160+
}
161+
162+
public String getClientPingTimeout() {
163+
return clientPingTimeout;
164+
}
165+
166+
public void setClientPingTimeout(String clientPingTimeout) {
167+
this.clientPingTimeout = clientPingTimeout;
168+
}
169+
170+
public Boolean getClientIgnoreClusterName() {
171+
return clientIgnoreClusterName;
172+
}
173+
174+
public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
175+
this.clientIgnoreClusterName = clientIgnoreClusterName;
176+
}
177+
149178
public void setProperties(Properties properties) {
150179
this.properties = properties;
151180
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
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.core;
17+
18+
import org.elasticsearch.index.query.*;
19+
import org.springframework.data.elasticsearch.core.geo.GeoBox;
20+
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
21+
import org.springframework.data.elasticsearch.core.query.Criteria;
22+
import org.springframework.util.Assert;
23+
24+
import java.util.Iterator;
25+
import java.util.LinkedList;
26+
import java.util.List;
27+
import java.util.ListIterator;
28+
29+
import static org.elasticsearch.index.query.FilterBuilders.*;
30+
import static org.springframework.data.elasticsearch.core.query.Criteria.OperationKey;
31+
32+
/**
33+
* CriteriaFilterProcessor
34+
*
35+
* @author Franck Marchand
36+
*/
37+
class CriteriaFilterProcessor {
38+
39+
40+
FilterBuilder createFilterFromCriteria(Criteria criteria) {
41+
List<FilterBuilder> fbList = new LinkedList<FilterBuilder>();
42+
FilterBuilder filter = null;
43+
44+
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
45+
46+
while (chainIterator.hasNext()) {
47+
FilterBuilder fb = null;
48+
Criteria chainedCriteria = chainIterator.next();
49+
if (chainedCriteria.isOr()) {
50+
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{}));
51+
fbList.add(fb);
52+
} else if (chainedCriteria.isNegating()) {
53+
List<FilterBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
54+
55+
if (!negationFilters.isEmpty()) {
56+
fbList.addAll(negationFilters);
57+
}
58+
} else {
59+
fbList.addAll(createFilterFragmentForCriteria(chainedCriteria));
60+
}
61+
}
62+
63+
if (!fbList.isEmpty()) {
64+
if (fbList.size() == 1) {
65+
filter = fbList.get(0);
66+
} else {
67+
filter = andFilter(fbList.toArray(new FilterBuilder[]{}));
68+
}
69+
}
70+
71+
return filter;
72+
}
73+
74+
75+
private List<FilterBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
76+
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getFilterCriteriaEntries().iterator();
77+
List<FilterBuilder> filterList = new LinkedList<FilterBuilder>();
78+
79+
String fieldName = chainedCriteria.getField().getName();
80+
Assert.notNull(fieldName, "Unknown field");
81+
FilterBuilder filter = null;
82+
83+
while (it.hasNext()) {
84+
Criteria.CriteriaEntry entry = it.next();
85+
filter = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
86+
filterList.add(filter);
87+
}
88+
89+
return filterList;
90+
}
91+
92+
93+
private FilterBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
94+
if (value == null) {
95+
return null;
96+
}
97+
FilterBuilder filter = null;
98+
99+
switch (key) {
100+
case WITHIN: {
101+
filter = geoDistanceFilter(fieldName);
102+
103+
Assert.isTrue(value instanceof Object[], "Value of a geo distance filter should be an array of two values.");
104+
Object[] valArray = (Object[]) value;
105+
Assert.noNullElements(valArray, "Geo distance filter takes 2 not null elements array as parameter.");
106+
Assert.isTrue(valArray.length == 2, "Geo distance filter takes a 2-elements array as parameter.");
107+
Assert.isTrue(valArray[0] instanceof GeoPoint || valArray[0] instanceof String, "First element of a geo distance filter must be a GeoLocation or String");
108+
Assert.isTrue(valArray[1] instanceof String, "Second element of a geo distance filter must be a String");
109+
110+
String dist = (String) valArray[1];
111+
if (valArray[0] instanceof GeoPoint) {
112+
GeoPoint loc = (GeoPoint) valArray[0];
113+
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist);
114+
} else {
115+
String loc = (String) valArray[0];
116+
if (loc.contains(",")) {
117+
String c[] = loc.split(",");
118+
((GeoDistanceFilterBuilder) filter).lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist);
119+
} else {
120+
((GeoDistanceFilterBuilder) filter).geohash(loc).distance(dist);
121+
}
122+
123+
}
124+
125+
break;
126+
}
127+
128+
case BBOX: {
129+
filter = geoBoundingBoxFilter(fieldName);
130+
131+
Assert.isTrue(value instanceof Object[], "Value of a bbox filter should be an array of one or two values.");
132+
Object[] valArray = (Object[]) value;
133+
Assert.noNullElements(valArray, "Geo bbox filter takes a not null element array as parameter.");
134+
135+
if (valArray.length == 1) {
136+
//GeoEnvelop
137+
oneParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray[0]);
138+
} else if (valArray.length == 2) {
139+
//2x GeoPoint
140+
//2x String
141+
twoParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray);
142+
} else {
143+
//error
144+
Assert.isTrue(false, "Geo distance filter takes a 1-elements array(GeoEnvelop) or 2-elements array(GeoPoints or Strings(geohash)).");
145+
}
146+
break;
147+
}
148+
149+
}
150+
151+
return filter;
152+
}
153+
154+
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
155+
Assert.isTrue(value instanceof GeoBox, "single-element of a geo bbox filter must be type of GeoEnvelop");
156+
GeoBox geoBBox = (GeoBox) value;
157+
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
158+
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
159+
}
160+
161+
private static boolean isType(Object[] array, Class clazz) {
162+
for (Object o : array) {
163+
if (!clazz.isInstance(o)) {
164+
return false;
165+
}
166+
}
167+
return true;
168+
}
169+
170+
private void twoParameterBBox(GeoBoundingBoxFilterBuilder filter, Object[] values) {
171+
Assert.isTrue(isType(values, GeoPoint.class) || isType(values, String.class), " both elements of geo bbox filter must be type of GeoPoint or String(geohash)");
172+
if (values[0] instanceof GeoPoint) {
173+
GeoPoint topLeft = (GeoPoint) values[0];
174+
GeoPoint bottomRight = (GeoPoint) values[1];
175+
filter.topLeft(topLeft.getLat(), topLeft.getLon());
176+
filter.bottomRight(bottomRight.getLat(), bottomRight.getLon());
177+
} else {
178+
String topLeft = (String) values[0];
179+
String bottomRight = (String) values[1];
180+
filter.topLeft(topLeft);
181+
filter.bottomRight(bottomRight);
182+
}
183+
}
184+
185+
private List<FilterBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
186+
List<FilterBuilder> notFilterList = new LinkedList<FilterBuilder>();
187+
188+
while (it.hasNext()) {
189+
Criteria.CriteriaEntry criteriaEntry = it.next();
190+
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
191+
notFilterList.add(notFilter);
192+
}
193+
194+
return notFilterList;
195+
}
196+
}

0 commit comments

Comments
 (0)