001/**
002 * Copyright 2017 Tampere University of Technology, Pori Department
003 * 
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package service.tut.pori.apilta.alerts.datatypes;
017
018import org.apache.commons.lang3.StringUtils;
019
020import core.tut.pori.dao.filter.AbstractQueryFilter;
021import core.tut.pori.http.Definitions;
022
023/**
024 * Basic filter for searching documents based on coordinate data.
025 * 
026 * The default filter type for this filter is {@link service.tut.pori.apilta.alerts.datatypes.AndGeoFilter#DEFAULT_FILTER_TYPE}.
027 */
028public class AndGeoFilter implements AbstractQueryFilter {
029  /** the default filter type */
030  public static final FilterType DEFAULT_FILTER_TYPE = FilterType.bbox;
031  private static final String PARAMETER_FIELD_NAME = "sfield";
032  private static final String PARAMETER_POINT = "pt";
033  private static final String PARAMETER_RANGE = "d";
034  private static final char PARAMETER_SEPARATOR = ' ';
035  private String _fieldName = null;
036  private FilterType _filterType = DEFAULT_FILTER_TYPE;
037  private Location _location = null;
038  private Double _range = null;
039  
040  /**
041   * Solr spatial filter type as defined in <a href="https://cwiki.apache.org/confluence/display/solr/Spatial+Search">Solr documentation</a>
042   * 
043   */
044  public enum FilterType {
045    /** filter of type geofilt */
046    geofilt,
047    /** filter of type bounding box */
048    bbox
049  } // enum FilterType
050  
051  /**
052   * 
053   * @param fieldName 
054   * @param location
055   * @param range
056   * @throws IllegalArgumentException
057   */
058  public AndGeoFilter(String fieldName, Location location, Double range) throws IllegalArgumentException {
059    if(range == null || range <= 0){
060      throw new IllegalArgumentException("Invalid range: "+range);
061    }
062    if(StringUtils.isBlank(fieldName)){
063      throw new IllegalArgumentException("Invalid field name: "+fieldName);
064    }
065    if(!Location.isValid(location)){
066      throw new IllegalArgumentException("Invalid location.");
067    }
068    _location = location;
069    _range = range;
070    _fieldName = fieldName;
071  }
072  
073  /**
074   * 
075   * @param fieldName 
076   * @param location
077   * @param filterType 
078   * @param range
079   * @throws IllegalArgumentException
080   */
081  public AndGeoFilter(String fieldName, Location location, FilterType filterType, Double range) throws IllegalArgumentException {
082    this(fieldName, location, range);
083    if(filterType == null){
084      throw new IllegalArgumentException("Invalid filter type: "+filterType);
085    }
086    _filterType = filterType;
087  }
088  
089  
090  @Override
091  public void toFilterString(StringBuilder fq) {
092    fq.append("{!");
093    fq.append(_filterType);
094    
095    fq.append(PARAMETER_SEPARATOR);   
096    fq.append(PARAMETER_POINT);
097    fq.append(Definitions.SEPARATOR_URI_QUERY_PARAM_VALUE);
098    fq.append(_location.getLatitude());
099    fq.append(Definitions.SEPARATOR_URI_QUERY_PARAM_VALUES);
100    fq.append(_location.getLongitude());
101    
102    fq.append(PARAMETER_SEPARATOR);
103    fq.append(PARAMETER_FIELD_NAME);
104    fq.append(Definitions.SEPARATOR_URI_QUERY_PARAM_VALUE);
105    fq.append(_fieldName);
106    
107    fq.append(PARAMETER_SEPARATOR);
108    fq.append(PARAMETER_RANGE);
109    fq.append(Definitions.SEPARATOR_URI_QUERY_PARAM_VALUE);
110    fq.append(_range);
111    
112    fq.append('}');
113  }
114
115  @Override
116  public QueryType getQueryType() {
117    return QueryType.AND;
118  }
119
120  /**
121   * @return the filterType
122   */
123  public FilterType getFilterType() {
124    return _filterType;
125  }
126}