/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.search.filter.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.hibernate.annotations.common.AssertionFailure;
/**
* A Filter capable of chaining other filters, so that it's
* possible to apply several filters on a Query.
* <p>The resulting filter will only enable result Documents
* if no filter removed it.</p>
*
* @author Emmanuel Bernard
* @author Sanne Grinovero
* @author Hardy Ferentschik
*/
public class ChainedFilter extends Filter {
private static final long serialVersionUID = -6153052295766531920L;
private final List<Filter> chainedFilters = new ArrayList<Filter>();
/**
* Add the specified filter to the chain of filters
*
* @param filter the filter to add to the filter chain. Cannot be {@code null}.
*/
public void addFilter(Filter filter) {
if ( filter == null ) {
throw new IllegalArgumentException( "The specified filter cannot be null" );
}
this.chainedFilters.add( filter );
}
/**
* Returns the specified filter from the current filter chain.
*
* @param filter the filter to remove form the chaim
*
* @return {@code true} if this chained filter contained the specified filter, {@code false} otherwise.
*/
public boolean removeFilter(Filter filter) {
return this.chainedFilters.remove( filter );
}
public boolean isEmpty() {
return chainedFilters.size() == 0;
}
@Override
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
int size = chainedFilters.size();
if ( size == 0 ) {
throw new AssertionFailure( "No filters to chain" );
}
else if ( size == 1 ) {
return chainedFilters.get( 0 ).getDocIdSet( reader );
}
else {
List<DocIdSet> subSets = new ArrayList<DocIdSet>( size );
for ( Filter f : chainedFilters ) {
subSets.add( f.getDocIdSet( reader ) );
}
subSets = FilterOptimizationHelper.mergeByBitAnds( subSets );
if ( subSets.size() == 1 ) {
return subSets.get( 0 );
}
return new AndDocIdSet( subSets, reader.maxDoc() );
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "ChainedFilter" );
sb.append( "{chainedFilters=" ).append( chainedFilters );
sb.append( '}' );
return sb.toString();
}
}