package com.manning.hsia.dvdstore.action.filter; import java.io.IOException; import java.util.BitSet; import java.util.Collections; import java.util.Map; import org.apache.commons.collections.map.ReferenceMap; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.Filter; import org.apache.lucene.util.DocIdBitSet; import org.hibernate.search.engine.DocumentBuilder; import com.manning.hsia.dvdstore.action.StockAction; import com.manning.hsia.dvdstore.action.StockActionImpl; import com.manning.hsia.dvdstore.model.Item; /** * Example 8.12 */ public class StockFilter extends Filter { private volatile long lastUpdateTime; //update timestamp @SuppressWarnings("unchecked") private final Map<IndexReader, DocIdSet> cache = Collections.synchronizedMap( new ReferenceMap(ReferenceMap.SOFT, ReferenceMap.HARD) ); //keep cache in a SoftHashMap @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { StockAction action = getStockAction(); //retrieve the service long lastUpdateTime = action.geLastUpdateTime(); if ( lastUpdateTime != this.lastUpdateTime ) { cache.clear(); //clear outdated cache } DocIdSet cached = cache.get( reader ); //check if in cache already if ( cached != null ) return cached; //not in cache, build info final BitSet bitSet = getAllPositiveBitSet( reader.maxDoc() ); //by default, all documents pass Term clazzTerm = new Term( DocumentBuilder.CLASS_FIELDNAME, Item.class.getName() ); if ( reader.docFreq( clazzTerm ) == 0) { //no need to filter //index does not contain Item objects //no-op } else { //for each item out of stock, find the corresponding document id by item id //and switch off the corresponding bit for ( String ean : action.getEanOfItemsOutOfStock() ) { //invoke external service Term term = new Term( "ean", ean ); TermDocs termDocs = reader.termDocs( term ); //find document by ean while ( termDocs.next() ) { bitSet.clear( termDocs.doc() ); } } } DocIdSet docIdSet = new DocIdBitSet( bitSet ); //build DocIdSet from BitSet cache.put( reader, docIdSet ); //put results in the cache this.lastUpdateTime = lastUpdateTime; //update timestamp return docIdSet; } private BitSet getAllPositiveBitSet(int maxDoc) { final BitSet bitSet = new BitSet( maxDoc ); bitSet.set( 0, maxDoc-1 ); //new BitSet with all bits on return bitSet; } private StockAction getStockAction() { return new StockActionImpl(); } }