/**
   * Merges the given taxonomy and index directories and commits the changes to the given writers.
   */
  public static void merge(
      Directory srcIndexDir,
      Directory srcTaxDir,
      OrdinalMap map,
      IndexWriter destIndexWriter,
      DirectoryTaxonomyWriter destTaxWriter)
      throws IOException {
    // merge the taxonomies
    destTaxWriter.addTaxonomy(srcTaxDir, map);

    int ordinalMap[] = map.getMap();
    FacetIndexingParams params = new DefaultFacetIndexingParams();

    DirectoryReader reader = DirectoryReader.open(srcIndexDir, -1);
    List<AtomicReaderContext> leaves = reader.leaves();
    AtomicReader wrappedLeaves[] = new AtomicReader[leaves.size()];
    for (int i = 0; i < leaves.size(); i++) {
      wrappedLeaves[i] = new OrdinalMappingAtomicReader(leaves.get(i).reader(), ordinalMap, params);
    }
    try {
      destIndexWriter.addIndexes(new MultiReader(wrappedLeaves));

      // commit changes to taxonomy and index respectively.
      destTaxWriter.commit();
      destIndexWriter.commit();
    } finally {
      reader.close();
    }
  }
  /** Build the example index. */
  private void index() throws IOException {
    IndexWriterConfig iwc =
        new IndexWriterConfig(new WhitespaceAnalyzer()).setOpenMode(OpenMode.CREATE);
    IndexWriter indexWriter = new IndexWriter(indexDir, iwc);

    // Writes facet ords to a separate directory from the main index
    DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);

    Document doc = new Document();
    // 3 occurrences for tag 'lucene'
    doc.add(new IntAssociationFacetField(3, "tags", "lucene"));
    // 87% confidence level of genre 'computing'
    doc.add(new FloatAssociationFacetField(0.87f, "genre", "computing"));
    indexWriter.addDocument(config.build(taxoWriter, doc));

    doc = new Document();
    // 1 occurrence for tag 'lucene'
    doc.add(new IntAssociationFacetField(1, "tags", "lucene"));
    // 2 occurrence for tag 'solr'
    doc.add(new IntAssociationFacetField(2, "tags", "solr"));
    // 75% confidence level of genre 'computing'
    doc.add(new FloatAssociationFacetField(0.75f, "genre", "computing"));
    // 34% confidence level of genre 'software'
    doc.add(new FloatAssociationFacetField(0.34f, "genre", "software"));
    indexWriter.addDocument(config.build(taxoWriter, doc));

    indexWriter.close();
    taxoWriter.close();
  }
 /**
  * Merges the given taxonomy and index directories. Note that this method opens {@link
  * DirectoryTaxonomyWriter} and {@link IndexWriter} on the respective destination indexes.
  * Therefore if you have a writer open on any of them, it should be closed, or you should use
  * {@link #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter)} instead.
  *
  * @see #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter)
  */
 public static void merge(
     Directory srcIndexDir, Directory srcTaxDir, Directory destIndexDir, Directory destTaxDir)
     throws IOException {
   IndexWriter destIndexWriter =
       new IndexWriter(destIndexDir, new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, null));
   DirectoryTaxonomyWriter destTaxWriter = new DirectoryTaxonomyWriter(destTaxDir);
   merge(srcIndexDir, srcTaxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter);
   destTaxWriter.close();
   destIndexWriter.close();
 }
  @Test
  public void testNRT() throws Exception {
    Directory dir = newDirectory();
    DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
    TaxonomyReader reader = new DirectoryTaxonomyReader(writer);

    FacetLabel cp = new FacetLabel("a");
    writer.addCategory(cp);
    TaxonomyReader newReader = TaxonomyReader.openIfChanged(reader);
    assertNotNull("expected a new instance", newReader);
    assertEquals(2, newReader.getSize());
    assertNotSame(TaxonomyReader.INVALID_ORDINAL, newReader.getOrdinal(cp));
    reader.close();
    reader = newReader;

    writer.close();
    reader.close();

    dir.close();
  }
 /**
  * Test what happens if we try to write to a locked taxonomy writer, and see that we can unlock it
  * and continue.
  */
 @Test
 public void testWriterLock() throws Exception {
   // native fslock impl gets angry if we use it, so use RAMDirectory explicitly.
   Directory indexDir = new RAMDirectory();
   TaxonomyWriter tw = new DirectoryTaxonomyWriter(indexDir);
   tw.addCategory(new FacetLabel("hi", "there"));
   tw.commit();
   // we deliberately not close the write now, and keep it open and
   // locked.
   // Verify that the writer worked:
   TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
   assertEquals(2, tr.getOrdinal(new FacetLabel("hi", "there")));
   // Try to open a second writer, with the first one locking the directory.
   // We expect to get a LockObtainFailedException.
   try {
     assertNull(new DirectoryTaxonomyWriter(indexDir));
     fail("should have failed to write in locked directory");
   } catch (LockObtainFailedException e) {
     // this is what we expect to happen.
   }
   // Remove the lock, and now the open should succeed, and we can
   // write to the new writer.
   DirectoryTaxonomyWriter.unlock(indexDir);
   TaxonomyWriter tw2 = new DirectoryTaxonomyWriter(indexDir);
   tw2.addCategory(new FacetLabel("hey"));
   tw2.close();
   // See that the writer indeed wrote:
   TaxonomyReader newtr = TaxonomyReader.openIfChanged(tr);
   assertNotNull(newtr);
   tr.close();
   tr = newtr;
   assertEquals(3, tr.getOrdinal(new FacetLabel("hey")));
   tr.close();
   tw.close();
   indexDir.close();
 }