001/**
002 * Copyright 2015 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 core.tut.pori.dao.filter;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.HashSet;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Set;
024
025import org.apache.commons.lang3.StringUtils;
026import org.apache.solr.client.solrj.util.ClientUtils;
027
028import core.tut.pori.dao.SolrQueryBuilder;
029
030/**
031 * Basic and filter with OR relation to other query filters, the values themselves have OR relation with one another.
032 *
033 * Comparison to null (non-existent) value is accepted.
034 */
035public class OrQueryFilter implements AbstractQueryFilter {
036  private static final char SOLR_NEGATIVE_QUERY = '-';
037  private String _fieldName = null;
038  private Set<String> _values = null;
039  private boolean _hasNullValue = false;
040  
041  /**
042   * 
043   * @param fieldName
044   * @param values
045   * @throws IllegalArgumentException on bad field name
046   */
047  public OrQueryFilter(String fieldName, Collection<? extends Object> values) throws IllegalArgumentException{
048    addFilter(fieldName, values);     
049  }
050  
051  /**
052   * 
053   * @param fieldName
054   * @param value
055   * @throws IllegalArgumentException on bad field name
056   */
057  public OrQueryFilter(String fieldName, Object value) throws IllegalArgumentException{
058    if(StringUtils.isBlank(fieldName)){
059      throw new IllegalArgumentException("No field name.");
060    }
061    _fieldName = fieldName;
062    if(value == null){
063      _hasNullValue = true;
064    }else{
065      _values = new HashSet<>(1);
066      _values.add(ClientUtils.escapeQueryChars(String.valueOf(value)));
067    }
068  }
069  
070  /**
071   * 
072   * @param fieldName
073   * @param values
074   * @throws IllegalArgumentException on bad field name
075   */
076  public OrQueryFilter(String fieldName, long[] values) throws IllegalArgumentException{
077    List<String> v = null;
078    if(values != null){
079      v = new ArrayList<>(values.length);
080      for(int i=0;i<values.length;++i){
081        v.add(String.valueOf(values[i]));
082      }
083    }
084    addFilter(fieldName, v);
085  }
086  
087  /**
088   * 
089   * @param fieldName
090   * @param values
091   * @throws IllegalArgumentException on bad field name
092   */
093  public OrQueryFilter(String fieldName, int[] values) throws IllegalArgumentException{
094    List<String> v = null;
095    if(values != null){
096      v = new ArrayList<>(values.length);
097      for(int i=0;i<values.length;++i){
098        v.add(String.valueOf(values[i]));
099      }
100    }
101    addFilter(fieldName, v);
102  }
103  
104  /**
105   * 
106   * @param fieldName
107   * @param values
108   * @throws IllegalArgumentException on bad field name
109   */
110  private void addFilter(String fieldName, Collection<? extends Object> values) throws IllegalArgumentException{
111    if(StringUtils.isBlank(fieldName)){
112      throw new IllegalArgumentException("No field name.");
113    }
114    
115    _fieldName = fieldName;
116    if(values == null || values.isEmpty()){
117      _hasNullValue = true;
118      return;
119    }
120    
121    _values = new HashSet<>(values.size());
122    for(Iterator<? extends Object> iter = values.iterator(); iter.hasNext();){
123      Object value = iter.next();
124      if(value == null){
125        _hasNullValue = true;
126      }else{
127        _values.add(ClientUtils.escapeQueryChars(String.valueOf(value)));
128      } 
129    }
130    
131    if(_values.isEmpty()){  // if there was only the null value
132      _values = null;
133    }
134  }
135
136  @Override
137  public void toFilterString(StringBuilder fq) {
138    fq.append('(');
139    if(_values != null){
140      fq.append(_fieldName);
141      fq.append(SolrQueryBuilder.SEPARATOR_SOLR_FIELD_VALUE);
142      fq.append('(');
143      Iterator<String> iter = _values.iterator();
144      fq.append(iter.next());
145      while(iter.hasNext()){
146        fq.append(SOLR_OR);
147        fq.append(iter.next());
148      }
149      
150      if(_hasNullValue){
151        fq.append(") OR (");
152      }else{
153        fq.append(')');
154      }
155    }
156    
157    if(_hasNullValue){
158      fq.append("("+SolrQueryBuilder.QUERY_ALL+SOLR_AND+" "+SOLR_NEGATIVE_QUERY);
159      fq.append(_fieldName);
160      fq.append(SolrQueryBuilder.SEPARATOR_SOLR_FIELD_VALUE+"["+SolrQueryBuilder.SOLR_WILD_CARD+" TO "+SolrQueryBuilder.SOLR_WILD_CARD+"])");
161    }
162    
163    fq.append(')');
164  }
165
166  @Override
167  public QueryType getQueryType() {
168    return QueryType.OR;
169  }
170}