blob: 2354dc6386747047b8738c9237e3018f50e62822 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.solr.search.function;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.Bits;
import org.apache.solr.search.BitsFilteredDocIdSet;
import org.apache.solr.search.SolrFilter;
import java.io.IOException;
import java.util.Map;
/**
* RangeFilter over a ValueSource.
*/
public class ValueSourceRangeFilter extends SolrFilter {
private final ValueSource valueSource;
private final String lowerVal;
private final String upperVal;
private final boolean includeLower;
private final boolean includeUpper;
public ValueSourceRangeFilter(ValueSource valueSource,
String lowerVal,
String upperVal,
boolean includeLower,
boolean includeUpper) {
this.valueSource = valueSource;
this.lowerVal = lowerVal;
this.upperVal = upperVal;
this.includeLower = includeLower;
this.includeUpper = includeUpper;
// this.includeLower = lowerVal != null && includeLower;
// this.includeUpper = upperVal != null && includeUpper;
}
public ValueSource getValueSource() {
return valueSource;
}
public String getLowerVal() {
return lowerVal;
}
public String getUpperVal() {
return upperVal;
}
public boolean isIncludeLower() {
return includeLower;
}
public boolean isIncludeUpper() {
return includeUpper;
}
@Override
@SuppressWarnings({"rawtypes"})
public DocIdSet getDocIdSet(final Map context, final LeafReaderContext readerContext, Bits acceptDocs) throws IOException {
// NB the IndexSearcher parameter here can be null because Filter Weights don't
// actually use it.
Weight weight = createWeight(null, ScoreMode.COMPLETE, 1);
return BitsFilteredDocIdSet.wrap(new DocIdSet() {
@Override
public DocIdSetIterator iterator() throws IOException {
@SuppressWarnings({"unchecked"})
Scorer scorer = valueSource.getValues(context, readerContext).getRangeScorer(weight, readerContext, lowerVal, upperVal, includeLower, includeUpper);
return scorer == null ? null : scorer.iterator();
}
@Override
public Bits bits() {
return null; // don't use random access
}
@Override
public long ramBytesUsed() {
return 0L;
}
}, acceptDocs);
}
@Override
@SuppressWarnings({"unchecked"})
public void createWeight(@SuppressWarnings({"rawtypes"})Map context, IndexSearcher searcher) throws IOException {
valueSource.createWeight(context, searcher);
}
@Override
public String toString(String field) {
StringBuilder sb = new StringBuilder();
sb.append("frange(");
sb.append(valueSource);
sb.append("):");
sb.append(includeLower ? '[' : '{');
sb.append(lowerVal == null ? "*" : lowerVal);
sb.append(" TO ");
sb.append(upperVal == null ? "*" : upperVal);
sb.append(includeUpper ? ']' : '}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ValueSourceRangeFilter)) return false;
ValueSourceRangeFilter other = (ValueSourceRangeFilter)o;
if (!this.valueSource.equals(other.valueSource)
|| this.includeLower != other.includeLower
|| this.includeUpper != other.includeUpper
) { return false; }
if (this.lowerVal != null ? !this.lowerVal.equals(other.lowerVal) : other.lowerVal != null) return false;
if (this.upperVal != null ? !this.upperVal.equals(other.upperVal) : other.upperVal != null) return false;
return true;
}
@Override
public int hashCode() {
int h = valueSource.hashCode();
h += lowerVal != null ? lowerVal.hashCode() : 0x572353db;
h = (h << 16) | (h >>> 16); // rotate to distinguish lower from upper
h += (upperVal != null ? (upperVal.hashCode()) : 0xe16fe9e7);
h += (includeLower ? 0xdaa47978 : 0)
+ (includeUpper ? 0x9e634b57 : 0);
return h;
}
}