1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.entity;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.servlet.http.HttpServletRequest;
26
27 import org.codelibs.core.lang.StringUtil;
28 import org.codelibs.fess.exception.InvalidQueryException;
29 import org.codelibs.fess.mylasta.direction.FessConfig;
30 import org.codelibs.fess.util.ComponentUtil;
31 import org.elasticsearch.index.query.BoolQueryBuilder;
32 import org.elasticsearch.index.query.QueryBuilder;
33 import org.elasticsearch.index.query.QueryBuilders;
34 import org.lastaflute.core.message.UserMessages;
35
36 public class GeoInfo {
37
38 private QueryBuilder builder;
39
40 public GeoInfo(final HttpServletRequest request) {
41
42 final FessConfig fessConfig = ComponentUtil.getFessConfig();
43 final String[] geoFields = fessConfig.getQueryGeoFieldsAsArray();
44 final Map<String, List<QueryBuilder>> geoMap = new HashMap<>();
45
46 stream(request.getParameterMap()).of(
47 stream -> stream.filter(e -> e.getKey().startsWith("geo.") && e.getKey().endsWith(".point")).forEach(
48 e -> {
49 final String key = e.getKey();
50 for (final String geoField : geoFields) {
51 if (key.startsWith("geo." + geoField + ".")) {
52 final String distanceKey = key.replaceFirst(".point$", ".distance");
53 final String distance = request.getParameter(distanceKey);
54 if (StringUtil.isNotBlank(distance)) {
55 stream(e.getValue()).of(
56 s -> s.forEach(pt -> {
57 List<QueryBuilder> list = geoMap.get(geoField);
58 if (list == null) {
59 list = new ArrayList<>();
60 geoMap.put(geoField, list);
61 }
62 final String[] values = pt.split(",");
63 if (values.length == 2) {
64 try {
65 final double lat = Double.parseDouble(values[0]);
66 final double lon = Double.parseDouble(values[1]);
67 list.add(QueryBuilders.geoDistanceQuery(geoField).distance(distance)
68 .point(lat, lon));
69 } catch (final Exception ex) {
70 throw new InvalidQueryException(messages -> messages
71 .addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY), ex
72 .getLocalizedMessage(), ex);
73 }
74 } else {
75 throw new InvalidQueryException(messages -> messages
76 .addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
77 "Invalid geo point: " + pt);
78 }
79 }));
80 }
81 break;
82 }
83 }
84 }));
85
86 final QueryBuilder[] queryBuilders = geoMap.values().stream().map(list -> {
87 if (list.size() == 1) {
88 return list.get(0);
89 } else if (list.size() > 1) {
90 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
91 list.forEach(boolQuery::should);
92 return boolQuery;
93 }
94 return null;
95 }).filter(q -> q != null).toArray(n -> new QueryBuilder[n]);
96
97 if (queryBuilders.length == 1) {
98 builder = queryBuilders[0];
99 } else if (queryBuilders.length > 1) {
100 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
101 stream(queryBuilders).of(stream -> stream.forEach(boolQuery::must));
102 builder = boolQuery;
103 }
104
105 }
106
107 public QueryBuilder toQueryBuilder() {
108 return builder;
109 }
110
111 }