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.fesen.index.query.BoolQueryBuilder;
29 import org.codelibs.fesen.index.query.QueryBuilder;
30 import org.codelibs.fesen.index.query.QueryBuilders;
31 import org.codelibs.fess.exception.InvalidQueryException;
32 import org.codelibs.fess.mylasta.direction.FessConfig;
33 import org.codelibs.fess.util.ComponentUtil;
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())
47 .of(stream -> stream.filter(e -> e.getKey().startsWith("geo.") && e.getKey().endsWith(".point")).forEach(e -> {
48 final String key = e.getKey();
49 for (final String geoField : geoFields) {
50 if (key.startsWith("geo." + geoField + ".")) {
51 final String distanceKey = key.replaceFirst(".point$", ".distance");
52 final String distance = request.getParameter(distanceKey);
53 if (StringUtil.isNotBlank(distance)) {
54 stream(e.getValue()).of(s -> s.forEach(pt -> {
55 List<QueryBuilder> list = geoMap.get(geoField);
56 if (list == null) {
57 list = new ArrayList<>();
58 geoMap.put(geoField, list);
59 }
60 final String[] values = pt.split(",");
61 if (values.length != 2) {
62 throw new InvalidQueryException(
63 messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
64 "Invalid geo point: " + pt);
65 }
66 try {
67 final double lat = Double.parseDouble(values[0]);
68 final double lon = Double.parseDouble(values[1]);
69 list.add(QueryBuilders.geoDistanceQuery(geoField).distance(distance).point(lat, lon));
70 } catch (final Exception ex) {
71 throw new InvalidQueryException(
72 messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
73 ex.getLocalizedMessage(), ex);
74 }
75 }));
76 }
77 break;
78 }
79 }
80 }));
81
82 final QueryBuilder[] queryBuilders = geoMap.values().stream().map(list -> {
83 if (list.size() == 1) {
84 return list.get(0);
85 }
86 if (list.size() > 1) {
87 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
88 list.forEach(boolQuery::should);
89 return boolQuery;
90 }
91 return null;
92 }).filter(q -> q != null).toArray(n -> new QueryBuilder[n]);
93
94 if (queryBuilders.length == 1) {
95 builder = queryBuilders[0];
96 } else if (queryBuilders.length > 1) {
97 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
98 stream(queryBuilders).of(stream -> stream.forEach(boolQuery::must));
99 builder = boolQuery;
100 }
101
102 }
103
104 public QueryBuilder toQueryBuilder() {
105 return builder;
106 }
107
108 }