/* * Copyright 2012-2017 CodeLibs Project and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.codelibs.fess.entity; import static org.codelibs.core.stream.StreamUtil.stream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.exception.InvalidQueryException; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.util.ComponentUtil; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.lastaflute.core.message.UserMessages; public class GeoInfo { private QueryBuilder builder; public GeoInfo(final HttpServletRequest request) { final FessConfig fessConfig = ComponentUtil.getFessConfig(); final String[] geoFields = fessConfig.getQueryGeoFieldsAsArray(); final Map<String, List<QueryBuilder>> geoMap = new HashMap<>(); stream(request.getParameterMap()).of( stream -> stream.filter(e -> e.getKey().startsWith("geo.") && e.getKey().endsWith(".point")).forEach( e -> { final String key = e.getKey(); for (final String geoField : geoFields) { if (key.startsWith("geo." + geoField + ".")) { final String distanceKey = key.replaceFirst(".point$", ".distance"); final String distance = request.getParameter(distanceKey); if (StringUtil.isNotBlank(distance)) { stream(e.getValue()).of( s -> s.forEach(pt -> { List<QueryBuilder> list = geoMap.get(geoField); if (list == null) { list = new ArrayList<>(); geoMap.put(geoField, list); } final String[] values = pt.split(","); if (values.length == 2) { try { final double lat = Double.parseDouble(values[0]); final double lon = Double.parseDouble(values[1]); list.add(QueryBuilders.geoDistanceQuery(geoField).distance(distance) .point(lat, lon)); } catch (final Exception ex) { throw new InvalidQueryException(messages -> messages .addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY), ex .getLocalizedMessage(), ex); } } else { throw new InvalidQueryException(messages -> messages .addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY), "Invalid geo point: " + pt); } })); } break; } } })); final QueryBuilder[] queryBuilders = geoMap.values().stream().map(list -> { if (list.size() == 1) { return list.get(0); } else if (list.size() > 1) { final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); list.forEach(boolQuery::should); return boolQuery; } return null; }).filter(q -> q != null).toArray(n -> new QueryBuilder[n]); if (queryBuilders.length == 1) { builder = queryBuilders[0]; } else if (queryBuilders.length > 1) { final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); stream(queryBuilders).of(stream -> stream.forEach(boolQuery::must)); builder = boolQuery; } } public QueryBuilder toQueryBuilder() { return builder; } }