Index: src/java/org/apache/lucene/search/CachingWrapperFilter.java
===================================================================
--- src/java/org/apache/lucene/search/CachingWrapperFilter.java	(revision 661395)
+++ src/java/org/apache/lucene/search/CachingWrapperFilter.java	(working copy)
@@ -22,10 +22,14 @@
 import java.util.WeakHashMap;
 import java.util.Map;
 import java.io.IOException;
+import org.apache.lucene.util.OpenBitSet;
+import org.apache.lucene.util.SortedVIntList;
 
 /**
  * Wraps another filter's result and caches it.  The purpose is to allow
  * filters to simply filter, and then wrap with this class to add caching.
+ * Instead of the DocIdSet returned by the filter, another
+ * DocIdSet may be cached.
  */
 public class CachingWrapperFilter extends Filter {
   protected Filter filter;
@@ -79,7 +83,8 @@
       }
     }
 
-    final DocIdSet docIdSet = filter.getDocIdSet(reader);
+    final DocIdSet docIdSet = docIdSetToCache(filter.getDocIdSet(reader),
+                                              reader.maxDoc());
 
     synchronized (cache) {  // update cache
       cache.put(reader, docIdSet);
@@ -89,6 +94,21 @@
     
   }
 
+  /** Provide the DocIdSet to be cached, using the DocIdSet provided
+   * by the wrapped Filter.
+   * This implementation uses an equivalent SortedVIntList when it is
+   * definitely smaller than a given OpenBitSet.
+   */
+  protected DocIdSet docIdSetToCache(DocIdSet docIdSet, int maxDocs) {
+    if (docIdSet instanceof OpenBitSet) {
+      OpenBitSet obs = (OpenBitSet) docIdSet;
+      if (obs.cardinality() < (maxDocs / 9)) {
+        return new SortedVIntList(obs);
+      }
+    }
+    return docIdSet;
+  }
+
   public String toString() {
     return "CachingWrapperFilter("+filter+")";
   }
Index: src/test/org/apache/lucene/search/TestCachingWrapperFilter.java
===================================================================
--- src/test/org/apache/lucene/search/TestCachingWrapperFilter.java	(revision 661395)
+++ src/test/org/apache/lucene/search/TestCachingWrapperFilter.java	(working copy)
@@ -22,16 +22,29 @@
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.document.Document;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.util.OpenBitSet;
+import org.apache.lucene.util.SortedVIntList;
 
 public class TestCachingWrapperFilter extends LuceneTestCase {
-  public void testCachingWorks() throws Exception {
+  IndexReader reader;
+
+  public void setUp() throws Exception {
     Directory dir = new RAMDirectory();
     IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
+    for (int i = 0; i < 10; i++) {
+      writer.addDocument(new Document());
+    }
     writer.close();
+    reader = IndexReader.open(dir);
+  }
 
-    IndexReader reader = IndexReader.open(dir);
-
+  public void tearDown() throws Exception {
+    reader.close();
+  }
+  
+  public void testCachingWorks() throws Exception {
     MockFilter filter = new MockFilter();
     CachingWrapperFilter cacher = new CachingWrapperFilter(filter);
 
@@ -43,7 +56,31 @@
     filter.clear();
     cacher.getDocIdSet(reader);
     assertFalse("second time", filter.wasCalled());
+ }
 
-    reader.close();
- }
+  public void testCachingSameDocIdSet() throws Exception {
+    class NonSparseBitSetFilter extends Filter {
+      public DocIdSet getDocIdSet(IndexReader reader) {
+        OpenBitSet obs = new OpenBitSet(reader.maxDoc());
+        obs.set(1);
+        obs.set(2);
+        return obs;  // two bits set, 10 docs in index.
+      }
+    }
+    CachingWrapperFilter cacher = new CachingWrapperFilter(new NonSparseBitSetFilter());
+    DocIdSet dis = cacher.getDocIdSet(reader);
+    assertTrue(dis.getClass().toString(), dis instanceof OpenBitSet);
+  }
+
+  public void testCachingOtherDocIdSet() throws Exception {
+    class EmptyBitSetFilter extends Filter {
+      public DocIdSet getDocIdSet(IndexReader reader) {
+        OpenBitSet obs = new OpenBitSet(reader.maxDoc());
+        return obs;  // no bits set, 10 docs in index.
+      }
+    }
+    CachingWrapperFilter cacher = new CachingWrapperFilter(new EmptyBitSetFilter());
+    DocIdSet dis = cacher.getDocIdSet(reader);
+    assertTrue(dis.getClass().toString(), dis instanceof SortedVIntList);
+  }
 }
Index: contrib/miscellaneous/src/java/org/apache/lucene/misc/ChainedFilter.java
===================================================================
--- contrib/miscellaneous/src/java/org/apache/lucene/misc/ChainedFilter.java	(revision 661395)
+++ contrib/miscellaneous/src/java/org/apache/lucene/misc/ChainedFilter.java	(working copy)
@@ -178,14 +178,6 @@
         return result;
     }
     
-    /** Provide a SortedVIntList when it is definitely smaller than an OpenBitSet */
-    protected DocIdSet finalResult(OpenBitSetDISI result, int maxDocs) {
-        return (result.cardinality() < (maxDocs / 9))
-              ? (DocIdSet) new SortedVIntList(result)
-              : (DocIdSet) result;
-    }
-        
-
     /**
      * Delegates to each filter in the chain.
      * @param reader IndexReader
@@ -200,7 +192,7 @@
         {
             doChain(result, logic, chain[index[0]].getDocIdSet(reader));
         }
-        return finalResult(result, reader.maxDoc());
+        return result;
     }
 
     /**
@@ -220,7 +212,7 @@
         {
             doChain(result, logic[index[0]], chain[index[0]].getDocIdSet(reader));
         }
-        return finalResult(result, reader.maxDoc());
+        return result;
     }
 
     public String toString()
Index: contrib/queries/src/java/org/apache/lucene/search/BooleanFilter.java
===================================================================
--- contrib/queries/src/java/org/apache/lucene/search/BooleanFilter.java	(revision 661395)
+++ contrib/queries/src/java/org/apache/lucene/search/BooleanFilter.java	(working copy)
@@ -109,7 +109,7 @@
     }
     
     if (res !=null)
-      return finalResult(res, reader.maxDoc());
+      return res;
 
     if (emptyDocIdSet == null)
       emptyDocIdSet = new OpenBitSetDISI(1);
@@ -117,13 +117,6 @@
     return emptyDocIdSet;
   }
 
-  /** Provide a SortedVIntList when it is definitely smaller than an OpenBitSet */
-  protected DocIdSet finalResult(OpenBitSetDISI result, int maxDocs) {
-    return (result.cardinality() < (maxDocs / 9))
-      ? (DocIdSet) new SortedVIntList(result)
-      : (DocIdSet) result;
-  }
-
   private static DocIdSet emptyDocIdSet = null;
 
   /**
