View Javadoc
1   /*
2    * Copyright 2012-2017 CodeLibs Project and the Others.
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,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
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 }