View Javadoc
1   /*
2    * Copyright 2012-2021 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.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 }