From 0255424864dd206cc8815da35f3607a4970b284a Mon Sep 17 00:00:00 2001 From: Michael McCandless Date: Tue, 26 Nov 2013 00:12:57 +0000 Subject: [PATCH] LUCENE-5339: finish cutover git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene5339@1545466 13f79535-47bb-0310-9956-ffa450edef68 --- .../AssociationsDrillDownStream.java | 74 -- .../associations/AssociationsFacetFields.java | 124 --- .../associations/AssociationsListBuilder.java | 82 -- .../associations/CategoryAssociation.java | 48 -- .../CategoryAssociationsContainer.java | 65 -- .../CategoryFloatAssociation.java | 80 -- .../associations/CategoryIntAssociation.java | 80 -- .../SumFloatAssociationFacetRequest.java | 46 -- .../SumFloatAssociationFacetsAggregator.java | 92 --- .../SumIntAssociationFacetRequest.java | 46 -- .../SumIntAssociationFacetsAggregator.java | 91 --- .../lucene/facet/associations/package.html | 25 - .../facet/collections/ArrayHashMap.java | 554 ------------- .../facet/collections/DoubleIterator.java | 31 - .../facet/collections/FloatIterator.java | 31 - .../facet/collections/FloatToObjectMap.java | 634 --------------- .../lucene/facet/collections/IntArray.java | 252 ------ .../lucene/facet/collections/IntHashSet.java | 548 ------------- .../lucene/facet/collections/IntIterator.java | 31 - .../facet/collections/IntToDoubleMap.java | 631 --------------- .../facet/collections/IntToFloatMap.java | 631 --------------- .../lucene/facet/collections/IntToIntMap.java | 622 --------------- .../facet/collections/IntToObjectMap.java | 634 --------------- .../facet/collections/ObjectToFloatMap.java | 623 --------------- .../facet/collections/ObjectToIntMap.java | 622 --------------- .../lucene/facet/collections/package.html | 24 - .../facet/complements/TotalFacetCounts.java | 180 ----- .../complements/TotalFacetCountsCache.java | 299 ------- .../lucene/facet/complements/package.html | 27 - .../facet/encoding/ChunksIntEncoder.java | 115 --- .../lucene/facet/encoding/DGapIntDecoder.java | 52 -- .../lucene/facet/encoding/DGapIntEncoder.java | 67 -- .../facet/encoding/DGapVInt8IntDecoder.java | 67 -- .../facet/encoding/DGapVInt8IntEncoder.java | 89 --- .../facet/encoding/EightFlagsIntDecoder.java | 92 --- .../facet/encoding/EightFlagsIntEncoder.java | 96 --- .../facet/encoding/FourFlagsIntDecoder.java | 92 --- .../facet/encoding/FourFlagsIntEncoder.java | 102 --- .../lucene/facet/encoding/IntDecoder.java | 37 - .../lucene/facet/encoding/IntEncoder.java | 46 -- .../facet/encoding/IntEncoderFilter.java | 34 - .../facet/encoding/NOnesIntDecoder.java | 86 --- .../facet/encoding/NOnesIntEncoder.java | 114 --- .../facet/encoding/SimpleIntDecoder.java | 56 -- .../facet/encoding/SimpleIntEncoder.java | 59 -- .../facet/encoding/SortingIntEncoder.java | 54 -- .../encoding/UniqueValuesIntEncoder.java | 63 -- .../facet/encoding/VInt8IntDecoder.java | 64 -- .../facet/encoding/VInt8IntEncoder.java | 104 --- .../apache/lucene/facet/encoding/package.html | 24 - .../facet/index/CategoryListBuilder.java | 38 - .../facet/index/CountingListBuilder.java | 170 ---- .../lucene/facet/index/DrillDownStream.java | 83 -- .../lucene/facet/index/FacetFields.java | 194 ----- .../apache/lucene/facet/index/package.html | 24 - .../facet/old/AdaptiveFacetsAccumulator.java | 116 --- .../apache/lucene/facet/old/Aggregator.java | 48 -- .../old/ComplementCountingAggregator.java | 44 -- .../lucene/facet/old/CountingAggregator.java | 66 -- .../facet/old/MatchingDocsAsScoredDocIDs.java | 174 ----- .../facet/old/OldFacetsAccumulator.java | 457 ----------- .../apache/lucene/facet/old/ScoredDocIDs.java | 42 - .../facet/old/ScoredDocIDsIterator.java | 43 -- .../lucene/facet/old/ScoredDocIdsUtils.java | 446 ----------- .../lucene/facet/old/ScoringAggregator.java | 67 -- .../org/apache/lucene/facet/old/package.html | 24 - .../facet/params/CategoryListParams.java | 187 ----- .../facet/params/FacetIndexingParams.java | 180 ----- .../facet/params/FacetSearchParams.java | 93 --- .../params/PerDimensionIndexingParams.java | 96 --- .../params/PerDimensionOrdinalPolicy.java | 55 -- .../apache/lucene/facet/params/package.html | 25 - .../partitions/IntermediateFacetResult.java | 42 - .../PartitionsFacetResultsHandler.java | 137 ---- .../lucene/facet/partitions/package.html | 27 - .../facet/range/RangeFacetResultNode.java | 33 - .../apache/lucene/facet/range/package.html | 24 - .../lucene/facet/sampling/RandomSampler.java | 71 -- .../facet/sampling/RepeatableSampler.java | 405 ---------- .../lucene/facet/sampling/SampleFixer.java | 73 -- .../apache/lucene/facet/sampling/Sampler.java | 216 ------ .../facet/sampling/SamplingAccumulator.java | 137 ---- .../lucene/facet/sampling/SamplingParams.java | 196 ----- .../facet/sampling/SamplingWrapper.java | 112 --- .../facet/sampling/TakmiSampleFixer.java | 168 ---- .../apache/lucene/facet/sampling/package.html | 24 - .../lucene/facet/search/ArraysPool.java | 110 --- .../CachedOrdsCountingFacetsAggregator.java | 54 -- .../facet/search/CategoryListIterator.java | 56 -- .../facet/search/CountFacetRequest.java | 39 - .../search/CountingFacetsAggregator.java | 72 -- .../search/DepthOneFacetResultsHandler.java | 136 ---- .../search/DocValuesCategoryListIterator.java | 87 --- .../lucene/facet/search/DrillDownQuery.java | 222 ------ .../facet/search/DrillSidewaysCollector.java | 188 ----- .../facet/search/DrillSidewaysQuery.java | 195 ----- .../facet/search/DrillSidewaysScorer.java | 654 ---------------- .../lucene/facet/search/FacetArrays.java | 83 -- .../lucene/facet/search/FacetRequest.java | 212 ----- .../lucene/facet/search/FacetResult.java | 117 --- .../lucene/facet/search/FacetResultNode.java | 107 --- .../facet/search/FacetResultsHandler.java | 48 -- .../facet/search/FacetsAccumulator.java | 101 --- .../lucene/facet/search/FacetsAggregator.java | 56 -- .../lucene/facet/search/FacetsCollector.java | 249 ------ .../search/FastCountingFacetsAggregator.java | 80 -- .../org/apache/lucene/facet/search/Heap.java | 56 -- .../search/IntRollupFacetsAggregator.java | 69 -- .../facet/search/MultiFacetsAccumulator.java | 69 -- .../facet/search/MultiFacetsAggregator.java | 96 --- .../facet/search/OrdinalValueResolver.java | 76 -- .../lucene/facet/search/OrdinalsCache.java | 149 ---- .../search/PerCategoryListAggregator.java | 71 -- .../facet/search/ReusingFacetArrays.java | 51 -- .../facet/search/SumScoreFacetRequest.java | 41 - .../search/SumScoreFacetsAggregator.java | 86 --- .../search/SumValueSourceFacetRequest.java | 194 ----- .../search/TaxonomyFacetsAccumulator.java | 218 ------ .../facet/search/TopKFacetResultsHandler.java | 276 ------- .../facet/search/TopKInEachNodeHandler.java | 727 ------------------ .../apache/lucene/facet/search/package.html | 24 - .../facet/{range => simple}/DoubleRange.java | 2 +- .../lucene/facet/simple/FacetField.java | 4 +- .../facet/{range => simple}/FloatRange.java | 2 +- .../facet/{range => simple}/LongRange.java | 2 +- .../lucene/facet/{range => simple}/Range.java | 2 +- .../lucene/facet/simple/RangeFacetCounts.java | 1 - .../SearcherTaxonomyManager.java | 2 +- .../facet/simple/SimpleDrillDownQuery.java | 1 - .../facet/simple/SimpleDrillSideways.java | 3 - .../facet/simple/SimpleFacetsCollector.java | 1 - .../simple/SortedSetDocValuesReaderState.java | 2 - .../lucene/facet/sortedset/package.html | 24 - .../{collections => taxonomy}/LRUHashMap.java | 8 +- .../PrintTaxonomyStats.java | 4 +- .../directory/DirectoryTaxonomyReader.java | 2 +- .../util/FacetsPayloadMigrationReader.java | 265 ------- .../util/OrdinalMappingAtomicReader.java | 146 ---- .../lucene/facet/util/PartitionsUtils.java | 71 -- .../lucene/facet/util/ResultSortUtils.java | 164 ---- .../lucene/facet/util/TaxonomyMergeUtils.java | 66 -- .../org/apache/lucene/facet/util/package.html | 24 - .../apache/lucene/facet/FacetTestBase.java | 362 --------- .../apache/lucene/facet/FacetTestCase.java | 66 +- .../apache/lucene/facet/FacetTestUtils.java | 38 - .../facet/collections/ArrayHashMapTest.java | 268 ------- .../collections/FloatToObjectMapTest.java | 267 ------- .../facet/collections/IntArrayTest.java | 125 --- .../facet/collections/IntHashSetTest.java | 223 ------ .../facet/collections/IntToDoubleMapTest.java | 272 ------- .../facet/collections/IntToFloatMapTest.java | 272 ------- .../facet/collections/IntToIntMapTest.java | 272 ------- .../facet/collections/IntToObjectMapTest.java | 267 ------- .../collections/ObjectToFloatMapTest.java | 279 ------- .../facet/collections/ObjectToIntMapTest.java | 277 ------- .../TestFacetsAccumulatorWithComplement.java | 135 ---- .../complements/TestTotalFacetCounts.java | 130 ---- .../TestTotalFacetCountsCache.java | 503 ------------ .../lucene/facet/encoding/EncodingSpeed.java | 649 ---------------- .../lucene/facet/encoding/EncodingTest.java | 170 ---- .../facet/old/AdaptiveAccumulatorTest.java | 38 - .../facet/old/TestScoredDocIDsUtils.java | 154 ---- .../facet/sampling/BaseSampleTestTopK.java | 149 ---- .../sampling/OversampleWithDepthTest.java | 124 --- .../lucene/facet/sampling/SamplerTest.java | 111 --- .../sampling/SamplingAccumulatorTest.java | 34 - .../facet/sampling/SamplingWrapperTest.java | 35 - .../AssertingSubDocsAtOnceCollector.java | 67 -- .../lucene/facet/search/BaseTestTopK.java | 112 --- .../TestTopKInEachNodeResultHandler.java | 304 -------- .../facet/search/TestTopKResultsHandler.java | 211 ----- .../search/TestTopKResultsHandlerRandom.java | 130 ---- .../simple/TestCachedOrdinalsReader.java | 2 - .../facet/simple/TestDrillDownQuery.java | 4 - .../facet/simple/TestMultipleIndexFields.java | 6 - .../lucene/facet/simple/TestRangeFacets.java | 14 - .../simple/TestSearcherTaxonomyManager.java | 9 +- .../facet/simple/TestSimpleDrillSideways.java | 2 - .../facet/simple/TestTaxonomyFacetCounts.java | 2 +- .../simple/TestTaxonomyFacetCounts2.java | 45 +- .../TestTaxonomyFacetSumValueSource.java | 2 +- .../TestLRUHashMap.java | 10 +- .../TestConcurrentFacetedIndexing.java | 30 +- .../TestDirectoryTaxonomyWriter.java | 44 +- .../util/AssertingCategoryListIterator.java | 65 -- .../facet/util/OrdinalMappingReaderTest.java | 123 --- .../TestFacetsPayloadMigrationReader.java | 412 ---------- 187 files changed, 92 insertions(+), 25664 deletions(-) delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsDrillDownStream.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsFacetFields.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsListBuilder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociation.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociationsContainer.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryFloatAssociation.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryIntAssociation.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/associations/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/ArrayHashMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/DoubleIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/FloatIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/FloatToObjectMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntArray.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntHashSet.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntToDoubleMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntToFloatMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntToIntMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/IntToObjectMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToFloatMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToIntMap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/collections/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCounts.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCountsCache.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/complements/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/ChunksIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/IntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoderFilter.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/SortingIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/UniqueValuesIntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntDecoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntEncoder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/encoding/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/index/CategoryListBuilder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/index/DrillDownStream.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/index/FacetFields.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/index/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/AdaptiveFacetsAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/Aggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/ComplementCountingAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/CountingAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/MatchingDocsAsScoredDocIDs.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/OldFacetsAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDs.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDsIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIdsUtils.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/ScoringAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/old/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/CategoryListParams.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/FacetIndexingParams.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionIndexingParams.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionOrdinalPolicy.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/params/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/partitions/IntermediateFacetResult.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/partitions/PartitionsFacetResultsHandler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/partitions/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetResultNode.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/range/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/RandomSampler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/RepeatableSampler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/SampleFixer.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingParams.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingWrapper.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/TakmiSampleFixer.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sampling/package.html delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/ArraysPool.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/CachedOrdsCountingFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/CategoryListIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DocValuesCategoryListIterator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DrillDownQuery.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysCollector.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysQuery.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetArrays.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultNode.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultsHandler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/Heap.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/IntRollupFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalValueResolver.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalsCache.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/ReusingFacetArrays.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetsAggregator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/SumValueSourceFacetRequest.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/search/package.html rename lucene/facet/src/java/org/apache/lucene/facet/{range => simple}/DoubleRange.java (98%) rename lucene/facet/src/java/org/apache/lucene/facet/{range => simple}/FloatRange.java (98%) rename lucene/facet/src/java/org/apache/lucene/facet/{range => simple}/LongRange.java (97%) rename lucene/facet/src/java/org/apache/lucene/facet/{range => simple}/Range.java (96%) rename lucene/facet/src/java/org/apache/lucene/facet/{search => simple}/SearcherTaxonomyManager.java (99%) delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/sortedset/package.html rename lucene/facet/src/java/org/apache/lucene/facet/{collections => taxonomy}/LRUHashMap.java (99%) rename lucene/facet/src/java/org/apache/lucene/facet/{util => taxonomy}/PrintTaxonomyStats.java (96%) delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/FacetsPayloadMigrationReader.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/OrdinalMappingAtomicReader.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/PartitionsUtils.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/ResultSortUtils.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java delete mode 100644 lucene/facet/src/java/org/apache/lucene/facet/util/package.html delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/ArrayHashMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/FloatToObjectMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntArrayTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntHashSetTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntToDoubleMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntToFloatMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntToIntMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/IntToObjectMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToFloatMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToIntMapTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/complements/TestFacetsAccumulatorWithComplement.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCounts.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCountsCache.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingSpeed.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/old/AdaptiveAccumulatorTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/old/TestScoredDocIDsUtils.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/sampling/BaseSampleTestTopK.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/sampling/OversampleWithDepthTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplerTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingAccumulatorTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingWrapperTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java rename lucene/facet/src/test/org/apache/lucene/facet/{collections => taxonomy}/TestLRUHashMap.java (95%) delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/util/AssertingCategoryListIterator.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/util/OrdinalMappingReaderTest.java delete mode 100644 lucene/facet/src/test/org/apache/lucene/facet/util/TestFacetsPayloadMigrationReader.java diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsDrillDownStream.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsDrillDownStream.java deleted file mode 100644 index 839bcbb67d5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsDrillDownStream.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.apache.lucene.facet.associations; - -import org.apache.lucene.analysis.tokenattributes.PayloadAttribute; -import org.apache.lucene.facet.index.DrillDownStream; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.store.ByteArrayDataOutput; -import org.apache.lucene.util.BytesRef; - -/* - * 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. - */ - -/** - * A {@link DrillDownStream} which adds to each drill-down token a - * payload according to the {@link CategoryAssociation} defined in the - * {@link CategoryAssociationsContainer}. - * - * @lucene.experimental - */ -public class AssociationsDrillDownStream extends DrillDownStream { - - private final PayloadAttribute payloadAttribute; - private final BytesRef payload; - private final ByteArrayDataOutput output = new ByteArrayDataOutput(); - private final CategoryAssociationsContainer associations; - - public AssociationsDrillDownStream(CategoryAssociationsContainer associations, FacetIndexingParams indexingParams) { - super(associations, indexingParams); - this.associations = associations; - payloadAttribute = addAttribute(PayloadAttribute.class); - BytesRef bytes = payloadAttribute.getPayload(); - if (bytes == null) { - bytes = new BytesRef(new byte[4]); - payloadAttribute.setPayload(bytes); - } - bytes.offset = 0; - this.payload = bytes; - } - - @Override - protected void addAdditionalAttributes(FacetLabel cp, boolean isParent) { - if (isParent) { - return; // associations are not added to parent categories - } - - CategoryAssociation association = associations.getAssociation(cp); - if (association == null) { - // it is ok to set a null association for a category - it's treated as a - // regular category in that case. - return; - } - if (payload.bytes.length < association.maxBytesNeeded()) { - payload.grow(association.maxBytesNeeded()); - } - output.reset(payload.bytes); - association.serialize(output); - payload.length = output.getPosition(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsFacetFields.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsFacetFields.java deleted file mode 100644 index b5964161c7c..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsFacetFields.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.lucene.document.Document; -import org.apache.lucene.document.FieldType; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.index.DrillDownStream; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.index.FieldInfo.IndexOptions; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A utility class for adding facet fields to a document. Usually one field will - * be added for all facets, however per the - * {@link FacetIndexingParams#getCategoryListParams(FacetLabel)}, one field - * may be added for every group of facets. - * - * @lucene.experimental - */ -public class AssociationsFacetFields extends FacetFields { - - // The drill-down field is added with a TokenStream, hence why it's based on - // TextField type. However for associations, we store a payload with the - // association value, therefore we set IndexOptions to include positions. - private static final FieldType DRILL_DOWN_TYPE = new FieldType(TextField.TYPE_NOT_STORED); - static { - DRILL_DOWN_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); - DRILL_DOWN_TYPE.freeze(); - } - - /** - * Constructs a new instance with the {@link FacetIndexingParams#DEFAULT - * default} facet indexing params. - * - * @param taxonomyWriter - * used to resolve given categories to ordinals - */ - public AssociationsFacetFields(TaxonomyWriter taxonomyWriter) { - super(taxonomyWriter); - } - - /** - * Constructs a new instance with the given facet indexing params. - * - * @param taxonomyWriter - * used to resolve given categories to ordinals - * @param params - * determines under which fields the categories should be indexed - */ - public AssociationsFacetFields(TaxonomyWriter taxonomyWriter, FacetIndexingParams params) { - super(taxonomyWriter, params); - } - - @Override - protected Map> createCategoryListMapping( - Iterable categories) { - CategoryAssociationsContainer categoryAssociations = (CategoryAssociationsContainer) categories; - HashMap> categoryLists = - new HashMap>(); - for (FacetLabel cp : categories) { - // each category may be indexed under a different field, so add it to the right list. - CategoryListParams clp = indexingParams.getCategoryListParams(cp); - CategoryAssociationsContainer clpContainer = (CategoryAssociationsContainer) categoryLists.get(clp); - if (clpContainer == null) { - clpContainer = new CategoryAssociationsContainer(); - categoryLists.put(clp, clpContainer); - } - clpContainer.setAssociation(cp, categoryAssociations.getAssociation(cp)); - } - return categoryLists; - } - - @Override - protected Map getCategoryListData(CategoryListParams categoryListParams, IntsRef ordinals, - Iterable categories) throws IOException { - AssociationsListBuilder associations = new AssociationsListBuilder((CategoryAssociationsContainer) categories); - return associations.build(ordinals, categories); - } - - @Override - protected DrillDownStream getDrillDownStream(Iterable categories) { - return new AssociationsDrillDownStream((CategoryAssociationsContainer) categories, indexingParams); - } - - @Override - protected FieldType drillDownFieldType() { - return DRILL_DOWN_TYPE; - } - - @Override - public void addFields(Document doc, Iterable categories) throws IOException { - if (!(categories instanceof CategoryAssociationsContainer)) { - throw new IllegalArgumentException("categories must be of type " + - CategoryAssociationsContainer.class.getSimpleName()); - } - super.addFields(doc, categories); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsListBuilder.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsListBuilder.java deleted file mode 100644 index c5adf49e646..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationsListBuilder.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.lucene.facet.index.CategoryListBuilder; -import org.apache.lucene.facet.index.CountingListBuilder; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.store.ByteArrayDataOutput; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link AssociationsListBuilder} which encodes category-association value pairs. - * Every category-association pair is written under the respective association's - * {@link CategoryAssociation#getCategoryListID()}. - *

- * NOTE: associations list do not encode the counting list data. You - * should use {@link CountingListBuilder} to build that information and then - * merge the results of both {@link #build(IntsRef, Iterable)}. - */ -public class AssociationsListBuilder implements CategoryListBuilder { - - private final CategoryAssociationsContainer associations; - private final ByteArrayDataOutput output = new ByteArrayDataOutput(); - - public AssociationsListBuilder(CategoryAssociationsContainer associations) { - this.associations = associations; - } - - @Override - public Map build(IntsRef ordinals, Iterable categories) throws IOException { - final HashMap res = new HashMap(); - int idx = 0; - for (FacetLabel cp : categories) { - // build per-association key BytesRef - CategoryAssociation association = associations.getAssociation(cp); - - BytesRef bytes = res.get(association.getCategoryListID()); - if (bytes == null) { - bytes = new BytesRef(32); - res.put(association.getCategoryListID(), bytes); - } - - int maxBytesNeeded = 4 /* int */ + association.maxBytesNeeded() + bytes.length; - if (bytes.bytes.length < maxBytesNeeded) { - bytes.grow(maxBytesNeeded); - } - - // reset the output to write from bytes.length (current position) until the end - output.reset(bytes.bytes, bytes.length, bytes.bytes.length - bytes.length); - output.writeInt(ordinals.ints[idx++]); - - // encode the association bytes - association.serialize(output); - - // update BytesRef - bytes.length = output.getPosition(); - } - - return res; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociation.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociation.java deleted file mode 100644 index ba34fcbdeac..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociation.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.apache.lucene.facet.associations; - -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.store.ByteArrayDataInput; -import org.apache.lucene.store.ByteArrayDataOutput; -import org.apache.lucene.store.DataInput; -import org.apache.lucene.store.DataOutput; - -/* - * 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. - */ - -/** - * Allows associating an arbitrary value with a {@link FacetLabel}. - * - * @lucene.experimental - */ -public interface CategoryAssociation { - - /** Serializes the associated value into the given {@link DataOutput}. */ - public void serialize(ByteArrayDataOutput output); - - /** Deserializes the association value from the given {@link DataInput}. */ - public void deserialize(ByteArrayDataInput input); - - /** Returns the maximum bytes needed to encode the association value. */ - public int maxBytesNeeded(); - - /** - * Returns the ID of the category association. The ID is used as e.g. the - * term's text under which to encode the association values. - */ - public String getCategoryListID(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociationsContainer.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociationsContainer.java deleted file mode 100644 index 11bde976caa..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryAssociationsContainer.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.util.HashMap; -import java.util.Iterator; - -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** Holds {@link CategoryAssociation} per {@link FacetLabel}. */ -public class CategoryAssociationsContainer implements Iterable { - - private final HashMap categoryAssociations = - new HashMap(); - - /** - * Adds the {@link CategoryAssociation} for the given {@link FacetLabel - * category}. Overrides any assocation that was previously set. - */ - public void setAssociation(FacetLabel category, CategoryAssociation association) { - if (association == null) { - throw new IllegalArgumentException("cannot set a null association to a category"); - } - categoryAssociations.put(category, association); - } - - /** - * Returns the {@link CategoryAssociation} that was set for the - * {@link FacetLabel category}, or {@code null} if none was defined. - */ - public CategoryAssociation getAssociation(FacetLabel category) { - return categoryAssociations.get(category); - } - - @Override - public Iterator iterator() { - return categoryAssociations.keySet().iterator(); - } - - /** Clears all category associations. */ - public void clear() { - categoryAssociations.clear(); - } - - @Override - public String toString() { - return categoryAssociations.toString(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryFloatAssociation.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryFloatAssociation.java deleted file mode 100644 index 459e523e15d..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryFloatAssociation.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; - -import org.apache.lucene.store.ByteArrayDataInput; -import org.apache.lucene.store.ByteArrayDataOutput; - -/* - * 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. - */ - -/** A {@link CategoryAssociation} that associates a float with a category. */ -public class CategoryFloatAssociation implements CategoryAssociation { - - public static final String ASSOCIATION_LIST_ID = "$assoc_float$"; - - private float value; - - public CategoryFloatAssociation() { - // used for deserialization - } - - public CategoryFloatAssociation(float value) { - this.value = value; - } - - @Override - public void serialize(ByteArrayDataOutput output) { - try { - output.writeInt(Float.floatToIntBits(value)); - } catch (IOException e) { - throw new RuntimeException("unexpected exception writing to a byte[]", e); - } - } - - @Override - public void deserialize(ByteArrayDataInput input) { - value = Float.intBitsToFloat(input.readInt()); - } - - @Override - public int maxBytesNeeded() { - // plain integer - return 4; - } - - @Override - public String getCategoryListID() { - return ASSOCIATION_LIST_ID; - } - - /** - * Returns the value associated with a category. If you used - * {@link #CategoryFloatAssociation()}, you should call - * {@link #deserialize(ByteArrayDataInput)} before calling this method, or - * otherwise the value returned is undefined. - */ - public float getValue() { - return value; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "(" + value + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryIntAssociation.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryIntAssociation.java deleted file mode 100644 index 1d3b691b0d3..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/CategoryIntAssociation.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; - -import org.apache.lucene.store.ByteArrayDataInput; -import org.apache.lucene.store.ByteArrayDataOutput; - -/* - * 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. - */ - -/** A {@link CategoryAssociation} that associates an integer with a category. */ -public class CategoryIntAssociation implements CategoryAssociation { - - public static final String ASSOCIATION_LIST_ID = "$assoc_int$"; - - private int value; - - public CategoryIntAssociation() { - // used for deserialization - } - - public CategoryIntAssociation(int value) { - this.value = value; - } - - @Override - public void serialize(ByteArrayDataOutput output) { - try { - output.writeInt(value); - } catch (IOException e) { - throw new RuntimeException("unexpected exception writing to a byte[]", e); - } - } - - @Override - public void deserialize(ByteArrayDataInput input) { - value = input.readInt(); - } - - @Override - public int maxBytesNeeded() { - // plain integer - return 4; - } - - @Override - public String getCategoryListID() { - return ASSOCIATION_LIST_ID; - } - - /** - * Returns the value associated with a category. If you used - * {@link #CategoryIntAssociation()}, you should call - * {@link #deserialize(ByteArrayDataInput)} before calling this method, or - * otherwise the value returned is undefined. - */ - public int getValue() { - return value; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "(" + value + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java deleted file mode 100644 index 87363895bb1..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.apache.lucene.facet.associations; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link FacetRequest} for weighting facets according to their float - * association by summing the association values. - * - * @lucene.experimental - */ -public class SumFloatAssociationFacetRequest extends FacetRequest { - - /** - * Create a float association facet request for a given node in the - * taxonomy. - */ - public SumFloatAssociationFacetRequest(FacetLabel path, int num) { - super(path, num); - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - return new SumFloatAssociationFacetsAggregator(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetsAggregator.java deleted file mode 100644 index 741a5cc4ab8..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetsAggregator.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver; -import org.apache.lucene.facet.search.OrdinalValueResolver.FloatValueResolver; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.util.BytesRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which computes the weight of a category as the sum - * of the float values associated with it in the result documents. Assumes that - * the association encoded for each ordinal is {@link CategoryFloatAssociation}. - *

- * NOTE: this aggregator does not support - * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)}. It only - * aggregates the categories for which you added a {@link CategoryAssociation}. - * - * @lucene.experimental - */ -public class SumFloatAssociationFacetsAggregator implements FacetsAggregator { - - private final BytesRef bytes = new BytesRef(32); - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - BinaryDocValues dv = matchingDocs.context.reader().getBinaryDocValues(clp.field + CategoryFloatAssociation.ASSOCIATION_LIST_ID); - if (dv == null) { - return; // no float associations in this reader - } - - final int length = matchingDocs.bits.length(); - final float[] values = facetArrays.getFloatArray(); - int doc = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - dv.get(doc, bytes); - if (bytes.length > 0) { - // aggreate float association values for ordinals - int bytesUpto = bytes.offset + bytes.length; - int pos = bytes.offset; - while (pos < bytesUpto) { - int ordinal = ((bytes.bytes[pos++] & 0xFF) << 24) | ((bytes.bytes[pos++] & 0xFF) << 16) - | ((bytes.bytes[pos++] & 0xFF) << 8) | (bytes.bytes[pos++] & 0xFF); - - int value = ((bytes.bytes[pos++] & 0xFF) << 24) | ((bytes.bytes[pos++] & 0xFF) << 16) - | ((bytes.bytes[pos++] & 0xFF) << 8) | (bytes.bytes[pos++] & 0xFF); - - values[ordinal] += Float.intBitsToFloat(value); - } - } - ++doc; - } - } - - @Override - public boolean requiresDocScores() { - return false; - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - // NO-OP: this aggregator does no rollup values to the parents. - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return new FloatValueResolver(arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java deleted file mode 100644 index da54eeeaa29..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.apache.lucene.facet.associations; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link FacetRequest} for weighting facets according to their integer - * association by summing the association values. - * - * @lucene.experimental - */ -public class SumIntAssociationFacetRequest extends FacetRequest { - - /** - * Create an integer association facet request for a given node in the - * taxonomy. - */ - public SumIntAssociationFacetRequest(FacetLabel path, int num) { - super(path, num); - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - return new SumIntAssociationFacetsAggregator(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetsAggregator.java deleted file mode 100644 index e72a9501c8e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetsAggregator.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.apache.lucene.facet.associations; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver; -import org.apache.lucene.facet.search.OrdinalValueResolver.IntValueResolver; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.util.BytesRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which computes the weight of a category as the sum - * of the integer values associated with it in the result documents. Assumes - * that the association encoded for each ordinal is - * {@link CategoryIntAssociation}. - *

- * NOTE: this aggregator does not support - * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)}. It only - * aggregates the categories for which you added a {@link CategoryAssociation}. - */ -public class SumIntAssociationFacetsAggregator implements FacetsAggregator { - - private final BytesRef bytes = new BytesRef(32); - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - BinaryDocValues dv = matchingDocs.context.reader().getBinaryDocValues(clp.field + CategoryIntAssociation.ASSOCIATION_LIST_ID); - if (dv == null) { - return; // no int associations in this reader - } - - final int length = matchingDocs.bits.length(); - final int[] values = facetArrays.getIntArray(); - int doc = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - dv.get(doc, bytes); - if (bytes.length > 0) { - // aggregate association values for ordinals - int bytesUpto = bytes.offset + bytes.length; - int pos = bytes.offset; - while (pos < bytesUpto) { - int ordinal = ((bytes.bytes[pos++] & 0xFF) << 24) | ((bytes.bytes[pos++] & 0xFF) << 16) - | ((bytes.bytes[pos++] & 0xFF) << 8) | (bytes.bytes[pos++] & 0xFF); - - int value = ((bytes.bytes[pos++] & 0xFF) << 24) | ((bytes.bytes[pos++] & 0xFF) << 16) - | ((bytes.bytes[pos++] & 0xFF) << 8) | (bytes.bytes[pos++] & 0xFF); - - values[ordinal] += value; - } - } - ++doc; - } - } - - @Override - public boolean requiresDocScores() { - return false; - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - // NO-OP: this aggregator does no rollup values to the parents. - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return new IntValueResolver(arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/associations/package.html b/lucene/facet/src/java/org/apache/lucene/facet/associations/package.html deleted file mode 100644 index e20828c22bf..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/associations/package.html +++ /dev/null @@ -1,25 +0,0 @@ - - - -Category Association - - -Allows associating arbitrary values with a category. The value can be used e.g. to compute -the category's weight during faceted search. - - diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/ArrayHashMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/ArrayHashMap.java deleted file mode 100644 index 93fe9e1d914..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/ArrayHashMap.java +++ /dev/null @@ -1,554 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; -import java.util.Iterator; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps, similar to Java's HashMap, only - * performance tests showed it performs better. - *

- * The hashtable is constructed with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows. Capacity is - * adjusted to a power of 2, and there are 2 * capacity entries for the hash. - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * where index 0 is used as 'Ground' or 'NULL'. - *

- * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the <key,value> pair is allocated. - * - * @lucene.experimental - */ -public class ArrayHashMap implements Iterable { - - /** Implements an IntIterator which iterates over all the allocated indexes. */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** The next not-yet-visited index. */ - private int index = 0; - - /** Index of the last visited pair. Used in {@link #remove()}. */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return index != 0; - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - @SuppressWarnings("unchecked") - public void remove() { - ArrayHashMap.this.remove((K) keys[lastIndex]); - } - - } - - /** Implements an Iterator, used for iteration over the map's keys. */ - private final class KeyIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public K next() { - return (K) keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** Implements an Iterator, used for iteration over the map's values. */ - private final class ValueIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public V next() { - return (V) values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** Default capacity - in case no capacity was specified in the constructor */ - private static final int DEFAULT_CAPACITY = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** hashFactor is always (2^(N+1)) - 1. Used for faster hashing. */ - private int hashFactor; - - /** Holds the unique keys. */ - Object[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** Number of currently stored objects in the map. */ - private int size; - - /** Holds the values. */ - Object[] values; - - /** Constructs a map with default capacity. */ - public ArrayHashMap() { - this(DEFAULT_CAPACITY); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity minimum capacity for the map. - */ - public ArrayHashMap(int capacity) { - this.capacity = 16; - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - values = new Object[arrayLength]; - keys = new Object[arrayLength]; - next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - hashFactor = baseHashSize - 1; - - size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. New pairs are always - * inserted to baseHash, and are followed by the old colliding pair. - */ - private void prvt_put(K key, V value) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = value; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** Calculating the baseHash index using the internal internal hashFactor. */ - protected int calcBaseHashIndex(K key) { - return key.hashCode() & hashFactor; - } - - /** Empties the map. Generates the "Empty" space list for later allocation. */ - public void clear() { - // Clears the hash entries - Arrays.fill(baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[capacity] = 0; - } - - /** Returns true iff the key exists in the map. */ - public boolean containsKey(K key) { - return find(key) != 0; - } - - /** Returns true iff the object exists in the map. */ - public boolean containsValue(Object o) { - for (Iterator iterator = iterator(); iterator.hasNext();) { - V object = iterator.next(); - if (object.equals(o)) { - return true; - } - } - return false; - } - - /** Returns the index of the given key, or zero if the key wasn't found. */ - protected int find(K key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex].equals(key)) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Finds the actual index of a given key with it's baseHashIndex. Some methods - * use the baseHashIndex. If those call {@link #find} there's no need to - * re-calculate that hash. - * - * @return the index of the given key, or 0 if the key wasn't found. - */ - private int findForRemove(K key, int baseHashIndex) { - // Start from the hash entry. - prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index].equals(key)) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got thus far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return prev = 0; - } - - /** Returns the object mapped with the given key, or null if the key wasn't found. */ - @SuppressWarnings("unchecked") - public V get(K key) { - return (V) values[find(key)]; - } - - /** - * Allocates a new map of double the capacity, and fast-insert the old - * key-value pairs. - */ - @SuppressWarnings("unchecked") - protected void grow() { - ArrayHashMap newmap = new ArrayHashMap(capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - newmap.prvt_put((K) keys[index], (V) values[index]); - } - - // Copy that's data into this. - capacity = newmap.capacity; - size = newmap.size; - firstEmpty = newmap.firstEmpty; - values = newmap.values; - keys = newmap.keys; - next = newmap.next; - baseHash = newmap.baseHash; - hashFactor = newmap.hashFactor; - } - - /** Returns true iff the map is empty. */ - public boolean isEmpty() { - return size == 0; - } - - /** Returns an iterator on the mapped objects. */ - @Override - public Iterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public Iterator keyIterator() { - return new KeyIterator(); - } - - /** Prints the baseHash array, used for debugging purposes. */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or null if the key didn't exist. - */ - @SuppressWarnings("unchecked") - public V put(K key, V e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - V old = (V) values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return null; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or null if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or null if none existed. - */ - @SuppressWarnings("unchecked") - public V remove(K key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return (V) values[index]; - } - - return null; - } - - /** Returns number of pairs currently in the map. */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public Object[] toArray() { - int j = -1; - Object[] array = new Object[size]; - - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of V - * - * @param a the array into which the elements of the list are to be stored, if - * it is big enough; otherwise, use as much space as it can. - * @return an array containing the elements of the list - */ - public V[] toArray(V[] a) { - int j = 0; - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - if (j < a.length) { - a[j] = null; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - Iterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - K key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object o) { - ArrayHashMap that = (ArrayHashMap)o; - if (that.size() != this.size()) { - return false; - } - - Iterator it = keyIterator(); - while (it.hasNext()) { - K key = it.next(); - V v1 = this.get(key); - V v2 = that.get(key); - if ((v1 == null && v2 != null) || - (v1 != null && v2 == null) || - (!v1.equals(v2))) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/DoubleIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/DoubleIterator.java deleted file mode 100644 index 00a0e730c4a..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/DoubleIterator.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.lucene.facet.collections; - -/* - * 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. - */ - -/** - * Iterator interface for primitive double iteration. * - * - * @lucene.experimental - */ -public interface DoubleIterator { - - boolean hasNext(); - double next(); - void remove(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatIterator.java deleted file mode 100644 index 677b6fa9bb0..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatIterator.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.lucene.facet.collections; - -/* - * 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. - */ - -/** - * Iterator interface for primitive int iteration. * - * - * @lucene.experimental - */ -public interface FloatIterator { - - boolean hasNext(); - float next(); - void remove(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatToObjectMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatToObjectMap.java deleted file mode 100644 index da5c4f84128..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/FloatToObjectMap.java +++ /dev/null @@ -1,634 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; -import java.util.Iterator; - -/* - * 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. - */ - -/** - - * An Array-based hashtable which maps primitive float to Objects of generic type - * T.
- * The hashtable is constracted with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class FloatToObjectMap implements Iterable { - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - FloatToObjectMap.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements FloatIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public float next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public T next() { - return (T) values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - float[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - Object[] values; - - /** - * Constructs a map with default capacity. - */ - public FloatToObjectMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public FloatToObjectMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new Object[arrayLength]; - this.keys = new float[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param e - * element which is being mapped using the given key - */ - private void prvt_put(float key, T e) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = e; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor. - */ - protected int calcBaseHashIndex(float key) { - return Float.floatToIntBits(key) & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(float key) { - return find(key) != 0; - } - - /** - * Checks if the given object exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param o - * object that is checked against the map data. - * @return true if the object exists in the map (in .equals() meaning). - * false otherwise. - */ - public boolean containsValue(Object o) { - for (Iterator iterator = iterator(); iterator.hasNext();) { - T object = iterator.next(); - if (object.equals(o)) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(float key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(float key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the object mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return an object mapped by the given key. null if the key wasn't found. - */ - @SuppressWarnings("unchecked") - public T get(float key) { - return (T) values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - @SuppressWarnings("unchecked") - protected void grow() { - FloatToObjectMap that = new FloatToObjectMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put(this.keys[index], (T) this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped objects. - */ - @Override - public Iterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public FloatIterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for DEBUG purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or null if the key didn't exist. - */ - @SuppressWarnings("unchecked") - public T put(float key, T e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - T old = (T) values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return null; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or null if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or null if none existed. - */ - @SuppressWarnings("unchecked") - public T remove(float key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return (T) values[index]; - } - - return null; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public Object[] toArray() { - int j = -1; - Object[] array = new Object[size]; - - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored, if it is big enough; otherwise, use whatever space we - * have, setting the one after the true data as null. - * - * @return an array containing the elements of the list - * - */ - public T[] toArray(T[] a) { - int j = 0; - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - - if (j < a.length) { - a[j] = null; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - FloatIterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - float key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object o) { - FloatToObjectMap that = (FloatToObjectMap)o; - if (that.size() != this.size()) { - return false; - } - - FloatIterator it = keyIterator(); - while (it.hasNext()) { - float key = it.next(); - if (!that.containsKey(key)) { - return false; - } - - T v1 = this.get(key); - T v2 = that.get(key); - if ((v1 == null && v2 != null) || - (v1 != null && v2 == null) || - (!v1.equals(v2))) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntArray.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntArray.java deleted file mode 100644 index 9cb6e1cc9a6..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntArray.java +++ /dev/null @@ -1,252 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; - -/* - * 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. - */ - -/** - * A Class wrapper for a grow-able int[] which can be sorted and intersect with - * other IntArrays. - * - * @lucene.experimental - */ -public class IntArray { - - /** - * The int[] which holds the data - */ - private int[] data; - - /** - * Holds the number of items in the array. - */ - private int size; - - /** - * A flag which indicates whether a sort should occur of the array is - * already sorted. - */ - private boolean shouldSort; - - /** - * Construct a default IntArray, size 0 and surly a sort should not occur. - */ - public IntArray() { - init(true); - } - - private void init(boolean realloc) { - size = 0; - if (realloc) { - data = new int[0]; - } - shouldSort = false; - } - - /** - * Intersects the data with a given {@link IntHashSet}. - * - * @param set - * A given ArrayHashSetInt which holds the data to be intersected - * against - */ - public void intersect(IntHashSet set) { - int newSize = 0; - for (int i = 0; i < size; ++i) { - if (set.contains(data[i])) { - data[newSize] = data[i]; - ++newSize; - } - } - this.size = newSize; - } - - /** - * Intersects the data with a given IntArray - * - * @param other - * A given IntArray which holds the data to be intersected agains - */ - public void intersect(IntArray other) { - sort(); - other.sort(); - - int myIndex = 0; - int otherIndex = 0; - int newSize = 0; - if (this.size > other.size) { - while (otherIndex < other.size && myIndex < size) { - while (otherIndex < other.size - && other.data[otherIndex] < data[myIndex]) { - ++otherIndex; - } - if (otherIndex == other.size) { - break; - } - while (myIndex < size && other.data[otherIndex] > data[myIndex]) { - ++myIndex; - } - if (other.data[otherIndex] == data[myIndex]) { - data[newSize++] = data[myIndex]; - ++otherIndex; - ++myIndex; - } - } - } else { - while (otherIndex < other.size && myIndex < size) { - while (myIndex < size && other.data[otherIndex] > data[myIndex]) { - ++myIndex; - } - if (myIndex == size) { - break; - } - while (otherIndex < other.size - && other.data[otherIndex] < data[myIndex]) { - ++otherIndex; - } - if (other.data[otherIndex] == data[myIndex]) { - data[newSize++] = data[myIndex]; - ++otherIndex; - ++myIndex; - } - } - } - this.size = newSize; - } - - /** - * Return the size of the Array. Not the allocated size, but the number of - * values actually set. - * - * @return the (filled) size of the array - */ - public int size() { - return size; - } - - /** - * Adds a value to the array. - * - * @param value - * value to be added - */ - public void addToArray(int value) { - if (size == data.length) { - int[] newArray = new int[2 * size + 1]; - System.arraycopy(data, 0, newArray, 0, size); - data = newArray; - } - data[size] = value; - ++size; - shouldSort = true; - } - - /** - * Equals method. Checking the sizes, than the values from the last index to - * the first (Statistically for random should be the same but for our - * specific use would find differences faster). - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof IntArray)) { - return false; - } - - IntArray array = (IntArray) o; - if (array.size != size) { - return false; - } - - sort(); - array.sort(); - - boolean equal = true; - - for (int i = size; i > 0 && equal;) { - --i; - equal = (array.data[i] == this.data[i]); - } - - return equal; - } - - /** - * Sorts the data. If it is needed. - */ - public void sort() { - if (shouldSort) { - shouldSort = false; - Arrays.sort(data, 0, size); - } - } - - /** - * Calculates a hash-code for HashTables - */ - @Override - public int hashCode() { - int hash = 0; - for (int i = 0; i < size; ++i) { - hash = data[i] ^ (hash * 31); - } - return hash; - } - - /** - * Get an element from a specific index. - * - * @param i - * index of which element should be retrieved. - */ - public int get(int i) { - if (i >= size) { - throw new ArrayIndexOutOfBoundsException(i); - } - return this.data[i]; - } - - public void set(int idx, int value) { - if (idx >= size) { - throw new ArrayIndexOutOfBoundsException(idx); - } - this.data[idx] = value; - } - - /** - * toString or not toString. That is the question! - */ - @Override - public String toString() { - String s = "(" + size + ") "; - for (int i = 0; i < size; ++i) { - s += "" + data[i] + ", "; - } - return s; - } - - /** - * Clear the IntArray (set all elements to zero). - * @param resize - if resize is true, then clear actually allocates - * a new array of size 0, essentially 'clearing' the array and freeing - * memory. - */ - public void clear(boolean resize) { - init(resize); - } - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntHashSet.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntHashSet.java deleted file mode 100644 index 3d5a81718f5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntHashSet.java +++ /dev/null @@ -1,548 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; - -/* - * 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. - */ - -/** - * A Set or primitive int. Implemented as a HashMap of int->int. * - * - * @lucene.experimental - */ -public class IntHashSet { - - // TODO (Facet): This is wasteful as the "values" are actually the "keys" and - // we could spare this amount of space (capacity * sizeof(int)). Perhaps even - // though it is not OOP, we should re-implement the hash for just that cause. - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - IntHashSet.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - int[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * Constructs a map with default capacity. - */ - public IntHashSet() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public IntHashSet(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.keys = new int[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given value - */ - private void prvt_add(int key) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor - * . - */ - protected int calcBaseHashIndex(int key) { - return key & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param value - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean contains(int value) { - return find(value) != 0; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(int key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(int key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - protected void grow() { - IntHashSet that = new IntHashSet(this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_add(this.keys[index]); - } - // for (int i = capacity; i > 0; --i) { - // - // that._add(this.keys[i]); - // - // } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped objects. - */ - public IntIterator iterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Add a mapping int key -> int value. - *

- * If the key was already inside just - * updating the value it refers to as the given object. - *

- * Otherwise if the map is full, first {@link #grow()} the map. - * - * @param value - * integer which maps the given value - * @return true always. - */ - public boolean add(int value) { - // Does key exists? - int index = find(value); - - // Yes! - if (index != 0) { - return true; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_add(value); - - return true; - } - - /** - * Remove a pair from the map, specified by it's key. - * - * @param value - * specify the value to be removed - * - * @return true if the map was changed (the key was found and removed). - * false otherwise. - */ - public boolean remove(int value) { - int baseHashIndex = calcBaseHashIndex(value); - int index = findForRemove(value, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return true; - } - - return false; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public int[] toArray() { - int j = -1; - int[] array = new int[size]; - - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of ints - * - * @param a - * the array into which the elements of the map are to be stored, - * if it is big enough; otherwise, a new array of the same - * runtime type is allocated for this purpose. - * - * @return an array containing the values stored in the map - * - */ - public int[] toArray(int[] a) { - int j = 0; - if (a.length < size) { - a = new int[size]; - } - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - return a; - } - - /** - * I have no idea why would anyone call it - but for debug purposes.
- * Prints the entire map, including the index, key, object, next and prev. - */ - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - IntIterator iterator = iterator(); - while (iterator.hasNext()) { - sb.append(iterator.next()); - if (iterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - public String toHashString() { - String string = "\n"; - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < this.baseHash.length; i++) { - StringBuffer sb2 = new StringBuffer(); - boolean shouldAppend = false; - sb2.append(i + ".\t"); - for (int index = baseHash[i]; index != 0; index = next[index]) { - sb2.append(" -> " + keys[index] + "@" + index); - shouldAppend = true; - } - if (shouldAppend) { - sb.append(sb2); - sb.append(string); - } - } - - return sb.toString(); - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntIterator.java deleted file mode 100644 index a69b2cbeb1e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntIterator.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.lucene.facet.collections; - -/* - * 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. - */ - -/** - * Iterator interface for primitive int iteration. * - * - * @lucene.experimental - */ -public interface IntIterator { - - boolean hasNext(); - int next(); - void remove(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToDoubleMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToDoubleMap.java deleted file mode 100644 index b787ab61e9a..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToDoubleMap.java +++ /dev/null @@ -1,631 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps primitive int to a primitive double.
- * The hashtable is constracted with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class IntToDoubleMap { - - public static final double GROUND = Double.NaN; - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - IntToDoubleMap.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements DoubleIterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public double next() { - return values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - int[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - double[] values; - - /** - * Constructs a map with default capacity. - */ - public IntToDoubleMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public IntToDoubleMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new double[arrayLength]; - this.keys = new int[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - this.values[0] = GROUND; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param v - * double value which is being mapped using the given key - */ - private void prvt_put(int key, double v) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = v; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor - * . - */ - protected int calcBaseHashIndex(int key) { - return key & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(int key) { - return find(key) != 0; - } - - /** - * Checks if the given value exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param value - * double value that is checked against the map data. - * @return true if the value exists in the map, false otherwise. - */ - public boolean containsValue(double value) { - for (DoubleIterator iterator = iterator(); iterator.hasNext();) { - double d = iterator.next(); - if (d == value) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(int key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(int key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the value mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return a double value mapped by the given key. Double.NaN if the key wasn't found. - */ - public double get(int key) { - return values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - protected void grow() { - IntToDoubleMap that = new IntToDoubleMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put(this.keys[index], this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped double values. - */ - public DoubleIterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public IntIterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or {@link Double#NaN} if the key didn't exist. - */ - public double put(int key, double v) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - double old = values[index]; - values[index] = v; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, v); - - return Double.NaN; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or {@link Double#NaN} if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or {@link Double#NaN} if none existed. - */ - public double remove(int key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return values[index]; - } - - return Double.NaN; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return a double array of all the values currently in the map. - */ - public double[] toArray() { - int j = -1; - double[] array = new double[size]; - - // Iterates over the values, adding them to the array. - for (DoubleIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored. If it is big enough use whatever space we need, - * setting the one after the true data as {@link Double#NaN}. - * - * @return an array containing the elements of the list, using the given - * parameter if big enough, otherwise allocate an appropriate array - * and return it. - * - */ - public double[] toArray(double[] a) { - int j = 0; - if (a.length < this.size()) { - a = new double[this.size()]; - } - - // Iterates over the values, adding them to the array. - for (DoubleIterator iterator = iterator(); iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - - if (j < a.length) { - a[j] = Double.NaN; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - IntIterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - int key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @Override - public boolean equals(Object o) { - IntToDoubleMap that = (IntToDoubleMap)o; - if (that.size() != this.size()) { - return false; - } - - IntIterator it = keyIterator(); - while (it.hasNext()) { - int key = it.next(); - if (!that.containsKey(key)) { - return false; - } - - double v1 = this.get(key); - double v2 = that.get(key); - if (Double.compare(v1, v2) != 0) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToFloatMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToFloatMap.java deleted file mode 100644 index 3e9d7aee2b8..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToFloatMap.java +++ /dev/null @@ -1,631 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps primitive int to a primitive float.
- * The hashtable is constracted with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class IntToFloatMap { - - public static final float GROUND = Float.NaN; - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - IntToFloatMap.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements FloatIterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public float next() { - return values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - int[] keys; - - /** - * In case of collisions, we implement a float linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - float[] values; - - /** - * Constructs a map with default capacity. - */ - public IntToFloatMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public IntToFloatMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new float[arrayLength]; - this.keys = new int[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - this.values[0] = GROUND; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param v - * float value which is being mapped using the given key - */ - private void prvt_put(int key, float v) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = v; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor - * . - */ - protected int calcBaseHashIndex(int key) { - return key & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(int key) { - return find(key) != 0; - } - - /** - * Checks if the given value exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param value - * float value that is checked against the map data. - * @return true if the value exists in the map, false otherwise. - */ - public boolean containsValue(float value) { - for (FloatIterator iterator = iterator(); iterator.hasNext();) { - float d = iterator.next(); - if (d == value) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(int key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(int key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the value mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return a float value mapped by the given key. float.NaN if the key wasn't found. - */ - public float get(int key) { - return values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of float the capacity, and - * fast-insert the old key-value pairs. - */ - protected void grow() { - IntToFloatMap that = new IntToFloatMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put(this.keys[index], this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped float values. - */ - public FloatIterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public IntIterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or {@link Float#NaN} if the key didn't exist. - */ - public float put(int key, float v) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - float old = values[index]; - values[index] = v; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, v); - - return Float.NaN; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or {@link Float#NaN} if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or {@link Float#NaN} if none existed. - */ - public float remove(int key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return values[index]; - } - - return Float.NaN; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return a float array of all the values currently in the map. - */ - public float[] toArray() { - int j = -1; - float[] array = new float[size]; - - // Iterates over the values, adding them to the array. - for (FloatIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored. If it is big enough use whatever space we need, - * setting the one after the true data as {@link Float#NaN}. - * - * @return an array containing the elements of the list, using the given - * parameter if big enough, otherwise allocate an appropriate array - * and return it. - * - */ - public float[] toArray(float[] a) { - int j = 0; - if (a.length < this.size()) { - a = new float[this.size()]; - } - - // Iterates over the values, adding them to the array. - for (FloatIterator iterator = iterator(); iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - - if (j < a.length) { - a[j] = Float.NaN; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - IntIterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - int key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @Override - public boolean equals(Object o) { - IntToFloatMap that = (IntToFloatMap)o; - if (that.size() != this.size()) { - return false; - } - - IntIterator it = keyIterator(); - while (it.hasNext()) { - int key = it.next(); - if (!that.containsKey(key)) { - return false; - } - - float v1 = this.get(key); - float v2 = that.get(key); - if (Float.compare(v1, v2) != 0) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToIntMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToIntMap.java deleted file mode 100644 index f2f27fce417..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToIntMap.java +++ /dev/null @@ -1,622 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps primitive int to primitive int.
- * The hashtable is constracted with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class IntToIntMap { - - public static final int GROUD = -1; - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - IntToIntMap.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an IntIterator used for iteration over the map's values. - */ - private final class ValueIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - int[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - int[] values; - - /** - * Constructs a map with default capacity. - */ - public IntToIntMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public IntToIntMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new int[arrayLength]; - this.keys = new int[arrayLength]; - this.next = new int[arrayLength]; - - this.values[0] = GROUD; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given value - * @param e - * value which is being mapped using the given key - */ - private void prvt_put(int key, int e) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = e; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor. - */ - protected int calcBaseHashIndex(int key) { - return key & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(int key) { - return find(key) != 0; - } - - /** - * Checks if the given object exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param v - * value that is checked against the map data. - * @return true if the value exists in the map (in .equals() meaning). - * false otherwise. - */ - public boolean containsValue(int v) { - for (IntIterator iterator = iterator(); iterator.hasNext();) { - if (v == iterator.next()) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(int key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(int key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the object mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return an object mapped by the given key. null if the key wasn't found. - */ - public int get(int key) { - return values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - protected void grow() { - IntToIntMap that = new IntToIntMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put(this.keys[index], this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped objects. - */ - public IntIterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public IntIterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(this.baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or 0 if the key didn't exist. - */ - public int put(int key, int e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - int old = values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return 0; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or 0 if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or 0 if none existed. - */ - public int remove(int key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return values[index]; - } - - return 0; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public int[] toArray() { - int j = -1; - int[] array = new int[size]; - - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of ints - * - * @param a - * the array into which the elements of the map are to be - * stored, if it is big enough; otherwise, a new array of the - * same runtime type is allocated for this purpose. - * - * @return an array containing the values stored in the map - * - */ - public int[] toArray(int[] a) { - int j = 0; - if (a.length < size) { - a = new int[size]; - } - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - IntIterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - int key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @Override - public boolean equals(Object o) { - IntToIntMap that = (IntToIntMap)o; - if (that.size() != this.size()) { - return false; - } - - IntIterator it = keyIterator(); - while (it.hasNext()) { - int key = it.next(); - - if (!that.containsKey(key)) { - return false; - } - - int v1 = this.get(key); - int v2 = that.get(key); - if (v1 != v2) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToObjectMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToObjectMap.java deleted file mode 100644 index 9db16ec189f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/IntToObjectMap.java +++ /dev/null @@ -1,634 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; -import java.util.Iterator; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps primitive int to Objects of generic type - * T.
- * The hashtable is constracted with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class IntToObjectMap implements Iterable { - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - public void remove() { - IntToObjectMap.this.remove(keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public T next() { - return (T) values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - int[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - Object[] values; - - /** - * Constructs a map with default capacity. - */ - public IntToObjectMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public IntToObjectMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new Object[arrayLength]; - this.keys = new int[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param e - * element which is being mapped using the given key - */ - private void prvt_put(int key, T e) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = e; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor. - * - */ - protected int calcBaseHashIndex(int key) { - return key & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(int key) { - return find(key) != 0; - } - - /** - * Checks if the given object exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param o - * object that is checked against the map data. - * @return true if the object exists in the map (in .equals() meaning). - * false otherwise. - */ - public boolean containsValue(Object o) { - for (Iterator iterator = iterator(); iterator.hasNext();) { - T object = iterator.next(); - if (object.equals(o)) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(int key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex] == key) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(int key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index] == key) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the object mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return an object mapped by the given key. null if the key wasn't found. - */ - @SuppressWarnings("unchecked") - public T get(int key) { - return (T) values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - @SuppressWarnings("unchecked") - protected void grow() { - IntToObjectMap that = new IntToObjectMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put(this.keys[index], (T) this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped objects. - */ - @Override - public Iterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public IntIterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or null if the key didn't exist. - */ - @SuppressWarnings("unchecked") - public T put(int key, T e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - T old = (T) values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return null; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or null if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or null if none existed. - */ - @SuppressWarnings("unchecked") - public T remove(int key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return (T) values[index]; - } - - return null; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public Object[] toArray() { - int j = -1; - Object[] array = new Object[size]; - - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored, if it is big enough; otherwise, use whatever space we - * have, setting the one after the true data as null. - * - * @return an array containing the elements of the list - * - */ - public T[] toArray(T[] a) { - int j = 0; - // Iterates over the values, adding them to the array. - for (Iterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - - if (j < a.length) { - a[j] = null; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - IntIterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - int key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object o) { - IntToObjectMap that = (IntToObjectMap)o; - if (that.size() != this.size()) { - return false; - } - - IntIterator it = keyIterator(); - while (it.hasNext()) { - int key = it.next(); - if (!that.containsKey(key)) { - return false; - } - - T v1 = this.get(key); - T v2 = that.get(key); - if ((v1 == null && v2 != null) || - (v1 != null && v2 == null) || - (!v1.equals(v2))) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToFloatMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToFloatMap.java deleted file mode 100644 index 7c7a95cd92f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToFloatMap.java +++ /dev/null @@ -1,623 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; -import java.util.Iterator; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps Objects of generic type - * T to primitive float values.
- * The hashtable is constructed with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class ObjectToFloatMap { - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - @SuppressWarnings("unchecked") - public void remove() { - ObjectToFloatMap.this.remove((K) keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public K next() { - return (K) keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements FloatIterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public float next() { - return values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - Object[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - float[] values; - - /** - * Constructs a map with default capacity. - */ - public ObjectToFloatMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public ObjectToFloatMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new float[arrayLength]; - this.keys = new Object[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param e - * element which is being mapped using the given key - */ - private void prvt_put(K key, float e) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = e; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor. - */ - protected int calcBaseHashIndex(K key) { - return key.hashCode() & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - values[0] = Float.NaN; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(K key) { - return find(key) != 0; - } - - /** - * Checks if the given object exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param o - * object that is checked against the map data. - * @return true if the object exists in the map (in .equals() meaning). - * false otherwise. - */ - public boolean containsValue(float o) { - for (FloatIterator iterator = iterator(); iterator.hasNext();) { - if (o == iterator.next()) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(K key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex].equals(key)) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(K key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index].equals(key)) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the float mapped with the given key. - * - * @param key - * object who's mapped float we're interested in. - * @return a float mapped by the given key. Float.NaN if the key wasn't found. - */ - public float get(K key) { - return values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - @SuppressWarnings("unchecked") - protected void grow() { - ObjectToFloatMap that = new ObjectToFloatMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put((K) this.keys[index], this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped floats. - */ - public FloatIterator iterator() { - return new ValueIterator(); - } - - /** Returns an iterator on the map keys. */ - public Iterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or {@link Float#NaN} if the key didn't exist. - */ - public float put(K key, float e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - float old = values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return Float.NaN; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or {@link Float#NaN} if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or {@link Float#NaN} if none existed. - */ - public float remove(K key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return values[index]; - } - - return Float.NaN; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public float[] toArray() { - int j = -1; - float[] array = new float[size]; - - // Iterates over the values, adding them to the array. - for (FloatIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored, if it is big enough; otherwise, use as much space as it can. - * - * @return an array containing the elements of the list - * - */ - public float[] toArray(float[] a) { - int j = 0; - // Iterates over the values, adding them to the array. - for (FloatIterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - if (j < a.length) { - a[j] = Float.NaN; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - Iterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - K key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object o) { - ObjectToFloatMap that = (ObjectToFloatMap)o; - if (that.size() != this.size()) { - return false; - } - - Iterator it = keyIterator(); - while (it.hasNext()) { - K key = it.next(); - float v1 = this.get(key); - float v2 = that.get(key); - if (Float.compare(v1, v2) != 0) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToIntMap.java b/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToIntMap.java deleted file mode 100644 index a7ce7a6e278..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/ObjectToIntMap.java +++ /dev/null @@ -1,622 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.Arrays; -import java.util.Iterator; - -/* - * 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. - */ - -/** - * An Array-based hashtable which maps Objects of generic type - * T to primitive int values.
- * The hashtable is constructed with a given capacity, or 16 as a default. In - * case there's not enough room for new pairs, the hashtable grows.
- * Capacity is adjusted to a power of 2, and there are 2 * capacity entries for - * the hash. - * - * The pre allocated arrays (for keys, values) are at length of capacity + 1, - * when index 0 is used as 'Ground' or 'NULL'.
- * - * The arrays are allocated ahead of hash operations, and form an 'empty space' - * list, to which the key,value pair is allocated. - * - * @lucene.experimental - */ -public class ObjectToIntMap { - - /** - * Implements an IntIterator which iterates over all the allocated indexes. - */ - private final class IndexIterator implements IntIterator { - /** - * The last used baseHashIndex. Needed for "jumping" from one hash entry - * to another. - */ - private int baseHashIndex = 0; - - /** - * The next not-yet-visited index. - */ - private int index = 0; - - /** - * Index of the last visited pair. Used in {@link #remove()}. - */ - private int lastIndex = 0; - - /** - * Create the Iterator, make index point to the "first" - * index which is not empty. If such does not exist (eg. the map is - * empty) it would be zero. - */ - public IndexIterator() { - for (baseHashIndex = 0; baseHashIndex < baseHash.length; ++baseHashIndex) { - index = baseHash[baseHashIndex]; - if (index != 0) { - break; - } - } - } - - @Override - public boolean hasNext() { - return (index != 0); - } - - @Override - public int next() { - // Save the last index visited - lastIndex = index; - - // next the index - index = next[index]; - - // if the next index points to the 'Ground' it means we're done with - // the current hash entry and we need to jump to the next one. This - // is done until all the hash entries had been visited. - while (index == 0 && ++baseHashIndex < baseHash.length) { - index = baseHash[baseHashIndex]; - } - - return lastIndex; - } - - @Override - @SuppressWarnings("unchecked") - public void remove() { - ObjectToIntMap.this.remove((K) keys[lastIndex]); - } - - } - - /** - * Implements an IntIterator, used for iteration over the map's keys. - */ - private final class KeyIterator implements Iterator { - private IntIterator iterator = new IndexIterator(); - - KeyIterator() { } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - @SuppressWarnings("unchecked") - public K next() { - return (K) keys[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Implements an Iterator of a generic type T used for iteration over the - * map's values. - */ - private final class ValueIterator implements IntIterator { - private IntIterator iterator = new IndexIterator(); - - ValueIterator() {} - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public int next() { - return values[iterator.next()]; - } - - @Override - public void remove() { - iterator.remove(); - } - } - - /** - * Default capacity - in case no capacity was specified in the constructor - */ - private static int defaultCapacity = 16; - - /** - * Holds the base hash entries. if the capacity is 2^N, than the base hash - * holds 2^(N+1). It can hold - */ - int[] baseHash; - - /** - * The current capacity of the map. Always 2^N and never less than 16. We - * never use the zero index. It is needed to improve performance and is also - * used as "ground". - */ - private int capacity; - /** - * All objects are being allocated at map creation. Those objects are "free" - * or empty. Whenever a new pair comes along, a pair is being "allocated" or - * taken from the free-linked list. as this is just a free list. - */ - private int firstEmpty; - - /** - * hashFactor is always (2^(N+1)) - 1. Used for faster hashing. - */ - private int hashFactor; - - /** - * This array holds the unique keys - */ - Object[] keys; - - /** - * In case of collisions, we implement a double linked list of the colliding - * hash's with the following next[] and prev[]. Those are also used to store - * the "empty" list. - */ - int[] next; - - private int prev; - - /** - * Number of currently objects in the map. - */ - private int size; - - /** - * This array holds the values - */ - int[] values; - - /** - * Constructs a map with default capacity. - */ - public ObjectToIntMap() { - this(defaultCapacity); - } - - /** - * Constructs a map with given capacity. Capacity is adjusted to a native - * power of 2, with minimum of 16. - * - * @param capacity - * minimum capacity for the map. - */ - public ObjectToIntMap(int capacity) { - this.capacity = 16; - // Minimum capacity is 16.. - while (this.capacity < capacity) { - // Multiply by 2 as long as we're still under the requested capacity - this.capacity <<= 1; - } - - // As mentioned, we use the first index (0) as 'Ground', so we need the - // length of the arrays to be one more than the capacity - int arrayLength = this.capacity + 1; - - this.values = new int[arrayLength]; - this.keys = new Object[arrayLength]; - this.next = new int[arrayLength]; - - // Hash entries are twice as big as the capacity. - int baseHashSize = this.capacity << 1; - - this.baseHash = new int[baseHashSize]; - - // The has factor is 2^M - 1 which is used as an "AND" hashing operator. - // {@link #calcBaseHash()} - this.hashFactor = baseHashSize - 1; - - this.size = 0; - - clear(); - } - - /** - * Adds a pair to the map. Takes the first empty position from the - * empty-linked-list's head - {@link #firstEmpty}. - * - * New pairs are always inserted to baseHash, and are followed by the old - * colliding pair. - * - * @param key - * integer which maps the given Object - * @param e - * element which is being mapped using the given key - */ - private void prvt_put(K key, int e) { - // Hash entry to which the new pair would be inserted - int hashIndex = calcBaseHashIndex(key); - - // 'Allocating' a pair from the "Empty" list. - int objectIndex = firstEmpty; - - // Setting data - firstEmpty = next[firstEmpty]; - values[objectIndex] = e; - keys[objectIndex] = key; - - // Inserting the new pair as the first node in the specific hash entry - next[objectIndex] = baseHash[hashIndex]; - baseHash[hashIndex] = objectIndex; - - // Announcing a new pair was added! - ++size; - } - - /** - * Calculating the baseHash index using the internal hashFactor. - */ - protected int calcBaseHashIndex(K key) { - return key.hashCode() & hashFactor; - } - - /** - * Empties the map. Generates the "Empty" space list for later allocation. - */ - public void clear() { - // Clears the hash entries - Arrays.fill(this.baseHash, 0); - - // Set size to zero - size = 0; - - values[0] = Integer.MAX_VALUE; - - // Mark all array entries as empty. This is done with - // firstEmpty pointing to the first valid index (1 as 0 is - // used as 'Ground'). - firstEmpty = 1; - - // And setting all the next[i] to point at - // i+1. - for (int i = 1; i < this.capacity;) { - next[i] = ++i; - } - - // Surly, the last one should point to the 'Ground'. - next[this.capacity] = 0; - } - - /** - * Checks if a given key exists in the map. - * - * @param key - * that is checked against the map data. - * @return true if the key exists in the map. false otherwise. - */ - public boolean containsKey(K key) { - return find(key) != 0; - } - - /** - * Checks if the given object exists in the map.
- * This method iterates over the collection, trying to find an equal object. - * - * @param o - * object that is checked against the map data. - * @return true if the object exists in the map (in .equals() meaning). - * false otherwise. - */ - public boolean containsValue(int o) { - for (IntIterator iterator = iterator(); iterator.hasNext();) { - if (o == iterator.next()) { - return true; - } - } - return false; - } - - /** - * Find the actual index of a given key. - * - * @return index of the key. zero if the key wasn't found. - */ - protected int find(K key) { - // Calculate the hash entry. - int baseHashIndex = calcBaseHashIndex(key); - - // Start from the hash entry. - int localIndex = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (localIndex != 0) { - // returns the index found in case of of a matching key. - if (keys[localIndex].equals(key)) { - return localIndex; - } - - // next the local index - localIndex = next[localIndex]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - return 0; - } - - /** - * Find the actual index of a given key with it's baseHashIndex.
- * Some methods use the baseHashIndex. If those call {@link #find} there's - * no need to re-calculate that hash. - * - * @return the index of the given key, or 0 as 'Ground' if the key wasn't - * found. - */ - private int findForRemove(K key, int baseHashIndex) { - // Start from the hash entry. - this.prev = 0; - int index = baseHash[baseHashIndex]; - - // while the index does not point to the 'Ground' - while (index != 0) { - // returns the index found in case of of a matching key. - if (keys[index].equals(key)) { - return index; - } - - // next the local index - prev = index; - index = next[index]; - } - - // If we got this far, it could only mean we did not find the key we - // were asked for. return 'Ground' index. - this.prev = 0; - return 0; - } - - /** - * Returns the int mapped with the given key. - * - * @param key - * int who's mapped object we're interested in. - * @return an object mapped by the given key. null if the key wasn't found. - */ - public int get(K key) { - return values[find(key)]; - } - - /** - * Grows the map. Allocates a new map of double the capacity, and - * fast-insert the old key-value pairs. - */ - @SuppressWarnings("unchecked") - protected void grow() { - ObjectToIntMap that = new ObjectToIntMap( - this.capacity * 2); - - // Iterates fast over the collection. Any valid pair is put into the new - // map without checking for duplicates or if there's enough space for - // it. - for (IndexIterator iterator = new IndexIterator(); iterator.hasNext();) { - int index = iterator.next(); - that.prvt_put((K) this.keys[index], this.values[index]); - } - - // Copy that's data into this. - this.capacity = that.capacity; - this.size = that.size; - this.firstEmpty = that.firstEmpty; - this.values = that.values; - this.keys = that.keys; - this.next = that.next; - this.baseHash = that.baseHash; - this.hashFactor = that.hashFactor; - } - - /** - * - * @return true if the map is empty. false otherwise. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns a new iterator for the mapped objects. - */ - public IntIterator iterator() { - return new ValueIterator(); - } - - public Iterator keyIterator() { - return new KeyIterator(); - } - - /** - * Prints the baseHash array, used for debug purposes. - */ - @SuppressWarnings("unused") - private String getBaseHashAsString() { - return Arrays.toString(baseHash); - } - - /** - * Inserts the <key,value> pair into the map. If the key already exists, - * this method updates the mapped value to the given one, returning the old - * mapped value. - * - * @return the old mapped value, or 0 if the key didn't exist. - */ - public int put(K key, int e) { - // Does key exists? - int index = find(key); - - // Yes! - if (index != 0) { - // Set new data and exit. - int old = values[index]; - values[index] = e; - return old; - } - - // Is there enough room for a new pair? - if (size == capacity) { - // No? Than grow up! - grow(); - } - - // Now that everything is set, the pair can be just put inside with no - // worries. - prvt_put(key, e); - - return 0; - } - - /** - * Removes a <key,value> pair from the map and returns the mapped value, - * or 0 if the none existed. - * - * @param key used to find the value to remove - * @return the removed value or 0 if none existed. - */ - public int remove(K key) { - int baseHashIndex = calcBaseHashIndex(key); - int index = findForRemove(key, baseHashIndex); - if (index != 0) { - // If it is the first in the collision list, we should promote its - // next colliding element. - if (prev == 0) { - baseHash[baseHashIndex] = next[index]; - } - - next[prev] = next[index]; - next[index] = firstEmpty; - firstEmpty = index; - --size; - return values[index]; - } - - return 0; - } - - /** - * @return number of pairs currently in the map - */ - public int size() { - return this.size; - } - - /** - * Translates the mapped pairs' values into an array of Objects - * - * @return an object array of all the values currently in the map. - */ - public int[] toArray() { - int j = -1; - int[] array = new int[size]; - - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); iterator.hasNext();) { - array[++j] = iterator.next(); - } - return array; - } - - /** - * Translates the mapped pairs' values into an array of T - * - * @param a - * the array into which the elements of the list are to be - * stored, if it is big enough; otherwise, use as much space as it can. - * - * @return an array containing the elements of the list - * - */ - public int[] toArray(int[] a) { - int j = 0; - // Iterates over the values, adding them to the array. - for (IntIterator iterator = iterator(); j < a.length - && iterator.hasNext(); ++j) { - a[j] = iterator.next(); - } - if (j < a.length) { - a[j] = Integer.MAX_VALUE; - } - - return a; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - Iterator keyIterator = keyIterator(); - while (keyIterator.hasNext()) { - K key = keyIterator.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (keyIterator.hasNext()) { - sb.append(','); - sb.append(' '); - } - } - sb.append('}'); - return sb.toString(); - } - - @Override - public int hashCode() { - return getClass().hashCode() ^ size(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object o) { - ObjectToIntMap that = (ObjectToIntMap)o; - if (that.size() != this.size()) { - return false; - } - - Iterator it = keyIterator(); - while (it.hasNext()) { - K key = it.next(); - int v1 = this.get(key); - int v2 = that.get(key); - if (Float.compare(v1, v2) != 0) { - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/package.html b/lucene/facet/src/java/org/apache/lucene/facet/collections/package.html deleted file mode 100644 index 792be18a139..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets Collections - - -Various optimized Collections implementations. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCounts.java deleted file mode 100644 index 44d81bed67b..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCounts.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.apache.lucene.facet.complements; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.lucene.facet.old.Aggregator; -import org.apache.lucene.facet.old.CountingAggregator; -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.old.ScoredDocIdsUtils; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CategoryListIterator; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.util.PartitionsUtils; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * Maintain Total Facet Counts per partition, for given parameters: - *

    - *
  • Index reader of an index
  • - *
  • Taxonomy index reader
  • - *
  • Facet indexing params (and particularly the category list params)
  • - *
  • - *
- * The total facet counts are maintained as an array of arrays of integers, - * where a separate array is kept for each partition. - * - * @lucene.experimental - */ -public class TotalFacetCounts { - - /** total facet counts per partition: totalCounts[partition][ordinal%partitionLength] */ - private int[][] totalCounts = null; - - private final TaxonomyReader taxonomy; - private final FacetIndexingParams facetIndexingParams; - - private final static AtomicInteger atomicGen4Test = new AtomicInteger(1); - /** Creation type for test purposes */ - enum CreationType { Computed, Loaded } // for testing - final int gen4test; - final CreationType createType4test; - - /** - * Construct by key - from index Directory or by recomputing. - */ - private TotalFacetCounts (TaxonomyReader taxonomy, FacetIndexingParams facetIndexingParams, - int[][] counts, CreationType createType4Test) { - this.taxonomy = taxonomy; - this.facetIndexingParams = facetIndexingParams; - this.totalCounts = counts; - this.createType4test = createType4Test; - this.gen4test = atomicGen4Test.incrementAndGet(); - } - - /** - * Fill a partition's array with the TotalCountsArray values. - * @param partitionArray array to fill - * @param partition number of required partition - */ - public void fillTotalCountsForPartition(int[] partitionArray, int partition) { - int partitionSize = partitionArray.length; - int[] countArray = totalCounts[partition]; - if (countArray == null) { - countArray = new int[partitionSize]; - totalCounts[partition] = countArray; - } - int length = Math.min(partitionSize, countArray.length); - System.arraycopy(countArray, 0, partitionArray, 0, length); - } - - /** - * Return the total count of an input category - * @param ordinal ordinal of category whose total count is required - */ - public int getTotalCount(int ordinal) { - int partition = PartitionsUtils.partitionNumber(facetIndexingParams,ordinal); - int offset = ordinal % PartitionsUtils.partitionSize(facetIndexingParams, taxonomy); - return totalCounts[partition][offset]; - } - - static TotalFacetCounts loadFromFile(File inputFile, TaxonomyReader taxonomy, - FacetIndexingParams facetIndexingParams) throws IOException { - DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(inputFile))); - try { - int[][] counts = new int[dis.readInt()][]; - for (int i=0; i getCategoryListMap( - FacetArrays facetArrays, int partition) throws IOException { - - Aggregator aggregator = new CountingAggregator(counts[partition]); - HashMap map = new HashMap(); - for (CategoryListParams clp: facetIndexingParams.getAllCategoryListParams()) { - map.put(clp.createCategoryListIterator(partition), aggregator); - } - return map; - } - }; - sfa.setComplementThreshold(OldFacetsAccumulator.DISABLE_COMPLEMENT); - sfa.accumulate(ScoredDocIdsUtils.createAllDocsScoredDocIDs(indexReader)); - return new TotalFacetCounts(taxonomy, facetIndexingParams, counts, CreationType.Computed); - } - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCountsCache.java b/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCountsCache.java deleted file mode 100644 index 6000e8c54f9..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/complements/TotalFacetCountsCache.java +++ /dev/null @@ -1,299 +0,0 @@ -package org.apache.lucene.facet.complements; - -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * Manage an LRU cache for {@link TotalFacetCounts} per index, taxonomy, and - * facet indexing params. - * - * @lucene.experimental - */ -public final class TotalFacetCountsCache { - - /** - * Default size of in memory cache for computed total facet counts. - * Set to 2 for the case when an application reopened a reader and - * the original one is still in use (Otherwise there will be - * switching again and again between the two.) - */ - public static final int DEFAULT_CACHE_SIZE = 2; - - private static final TotalFacetCountsCache singleton = new TotalFacetCountsCache(); - - /** - * Get the single instance of this cache - */ - public static TotalFacetCountsCache getSingleton() { - return singleton; - } - - /** - * In-memory cache of TFCs. - *
    - *
  • It's size is kept within limits through {@link #trimCache()}. - *
  • An LRU eviction policy is applied, by maintaining active keys in {@link #lruKeys}. - *
  • After each addition to the cache, trimCache is called, to remove entries least recently used. - *
- * @see #markRecentlyUsed(TFCKey) - */ - private ConcurrentHashMap cache = new ConcurrentHashMap(); - - /** - * A queue of active keys for applying LRU policy on eviction from the {@link #cache}. - * @see #markRecentlyUsed(TFCKey) - */ - private ConcurrentLinkedQueue lruKeys = new ConcurrentLinkedQueue(); - - private int maxCacheSize = DEFAULT_CACHE_SIZE; - - /** private constructor for singleton pattern */ - private TotalFacetCountsCache() { - } - - /** - * Get the total facet counts for a reader/taxonomy pair and facet indexing - * parameters. If not in cache, computed here and added to the cache for later - * use. - * - * @param indexReader - * the documents index - * @param taxonomy - * the taxonomy index - * @param facetIndexingParams - * facet indexing parameters - * @return the total facet counts. - */ - public TotalFacetCounts getTotalCounts(IndexReader indexReader, TaxonomyReader taxonomy, - FacetIndexingParams facetIndexingParams) throws IOException { - // create the key - TFCKey key = new TFCKey(indexReader, taxonomy, facetIndexingParams); - // it is important that this call is not synchronized, so that available TFC - // would not wait for one that needs to be computed. - TotalFacetCounts tfc = cache.get(key); - if (tfc != null) { - markRecentlyUsed(key); - return tfc; - } - return computeAndCache(key); - } - - /** - * Mark key as it as recently used. - *

- * Implementation notes: Synchronization considerations and the interaction between lruKeys and cache: - *

    - *
  1. A concurrent {@link LinkedHashMap} would have made this class much simpler. - * But unfortunately, Java does not provide one. - * Instead, we combine two concurrent objects: - *
      - *
    • {@link ConcurrentHashMap} for the cached TFCs. - *
    • {@link ConcurrentLinkedQueue} for active keys - *
    - *
  2. Both {@link #lruKeys} and {@link #cache} are concurrently safe. - *
  3. Checks for a cached item through getTotalCounts() are not synchronized. - * Therefore, the case that a needed TFC is in the cache is very fast: - * it does not wait for the computation of other TFCs. - *
  4. computeAndCache() is synchronized, and, has a (double) check of the required - * TFC, to avoid computing the same TFC twice. - *
  5. A race condition in this method (markRecentlyUsed) might result in two copies - * of the same 'key' in lruKeys, but this is handled by the loop in trimCache(), - * where an attempt to remove the same key twice is a no-op. - *
- */ - private void markRecentlyUsed(TFCKey key) { - lruKeys.remove(key); - lruKeys.add(key); - } - - private synchronized void trimCache() { - // loop until cache is of desired size. - while (cache.size()>maxCacheSize ) { - TFCKey key = lruKeys.poll(); - if (key==null) { //defensive - // it is defensive since lruKeys presumably covers the cache keys - key = cache.keys().nextElement(); - } - // remove this element. Note that an attempt to remove with the same key again is a no-op, - // which gracefully handles the possible race in markRecentlyUsed(). - cache.remove(key); - } - } - - /** - * compute TFC and cache it, after verifying it was not just added - for this - * matter this method is synchronized, which is not too bad, because there is - * lots of work done in the computations. - */ - private synchronized TotalFacetCounts computeAndCache(TFCKey key) throws IOException { - TotalFacetCounts tfc = cache.get(key); - if (tfc == null) { - tfc = TotalFacetCounts.compute(key.indexReader, key.taxonomy, key.facetIndexingParams); - lruKeys.add(key); - cache.put(key,tfc); - trimCache(); - } - return tfc; - } - - /** - * Load {@link TotalFacetCounts} matching input parameters from the provided - * outputFile and add them into the cache for the provided indexReader, - * taxonomy, and facetIndexingParams. If a {@link TotalFacetCounts} for these - * parameters already exists in the cache, it will be replaced by the loaded - * one. - * - * @param inputFile - * file from which to read the data - * @param indexReader - * the documents index - * @param taxonomy - * the taxonomy index - * @param facetIndexingParams - * the facet indexing parameters - * @throws IOException - * on error - */ - public synchronized void load(File inputFile, IndexReader indexReader, TaxonomyReader taxonomy, - FacetIndexingParams facetIndexingParams) throws IOException { - if (!inputFile.isFile() || !inputFile.exists() || !inputFile.canRead()) { - throw new IllegalArgumentException("Exepecting an existing readable file: "+inputFile); - } - TFCKey key = new TFCKey(indexReader, taxonomy, facetIndexingParams); - TotalFacetCounts tfc = TotalFacetCounts.loadFromFile(inputFile, taxonomy, facetIndexingParams); - cache.put(key,tfc); - trimCache(); - markRecentlyUsed(key); - } - - /** - * Store the {@link TotalFacetCounts} matching input parameters into the - * provided outputFile, making them available for a later call to - * {@link #load(File, IndexReader, TaxonomyReader, FacetIndexingParams)}. If - * these {@link TotalFacetCounts} are available in the cache, they are used. - * But if they are not in the cache, this call will first compute them (which - * will also add them to the cache). - * - * @param outputFile - * file to store in. - * @param indexReader - * the documents index - * @param taxonomy - * the taxonomy index - * @param facetIndexingParams - * the facet indexing parameters - * @throws IOException - * on error - * @see #load(File, IndexReader, TaxonomyReader, FacetIndexingParams) - */ - public void store(File outputFile, IndexReader indexReader, TaxonomyReader taxonomy, - FacetIndexingParams facetIndexingParams) throws IOException { - File parentFile = outputFile.getParentFile(); - if ( - ( outputFile.exists() && (!outputFile.isFile() || !outputFile.canWrite())) || - (!outputFile.exists() && (!parentFile.isDirectory() || !parentFile.canWrite())) - ) { - throw new IllegalArgumentException("Exepecting a writable file: "+outputFile); - } - TotalFacetCounts tfc = getTotalCounts(indexReader, taxonomy, facetIndexingParams); - TotalFacetCounts.storeToFile(outputFile, tfc); - } - - private static class TFCKey { - final IndexReader indexReader; - final TaxonomyReader taxonomy; - private final Iterable clps; - private final int hashCode; - private final int nDels; // needed when a reader used for faceted search was just used for deletion. - final FacetIndexingParams facetIndexingParams; - - public TFCKey(IndexReader indexReader, TaxonomyReader taxonomy, - FacetIndexingParams facetIndexingParams) { - this.indexReader = indexReader; - this.taxonomy = taxonomy; - this.facetIndexingParams = facetIndexingParams; - this.clps = facetIndexingParams.getAllCategoryListParams(); - this.nDels = indexReader.numDeletedDocs(); - hashCode = indexReader.hashCode() ^ taxonomy.hashCode(); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object other) { - TFCKey o = (TFCKey) other; - if (indexReader != o.indexReader || taxonomy != o.taxonomy || nDels != o.nDels) { - return false; - } - Iterator it1 = clps.iterator(); - Iterator it2 = o.clps.iterator(); - while (it1.hasNext() && it2.hasNext()) { - if (!it1.next().equals(it2.next())) { - return false; - } - } - return it1.hasNext() == it2.hasNext(); - } - } - - /** - * Clear the cache. - */ - public synchronized void clear() { - cache.clear(); - lruKeys.clear(); - } - - /** - * @return the maximal cache size - */ - public int getCacheSize() { - return maxCacheSize; - } - - /** - * Set the number of TotalFacetCounts arrays that will remain in memory cache. - *

- * If new size is smaller than current size, the cache is appropriately trimmed. - *

- * Minimal size is 1, so passing zero or negative size would result in size of 1. - * @param size new size to set - */ - public void setCacheSize(int size) { - if (size < 1) size = 1; - int origSize = maxCacheSize; - maxCacheSize = size; - if (maxCacheSize < origSize) { // need to trim only if the cache was reduced - trimCache(); - } - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/complements/package.html b/lucene/facet/src/java/org/apache/lucene/facet/complements/package.html deleted file mode 100644 index beca697e675..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/complements/package.html +++ /dev/null @@ -1,27 +0,0 @@ - - - -Facets Complements counting - - -Allows to cache the total counts of categories, so that during search which -returns a large number of results (>60% of segment size), the complement set -of matching documents is counted. Useful for queries that visit a large -number of documents, e.g. overview queries. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/ChunksIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/ChunksIntEncoder.java deleted file mode 100644 index 464f4e9abdf..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/ChunksIntEncoder.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoder} which encodes values in chunks. Implementations of this - * class assume the data which needs encoding consists of small, consecutive - * values, and therefore the encoder is able to compress them better. You can - * read more on the two implementations {@link FourFlagsIntEncoder} and - * {@link EightFlagsIntEncoder}. - *

- * Extensions of this class need to implement {@link #encode(IntsRef, BytesRef)} - * in order to build the proper indicator (flags). When enough values were - * accumulated (typically the batch size), extensions can call - * {@link #encodeChunk(BytesRef)} to flush the indicator and the rest of the - * values. - *

- * NOTE: flags encoders do not accept values ≤ 0 (zero) in their - * {@link #encode(IntsRef, BytesRef)}. For performance reasons they do not check - * that condition, however if such value is passed the result stream may be - * corrupt or an exception will be thrown. Also, these encoders perform the best - * when there are many consecutive small values (depends on the encoder - * implementation). If that is not the case, the encoder will occupy 1 more byte - * for every batch number of integers, over whatever - * {@link VInt8IntEncoder} would have occupied. Therefore make sure to check - * whether your data fits into the conditions of the specific encoder. - *

- * For the reasons mentioned above, these encoders are usually chained with - * {@link UniqueValuesIntEncoder} and {@link DGapIntEncoder}. - * - * @lucene.experimental - */ -public abstract class ChunksIntEncoder extends IntEncoder { - - /** Holds the values which must be encoded, outside the indicator. */ - protected final IntsRef encodeQueue; - - /** Represents bits flag byte. */ - protected int indicator = 0; - - /** Counts the current ordinal of the encoded value. */ - protected byte ordinal = 0; - - protected ChunksIntEncoder(int chunkSize) { - encodeQueue = new IntsRef(chunkSize); - } - - /** - * Encodes the values of the current chunk. First it writes the indicator, and - * then it encodes the values outside the indicator. - */ - protected void encodeChunk(BytesRef buf) { - // ensure there's enough room in the buffer - int maxBytesRequired = buf.length + 1 + encodeQueue.length * 4; /* indicator + at most 4 bytes per positive VInt */ - if (buf.bytes.length < maxBytesRequired) { - buf.grow(maxBytesRequired); - } - - buf.bytes[buf.length++] = ((byte) indicator); - for (int i = 0; i < encodeQueue.length; i++) { - // it is better if the encoding is inlined like so, and not e.g. - // in a utility method - int value = encodeQueue.ints[i]; - if ((value & ~0x7F) == 0) { - buf.bytes[buf.length] = (byte) value; - buf.length++; - } else if ((value & ~0x3FFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 1] = (byte) (value & 0x7F); - buf.length += 2; - } else if ((value & ~0x1FFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 2] = (byte) (value & 0x7F); - buf.length += 3; - } else if ((value & ~0xFFFFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 3] = (byte) (value & 0x7F); - buf.length += 4; - } else { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xF0000000) >> 28)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 3] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 4] = (byte) (value & 0x7F); - buf.length += 5; - } - } - - ordinal = 0; - indicator = 0; - encodeQueue.length = 0; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntDecoder.java deleted file mode 100644 index 5537663ba1a..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntDecoder.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntDecoder} which wraps another decoder and reverts the d-gap that - * was encoded by {@link DGapIntEncoder}. - * - * @lucene.experimental - */ -public final class DGapIntDecoder extends IntDecoder { - - private final IntDecoder decoder; - - public DGapIntDecoder(IntDecoder decoder) { - this.decoder = decoder; - } - - @Override - public void decode(BytesRef buf, IntsRef values) { - decoder.decode(buf, values); - int prev = 0; - for (int i = 0; i < values.length; i++) { - values.ints[i] += prev; - prev = values.ints[i]; - } - } - - @Override - public String toString() { - return "DGap(" + decoder.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntEncoder.java deleted file mode 100644 index 0aaf5d3d493..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapIntEncoder.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoderFilter} which encodes the gap between the given values, - * rather than the values themselves. This encoder usually yields better - * encoding performance space-wise (i.e., the final encoded values consume less - * space) if the values are 'close' to each other. - *

- * NOTE: this encoder assumes the values are given to - * {@link #encode(IntsRef, BytesRef)} in an ascending sorted manner, which ensures only - * positive values are encoded and thus yields better performance. If you are - * not sure whether the values are sorted or not, it is possible to chain this - * encoder with {@link SortingIntEncoder} to ensure the values will be - * sorted before encoding. - * - * @lucene.experimental - */ -public final class DGapIntEncoder extends IntEncoderFilter { - - /** Initializes with the given encoder. */ - public DGapIntEncoder(IntEncoder encoder) { - super(encoder); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - int prev = 0; - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - int tmp = values.ints[i]; - values.ints[i] -= prev; - prev = tmp; - } - encoder.encode(values, buf); - } - - @Override - public IntDecoder createMatchingDecoder() { - return new DGapIntDecoder(encoder.createMatchingDecoder()); - } - - @Override - public String toString() { - return "DGap(" + encoder.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntDecoder.java deleted file mode 100644 index c72c1185a8b..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntDecoder.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; -import org.apache.lucene.util.RamUsageEstimator; - -/* - * 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. - */ - -/** - * Decodes values encoded by {@link DGapVInt8IntDecoder}. - * - * @lucene.experimental - */ -public final class DGapVInt8IntDecoder extends IntDecoder { - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - - // grow the buffer up front, even if by a large number of values (buf.length) - // that saves the need to check inside the loop for every decoded value if - // the buffer needs to grow. - if (values.ints.length < buf.length) { - values.ints = new int[ArrayUtil.oversize(buf.length, RamUsageEstimator.NUM_BYTES_INT)]; - } - - // it is better if the decoding is inlined like so, and not e.g. - // in a utility method - int upto = buf.offset + buf.length; - int value = 0; - int offset = buf.offset; - int prev = 0; - while (offset < upto) { - byte b = buf.bytes[offset++]; - if (b >= 0) { - values.ints[values.length] = ((value << 7) | b) + prev; - value = 0; - prev = values.ints[values.length]; - values.length++; - } else { - value = (value << 7) | (b & 0x7F); - } - } - } - - @Override - public String toString() { - return "DGapVInt8"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntEncoder.java deleted file mode 100644 index bc063835563..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/DGapVInt8IntEncoder.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoder} which implements variable length encoding for the gap - * between values. It's a specialized form of the combination of - * {@link DGapIntEncoder} and {@link VInt8IntEncoder}. - * - * @see VInt8IntEncoder - * @see DGapIntEncoder - * - * @lucene.experimental - */ -public final class DGapVInt8IntEncoder extends IntEncoder { - - @Override - public void encode(IntsRef values, BytesRef buf) { - buf.offset = buf.length = 0; - int maxBytesNeeded = 5 * values.length; // at most 5 bytes per VInt - if (buf.bytes.length < maxBytesNeeded) { - buf.grow(maxBytesNeeded); - } - - int upto = values.offset + values.length; - int prev = 0; - for (int i = values.offset; i < upto; i++) { - // it is better if the encoding is inlined like so, and not e.g. - // in a utility method - int value = values.ints[i] - prev; - if ((value & ~0x7F) == 0) { - buf.bytes[buf.length] = (byte) value; - buf.length++; - } else if ((value & ~0x3FFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 1] = (byte) (value & 0x7F); - buf.length += 2; - } else if ((value & ~0x1FFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 2] = (byte) (value & 0x7F); - buf.length += 3; - } else if ((value & ~0xFFFFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 3] = (byte) (value & 0x7F); - buf.length += 4; - } else { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xF0000000) >> 28)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 3] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 4] = (byte) (value & 0x7F); - buf.length += 5; - } - prev = values.ints[i]; - } - } - - @Override - public IntDecoder createMatchingDecoder() { - return new DGapVInt8IntDecoder(); - } - - @Override - public String toString() { - return "DGapVInt8"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntDecoder.java deleted file mode 100644 index 3bf12efcd91..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntDecoder.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Decodes values encoded with {@link EightFlagsIntEncoder}. - * - * @lucene.experimental - */ -public class EightFlagsIntDecoder extends IntDecoder { - - /* - * Holds all combinations of indicator for fast decoding (saves time - * on real-time bit manipulation) - */ - private static final byte[][] DECODE_TABLE = new byte[256][8]; - - /** Generating all combinations of indicator into separate flags. */ - static { - for (int i = 256; i != 0;) { - --i; - for (int j = 8; j != 0;) { - --j; - DECODE_TABLE[i][j] = (byte) ((i >>> j) & 0x1); - } - } - } - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - int upto = buf.offset + buf.length; - int offset = buf.offset; - while (offset < upto) { - // read indicator - int indicator = buf.bytes[offset++] & 0xFF; - int ordinal = 0; - - int capacityNeeded = values.length + 8; - if (values.ints.length < capacityNeeded) { - values.grow(capacityNeeded); - } - - // process indicator, until we read 8 values, or end-of-buffer - while (ordinal != 8) { - if (DECODE_TABLE[indicator][ordinal++] == 0) { - if (offset == upto) { // end of buffer - return; - } - // it is better if the decoding is inlined like so, and not e.g. - // in a utility method - int value = 0; - while (true) { - byte b = buf.bytes[offset++]; - if (b >= 0) { - values.ints[values.length++] = ((value << 7) | b) + 2; - break; - } else { - value = (value << 7) | (b & 0x7F); - } - } - } else { - values.ints[values.length++] = 1; - } - } - } - } - - @Override - public String toString() { - return "EightFlags(VInt8)"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntEncoder.java deleted file mode 100644 index 5b1fec82bd2..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/EightFlagsIntEncoder.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link ChunksIntEncoder} which encodes data in chunks of 8. Every group - * starts with a single byte (called indicator) which represents 8 - 1 bit - * flags, where the value: - *

    - *
  • 1 means the encoded value is '1' - *
  • 0 means the value is encoded using {@link VInt8IntEncoder}, and the - * encoded bytes follow the indicator.
    - * Since value 0 is illegal, and 1 is encoded in the indicator, the actual value - * that is encoded is value-2, which saves some more bits. - *
- * Encoding example: - *
    - *
  • Original values: 6, 16, 5, 9, 7, 1 - *
  • After sorting: 1, 5, 6, 7, 9, 16 - *
  • D-Gap computing: 1, 4, 1, 1, 2, 5 (so far - done by - * {@link DGapIntEncoder}) - *
  • Encoding: 1,0,1,1,0,0,0,0 as the indicator, by 2 (4-2), 0 (2-2), 3 (5-2). - *
  • Binary encode: 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 00000010 00000000 - * 00000011 (indicator is underlined).
    - * NOTE: the order of the values in the indicator is lsb ⇒ msb, - * which allows for more efficient decoding. - *
- * - * @lucene.experimental - */ -public class EightFlagsIntEncoder extends ChunksIntEncoder { - - /* - * Holds all combinations of indicator flags for fast encoding (saves - * time on bit manipulation at encode time) - */ - private static final byte[] ENCODE_TABLE = new byte[] { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, (byte) 0x80 }; - - public EightFlagsIntEncoder() { - super(8); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - buf.offset = buf.length = 0; - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - int value = values.ints[i]; - if (value == 1) { - indicator |= ENCODE_TABLE[ordinal]; - } else { - encodeQueue.ints[encodeQueue.length++] = value - 2; - } - ++ordinal; - - // encode the chunk and the indicator - if (ordinal == 8) { - encodeChunk(buf); - } - } - - // encode remaining values - if (ordinal != 0) { - encodeChunk(buf); - } - } - - @Override - public IntDecoder createMatchingDecoder() { - return new EightFlagsIntDecoder(); - } - - @Override - public String toString() { - return "EightFlags(VInt)"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntDecoder.java deleted file mode 100644 index b2cb5d1232f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntDecoder.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Decodes values encoded with {@link FourFlagsIntEncoder}. - * - * @lucene.experimental - */ -public class FourFlagsIntDecoder extends IntDecoder { - - /** - * Holds all combinations of indicator for fast decoding (saves time - * on real-time bit manipulation) - */ - private final static byte[][] DECODE_TABLE = new byte[256][4]; - - /** Generating all combinations of indicator into separate flags. */ - static { - for (int i = 256; i != 0;) { - --i; - for (int j = 4; j != 0;) { - --j; - DECODE_TABLE[i][j] = (byte) ((i >>> (j << 1)) & 0x3); - } - } - } - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - int upto = buf.offset + buf.length; - int offset = buf.offset; - while (offset < upto) { - // read indicator - int indicator = buf.bytes[offset++] & 0xFF; - int ordinal = 0; - - int capacityNeeded = values.length + 4; - if (values.ints.length < capacityNeeded) { - values.grow(capacityNeeded); - } - - while (ordinal != 4) { - byte decodeVal = DECODE_TABLE[indicator][ordinal++]; - if (decodeVal == 0) { - if (offset == upto) { // end of buffer - return; - } - // it is better if the decoding is inlined like so, and not e.g. - // in a utility method - int value = 0; - while (true) { - byte b = buf.bytes[offset++]; - if (b >= 0) { - values.ints[values.length++] = ((value << 7) | b) + 4; - break; - } else { - value = (value << 7) | (b & 0x7F); - } - } - } else { - values.ints[values.length++] = decodeVal; - } - } - } - } - - @Override - public String toString() { - return "FourFlags(VInt)"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntEncoder.java deleted file mode 100644 index edf448e47fa..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/FourFlagsIntEncoder.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link ChunksIntEncoder} which encodes values in chunks of 4. Every group - * starts with a single byte (called indicator) which represents 4 - 2 bit - * flags, where the values: - *
    - *
  • 1, 2 or 3 mean the encoded value is '1', '2' or '3' respectively. - *
  • 0 means the value is encoded using {@link VInt8IntEncoder}, and the - * encoded bytes follow the indicator.
    - * Since value 0 is illegal, and 1-3 are encoded in the indicator, the actual - * value that is encoded is value-4, which saves some more bits. - *
- * Encoding example: - *
    - *
  • Original values: 6, 16, 5, 9, 7, 1, 11 - *
  • After sorting: 1, 5, 6, 7, 9, 11, 16 - *
  • D-Gap computing: 1, 4, 1, 1, 2, 5 (so far - done by - * {@link DGapIntEncoder}) - *
  • Encoding: 1,0,1,1 as the first indicator, followed by 0 (4-4), than - * 2,0,0,0 as the second indicator, followed by 1 (5-4) encoded with. - *
  • Binary encode: 01 | 01 | 00 | 01 00000000 00 | 00 | 00 | 10 - * 00000001 (indicators are underlined).
    - * NOTE: the order of the values in the indicator is lsb ⇒ msb, - * which allows for more efficient decoding. - *
- * - * @lucene.experimental - */ -public class FourFlagsIntEncoder extends ChunksIntEncoder { - - /* - * Holds all combinations of indicator flags for fast encoding (saves - * time on bit manipulation @ encode time) - */ - private static final byte[][] ENCODE_TABLE = new byte[][] { - new byte[] { 0x00, 0x00, 0x00, 0x00 }, - new byte[] { 0x01, 0x04, 0x10, 0x40 }, - new byte[] { 0x02, 0x08, 0x20, (byte) 0x80 }, - new byte[] { 0x03, 0x0C, 0x30, (byte) 0xC0 }, - }; - - public FourFlagsIntEncoder() { - super(4); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - buf.offset = buf.length = 0; - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - int value = values.ints[i]; - if (value <= 3) { - indicator |= ENCODE_TABLE[value][ordinal]; - } else { - encodeQueue.ints[encodeQueue.length++] = value - 4; - } - ++ordinal; - - // encode the chunk and the indicator - if (ordinal == 4) { - encodeChunk(buf); - } - } - - // encode remaining values - if (ordinal != 0) { - encodeChunk(buf); - } - } - - @Override - public IntDecoder createMatchingDecoder() { - return new FourFlagsIntDecoder(); - } - - @Override - public String toString() { - return "FourFlags(VInt)"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntDecoder.java deleted file mode 100644 index a46d28c5480..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntDecoder.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Decodes integers from a set {@link BytesRef}. - * - * @lucene.experimental - */ -public abstract class IntDecoder { - - /** - * Decodes the values from the buffer into the given {@link IntsRef}. Note - * that {@code values.offset} is set to 0, and {@code values.length} is - * updated to denote the number of decoded values. - */ - public abstract void decode(BytesRef buf, IntsRef values); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoder.java deleted file mode 100644 index 5d3e74df765..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoder.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Encodes integers to a set {@link BytesRef}. For convenience, each encoder - * implements {@link #createMatchingDecoder()} for easy access to the matching - * decoder. - * - * @lucene.experimental - */ -public abstract class IntEncoder { - - public IntEncoder() {} - - /** - * Encodes the values to the given buffer. Note that the buffer's offset and - * length are set to 0. - */ - public abstract void encode(IntsRef values, BytesRef buf); - - /** - * Returns an {@link IntDecoder} which can decode the values that were encoded - * with this encoder. - */ - public abstract IntDecoder createMatchingDecoder(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoderFilter.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoderFilter.java deleted file mode 100644 index 3c1f24a7bf5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/IntEncoderFilter.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apache.lucene.facet.encoding; - - -/* - * 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. - */ - -/** - * An abstract implementation of {@link IntEncoder} which wraps another encoder. - * - * @lucene.experimental - */ -public abstract class IntEncoderFilter extends IntEncoder { - - protected final IntEncoder encoder; - - protected IntEncoderFilter(IntEncoder encoder) { - this.encoder = encoder; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntDecoder.java deleted file mode 100644 index 5819b621f3f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntDecoder.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Decodes values encoded encoded with {@link NOnesIntEncoder}. - * - * @lucene.experimental - */ -public class NOnesIntDecoder extends FourFlagsIntDecoder { - - // Number of consecutive '1's to generate upon decoding a '2' - private final int n; - private final IntsRef internalBuffer; - - /** - * Constructs a decoder with a given N (Number of consecutive '1's which are - * translated into a single target value '2'. - */ - public NOnesIntDecoder(int n) { - this.n = n; - // initial size (room for 100 integers) - internalBuffer = new IntsRef(100); - } - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - internalBuffer.length = 0; - super.decode(buf, internalBuffer); - if (values.ints.length < internalBuffer.length) { - // need space for internalBuffer.length to internalBuffer.length*N, - // grow mildly at first - values.grow(internalBuffer.length * n/2); - } - - for (int i = 0; i < internalBuffer.length; i++) { - int decode = internalBuffer.ints[i]; - if (decode == 1) { - if (values.length == values.ints.length) { - values.grow(values.length + 10); // grow by few items, however not too many - } - // 1 is 1 - values.ints[values.length++] = 1; - } else if (decode == 2) { - if (values.length + n >= values.ints.length) { - values.grow(values.length + n); // grow by few items, however not too many - } - // '2' means N 1's - for (int j = 0; j < n; j++) { - values.ints[values.length++] = 1; - } - } else { - if (values.length == values.ints.length) { - values.grow(values.length + 10); // grow by few items, however not too many - } - // any other value is val-1 - values.ints[values.length++] = decode - 1; - } - } - } - - @Override - public String toString() { - return "NOnes(" + n + ") (" + super.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntEncoder.java deleted file mode 100644 index 6c117de1f9c..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/NOnesIntEncoder.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A variation of {@link FourFlagsIntEncoder} which translates the data as - * follows: - *
    - *
  • Values ≥ 2 are trnalsated to value+1 (2 ⇒ 3, 3 - * ⇒ 4 and so forth). - *
  • Any N occurrences of 1 are encoded as a single 2. - *
  • Otherwise, each 1 is encoded as 1. - *
- *

- * Encoding examples: - *

    - *
  • N = 4: the data 1,1,1,1,1 is translated to: 2, 1 - *
  • N = 3: the data 1,2,3,4,1,1,1,1,5 is translated to 1,3,4,5,2,1,6 - *
- * NOTE: this encoder does not support values ≤ 0 and - * {@link Integer#MAX_VALUE}. 0 is not supported because it's not supported by - * {@link FourFlagsIntEncoder} and {@link Integer#MAX_VALUE} because this - * encoder translates N to N+1, which will cause an overflow and - * {@link Integer#MAX_VALUE} will become a negative number, which is not - * supported as well.
- * This does not mean you cannot encode {@link Integer#MAX_VALUE}. If it is not - * the first value to encode, and you wrap this encoder with - * {@link DGapIntEncoder}, then the value that will be sent to this encoder will - * be MAX_VAL - prev. - * - * @lucene.experimental - */ -public class NOnesIntEncoder extends FourFlagsIntEncoder { - - private final IntsRef internalBuffer; - - /** Number of consecutive '1's to be translated into single target value '2'. */ - private final int n; - - /** - * Constructs an encoder with a given value of N (N: Number of consecutive - * '1's to be translated into single target value '2'). - */ - public NOnesIntEncoder(int n) { - this.n = n; - internalBuffer = new IntsRef(n); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - internalBuffer.length = 0; - // make sure the internal buffer is large enough - if (values.length > internalBuffer.ints.length) { - internalBuffer.grow(values.length); - } - - int onesCounter = 0; - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - int value = values.ints[i]; - if (value == 1) { - // every N 1's should be encoded as '2' - if (++onesCounter == n) { - internalBuffer.ints[internalBuffer.length++] = 2; - onesCounter = 0; - } - } else { - // there might have been 1's that we need to encode - while (onesCounter > 0) { - --onesCounter; - internalBuffer.ints[internalBuffer.length++] = 1; - } - - // encode value as value+1 - internalBuffer.ints[internalBuffer.length++] = value + 1; - } - } - // there might have been 1's that we need to encode - while (onesCounter > 0) { - --onesCounter; - internalBuffer.ints[internalBuffer.length++] = 1; - } - super.encode(internalBuffer, buf); - } - - @Override - public IntDecoder createMatchingDecoder() { - return new NOnesIntDecoder(n); - } - - @Override - public String toString() { - return "NOnes(" + n + ") (" + super.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntDecoder.java deleted file mode 100644 index 82c489a071b..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntDecoder.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; -import org.apache.lucene.util.RamUsageEstimator; - -/* - * 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. - */ - -/** - * Decodes values encoded with {@link SimpleIntEncoder}. - * - * @lucene.experimental - */ -public final class SimpleIntDecoder extends IntDecoder { - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - int numValues = buf.length / 4; // every value is 4 bytes - if (values.ints.length < numValues) { // offset and length are 0 - values.ints = new int[ArrayUtil.oversize(numValues, RamUsageEstimator.NUM_BYTES_INT)]; - } - - int offset = buf.offset; - int upto = buf.offset + buf.length; - while (offset < upto) { - values.ints[values.length++] = - ((buf.bytes[offset++] & 0xFF) << 24) | - ((buf.bytes[offset++] & 0xFF) << 16) | - ((buf.bytes[offset++] & 0xFF) << 8) | - (buf.bytes[offset++] & 0xFF); - } - } - - @Override - public String toString() { - return "Simple"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntEncoder.java deleted file mode 100644 index f2eb6b919fe..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SimpleIntEncoder.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A simple {@link IntEncoder}, writing an integer as 4 raw bytes. * - * - * @lucene.experimental - */ -public final class SimpleIntEncoder extends IntEncoder { - - @Override - public void encode(IntsRef values, BytesRef buf) { - buf.offset = buf.length = 0; - // ensure there's enough room in the buffer - int bytesNeeded = values.length * 4; - if (buf.bytes.length < bytesNeeded) { - buf.grow(bytesNeeded); - } - - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - int value = values.ints[i]; - buf.bytes[buf.length++] = (byte) (value >>> 24); - buf.bytes[buf.length++] = (byte) ((value >> 16) & 0xFF); - buf.bytes[buf.length++] = (byte) ((value >> 8) & 0xFF); - buf.bytes[buf.length++] = (byte) (value & 0xFF); - } - } - - @Override - public IntDecoder createMatchingDecoder() { - return new SimpleIntDecoder(); - } - - @Override - public String toString() { - return "Simple"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SortingIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/SortingIntEncoder.java deleted file mode 100644 index c162c6150d1..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/SortingIntEncoder.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import java.util.Arrays; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoderFilter} which sorts the values to encode in ascending - * order before encoding them. - * - * @lucene.experimental - */ -public final class SortingIntEncoder extends IntEncoderFilter { - - /** Initializes with the given encoder. */ - public SortingIntEncoder(IntEncoder encoder) { - super(encoder); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - Arrays.sort(values.ints, values.offset, values.offset + values.length); - encoder.encode(values, buf); - } - - @Override - public IntDecoder createMatchingDecoder() { - return encoder.createMatchingDecoder(); - } - - @Override - public String toString() { - return "Sorting(" + encoder.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/UniqueValuesIntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/UniqueValuesIntEncoder.java deleted file mode 100644 index fe5388d1f3c..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/UniqueValuesIntEncoder.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoderFilter} which ensures only unique values are encoded. The - * implementation assumes the values given to {@link #encode(IntsRef, BytesRef)} are sorted. - * If this is not the case, you can chain this encoder with - * {@link SortingIntEncoder}. - * - * @lucene.experimental - */ -public final class UniqueValuesIntEncoder extends IntEncoderFilter { - - /** Constructs a new instance with the given encoder. */ - public UniqueValuesIntEncoder(IntEncoder encoder) { - super(encoder); - } - - @Override - public void encode(IntsRef values, BytesRef buf) { - int prev = values.ints[values.offset]; - int idx = values.offset + 1; - int upto = values.offset + values.length; - for (int i = idx; i < upto; i++) { - if (values.ints[i] != prev) { - values.ints[idx++] = values.ints[i]; - prev = values.ints[i]; - } - } - values.length = idx - values.offset; - encoder.encode(values, buf); - } - - @Override - public IntDecoder createMatchingDecoder() { - return encoder.createMatchingDecoder(); - } - - @Override - public String toString() { - return "Unique(" + encoder.toString() + ")"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntDecoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntDecoder.java deleted file mode 100644 index 785eafe9a12..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntDecoder.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; -import org.apache.lucene.util.RamUsageEstimator; - -/* - * 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. - */ - -/** - * Decodes values encoded by {@link VInt8IntEncoder}. - * - * @lucene.experimental - */ -public final class VInt8IntDecoder extends IntDecoder { - - @Override - public void decode(BytesRef buf, IntsRef values) { - values.offset = values.length = 0; - - // grow the buffer up front, even if by a large number of values (buf.length) - // that saves the need to check inside the loop for every decoded value if - // the buffer needs to grow. - if (values.ints.length < buf.length) { - values.ints = new int[ArrayUtil.oversize(buf.length, RamUsageEstimator.NUM_BYTES_INT)]; - } - - // it is better if the decoding is inlined like so, and not e.g. - // in a utility method - int upto = buf.offset + buf.length; - int value = 0; - int offset = buf.offset; - while (offset < upto) { - byte b = buf.bytes[offset++]; - if (b >= 0) { - values.ints[values.length++] = (value << 7) | b; - value = 0; - } else { - value = (value << 7) | (b & 0x7F); - } - } - } - - @Override - public String toString() { - return "VInt8"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntEncoder.java b/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntEncoder.java deleted file mode 100644 index 5fdda79edb5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/VInt8IntEncoder.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link IntEncoder} which implements variable length encoding. A number is - * encoded as follows: - *
    - *
  • If it is less than 127 and non-negative, i.e. uses only 7 bits, it is - * encoded as a single byte: 0bbbbbbb. - *
  • If it occupies more than 7 bits, it is represented as a series of bytes, - * each byte carrying 7 bits. All but the last byte have the MSB set, the last - * one has it unset. - *
- * Example: - *
    - *
  1. n = 117 = 01110101: This has less than 8 significant bits, therefore is - * encoded as 01110101 = 0x75. - *
  2. n = 100000 = (binary) 11000011010100000. This has 17 significant bits, - * thus needs three Vint8 bytes. Pad it to a multiple of 7 bits, then split it - * into chunks of 7 and add an MSB, 0 for the last byte, 1 for the others: - * 1|0000110 1|0001101 0|0100000 = 0x86 0x8D 0x20. - *
- * NOTE: although this encoder is not limited to values ≥ 0, it is not - * recommended for use with negative values, as their encoding will result in 5 - * bytes written to the output stream, rather than 4. For such values, either - * use {@link SimpleIntEncoder} or write your own version of variable length - * encoding, which can better handle negative values. - * - * @lucene.experimental - */ -public final class VInt8IntEncoder extends IntEncoder { - - @Override - public void encode(IntsRef values, BytesRef buf) { - buf.offset = buf.length = 0; - int maxBytesNeeded = 5 * values.length; // at most 5 bytes per VInt - if (buf.bytes.length < maxBytesNeeded) { - buf.grow(maxBytesNeeded); - } - - int upto = values.offset + values.length; - for (int i = values.offset; i < upto; i++) { - // it is better if the encoding is inlined like so, and not e.g. - // in a utility method - int value = values.ints[i]; - if ((value & ~0x7F) == 0) { - buf.bytes[buf.length] = (byte) value; - buf.length++; - } else if ((value & ~0x3FFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 1] = (byte) (value & 0x7F); - buf.length += 2; - } else if ((value & ~0x1FFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 2] = (byte) (value & 0x7F); - buf.length += 3; - } else if ((value & ~0xFFFFFFF) == 0) { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 3] = (byte) (value & 0x7F); - buf.length += 4; - } else { - buf.bytes[buf.length] = (byte) (0x80 | ((value & 0xF0000000) >> 28)); - buf.bytes[buf.length + 1] = (byte) (0x80 | ((value & 0xFE00000) >> 21)); - buf.bytes[buf.length + 2] = (byte) (0x80 | ((value & 0x1FC000) >> 14)); - buf.bytes[buf.length + 3] = (byte) (0x80 | ((value & 0x3F80) >> 7)); - buf.bytes[buf.length + 4] = (byte) (value & 0x7F); - buf.length += 5; - } - } - } - - @Override - public IntDecoder createMatchingDecoder() { - return new VInt8IntDecoder(); - } - - @Override - public String toString() { - return "VInt8"; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/encoding/package.html b/lucene/facet/src/java/org/apache/lucene/facet/encoding/package.html deleted file mode 100644 index b1b95bce7e3..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/encoding/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets Encoding - - -Offers various encoders and decoders for category ordinals. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/index/CategoryListBuilder.java b/lucene/facet/src/java/org/apache/lucene/facet/index/CategoryListBuilder.java deleted file mode 100644 index 6e204d5841e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/index/CategoryListBuilder.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apache.lucene.facet.index; - -import java.io.IOException; -import java.util.Map; - -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Builds a category list data by encoding the appropriate information for every - * category and ordinal given to {@link #build(IntsRef, Iterable)}. - * - * @lucene.experimental - */ -public interface CategoryListBuilder { - - /** Returns the encoded ordinals data. */ - public Map build(IntsRef ordinals, Iterable categories) throws IOException; - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java b/lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java deleted file mode 100644 index 1b4b6d33844..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.apache.lucene.facet.index; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.util.PartitionsUtils; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link CategoryListBuilder} which builds a counting list data by encoding - * the category ordinals into one or more {@link BytesRef}. Each - * {@link BytesRef} corresponds to a set of ordinals that belong to the same - * partition. When partitions are not enabled (i.e. - * {@link FacetIndexingParams#getPartitionSize()} returns - * {@link Integer#MAX_VALUE}), only one {@link BytesRef} is returned by this - * class. - *

- * Counting lists are used usually for computing the weight of categories by - * summing their number of occurrences (hence counting) in a result set. - */ -public class CountingListBuilder implements CategoryListBuilder { - - /** Specializes encoding ordinals when partitions are enabled/disabled. */ - private static abstract class OrdinalsEncoder { - OrdinalsEncoder() {} - public abstract Map encode(IntsRef ordinals); - } - - private static final class NoPartitionsOrdinalsEncoder extends OrdinalsEncoder { - - private final IntEncoder encoder; - private final String name = ""; - - NoPartitionsOrdinalsEncoder(CategoryListParams categoryListParams) { - encoder = categoryListParams.createEncoder(); - } - - @Override - public Map encode(IntsRef ordinals) { - final BytesRef bytes = new BytesRef(128); // should be enough for most common applications - encoder.encode(ordinals, bytes); - return Collections.singletonMap(name, bytes); - } - - } - - private static final class PerPartitionOrdinalsEncoder extends OrdinalsEncoder { - - private final FacetIndexingParams indexingParams; - private final CategoryListParams categoryListParams; - private final int partitionSize; - private final HashMap partitionEncoder = new HashMap(); - - PerPartitionOrdinalsEncoder(FacetIndexingParams indexingParams, CategoryListParams categoryListParams) { - this.indexingParams = indexingParams; - this.categoryListParams = categoryListParams; - this.partitionSize = indexingParams.getPartitionSize(); - } - - @Override - public HashMap encode(IntsRef ordinals) { - // build the partitionOrdinals map - final HashMap partitionOrdinals = new HashMap(); - for (int i = 0; i < ordinals.length; i++) { - int ordinal = ordinals.ints[i]; - final String name = PartitionsUtils.partitionNameByOrdinal(indexingParams, ordinal); - IntsRef partitionOrds = partitionOrdinals.get(name); - if (partitionOrds == null) { - partitionOrds = new IntsRef(32); - partitionOrdinals.put(name, partitionOrds); - partitionEncoder.put(name, categoryListParams.createEncoder()); - } - partitionOrds.ints[partitionOrds.length++] = ordinal % partitionSize; - } - - HashMap partitionBytes = new HashMap(); - for (Entry e : partitionOrdinals.entrySet()) { - String name = e.getKey(); - final IntEncoder encoder = partitionEncoder.get(name); - final BytesRef bytes = new BytesRef(128); // should be enough for most common applications - encoder.encode(e.getValue(), bytes); - partitionBytes.put(name, bytes); - } - return partitionBytes; - } - - } - - private final OrdinalsEncoder ordinalsEncoder; - private final TaxonomyWriter taxoWriter; - private final CategoryListParams clp; - - public CountingListBuilder(CategoryListParams categoryListParams, FacetIndexingParams indexingParams, - TaxonomyWriter taxoWriter) { - this.taxoWriter = taxoWriter; - this.clp = categoryListParams; - if (indexingParams.getPartitionSize() == Integer.MAX_VALUE) { - ordinalsEncoder = new NoPartitionsOrdinalsEncoder(categoryListParams); - } else { - ordinalsEncoder = new PerPartitionOrdinalsEncoder(indexingParams, categoryListParams); - } - } - - /** - * Every returned {@link BytesRef} corresponds to a single partition (as - * defined by {@link FacetIndexingParams#getPartitionSize()}) and the key - * denotes the partition ID. When no partitions are defined, the returned map - * contains only one value. - *

- * NOTE: the {@code ordinals} array is modified by adding parent - * ordinals to it. Also, some encoders may sort the array and remove duplicate - * ordinals. Therefore you may want to invoke this method after you finished - * processing the array for other purposes. - */ - @Override - public Map build(IntsRef ordinals, Iterable categories) throws IOException { - int upto = ordinals.length; // since we may add ordinals to IntsRef, iterate upto original length - - Iterator iter = categories.iterator(); - for (int i = 0; i < upto; i++) { - int ordinal = ordinals.ints[i]; - FacetLabel cp = iter.next(); - OrdinalPolicy op = clp.getOrdinalPolicy(cp.components[0]); - if (op != OrdinalPolicy.NO_PARENTS) { - // need to add parents too - int parent = taxoWriter.getParent(ordinal); - if (parent > 0) { - // only do this if the category is not a dimension itself, otherwise, it was just discarded by the 'if' below - while (parent > 0) { - ordinals.ints[ordinals.length++] = parent; - parent = taxoWriter.getParent(parent); - } - if (op == OrdinalPolicy.ALL_BUT_DIMENSION) { // discard the last added parent, which is the dimension - ordinals.length--; - } - } - } - } - return ordinalsEncoder.encode(ordinals); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/index/DrillDownStream.java b/lucene/facet/src/java/org/apache/lucene/facet/index/DrillDownStream.java deleted file mode 100644 index a40832a88c1..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/index/DrillDownStream.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.apache.lucene.facet.index; - -import java.io.IOException; -import java.util.Iterator; - -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link TokenStream} which creates category drill-down terms. - * - * @lucene.experimental - */ -public class DrillDownStream extends TokenStream { - - private final FacetIndexingParams indexingParams; - private final Iterator categories; - private final CharTermAttribute termAttribute; - - private FacetLabel current; - private boolean isParent; - - public DrillDownStream(Iterable categories, FacetIndexingParams indexingParams) { - termAttribute = addAttribute(CharTermAttribute.class); - this.categories = categories.iterator(); - this.indexingParams = indexingParams; - } - - protected void addAdditionalAttributes(FacetLabel category, boolean isParent) { - // a hook for AssociationsDrillDownStream to add the associations payload to - // the drill-down terms - } - - @Override - public final boolean incrementToken() throws IOException { - if (current.length == 0) { - if (!categories.hasNext()) { - return false; // no more categories - } - current = categories.next(); - termAttribute.resizeBuffer(current.fullPathLength()); - isParent = false; - } - - // copy current as drill-down term (it's either the leaf node or PathPolicy - // accepted it. - int nChars = indexingParams.drillDownTermText(current, termAttribute.buffer()); - termAttribute.setLength(nChars); - addAdditionalAttributes(current, isParent); - - // prepare current for next call by trimming the last component (parents) - current = current.subpath(current.length - 1); - isParent = true; - return true; - } - - @Override - public void reset() throws IOException { - current = categories.next(); - termAttribute.resizeBuffer(current.fullPathLength()); - isParent = false; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/index/FacetFields.java b/lucene/facet/src/java/org/apache/lucene/facet/index/FacetFields.java deleted file mode 100644 index 52ad945ea7f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/index/FacetFields.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.apache.lucene.facet.index; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map.Entry; -import java.util.Map; - -import org.apache.lucene.document.BinaryDocValuesField; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.FieldType; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.index.FieldInfo.IndexOptions; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A utility class for adding facet fields to a document. Usually one field will - * be added for all facets, however per the - * {@link FacetIndexingParams#getCategoryListParams(FacetLabel)}, one field - * may be added for every group of facets. - * - * @lucene.experimental - */ -public class FacetFields { - - // The drill-down field is added with a TokenStream, hence why it's based on - // TextField type. However in practice, it is added just like StringField. - // Therefore we set its IndexOptions to DOCS_ONLY. - private static final FieldType DRILL_DOWN_TYPE = new FieldType(TextField.TYPE_NOT_STORED); - static { - DRILL_DOWN_TYPE.setIndexOptions(IndexOptions.DOCS_ONLY); - DRILL_DOWN_TYPE.setOmitNorms(true); - DRILL_DOWN_TYPE.freeze(); - } - - protected final TaxonomyWriter taxonomyWriter; - - protected final FacetIndexingParams indexingParams; - - /** - * Constructs a new instance with the {@link FacetIndexingParams#DEFAULT - * default} facet indexing params. - * - * @param taxonomyWriter - * used to resolve given categories to ordinals - */ - public FacetFields(TaxonomyWriter taxonomyWriter) { - this(taxonomyWriter, FacetIndexingParams.DEFAULT); - } - - /** - * Constructs a new instance with the given facet indexing params. - * - * @param taxonomyWriter - * used to resolve given categories to ordinals - * @param params - * determines under which fields the categories should be indexed - */ - public FacetFields(TaxonomyWriter taxonomyWriter, FacetIndexingParams params) { - this.taxonomyWriter = taxonomyWriter; - this.indexingParams = params; - } - - /** - * Creates a mapping between a {@link CategoryListParams} and all - * {@link FacetLabel categories} that are associated with it. - */ - protected Map> createCategoryListMapping( - Iterable categories) { - if (indexingParams.getAllCategoryListParams().size() == 1) { - return Collections.singletonMap(indexingParams.getCategoryListParams(null), categories); - } - HashMap> categoryLists = - new HashMap>(); - for (FacetLabel cp : categories) { - // each category may be indexed under a different field, so add it to the right list. - CategoryListParams clp = indexingParams.getCategoryListParams(cp); - List list = (List) categoryLists.get(clp); - if (list == null) { - list = new ArrayList(); - categoryLists.put(clp, list); - } - list.add(cp); - } - return categoryLists; - } - - /** - * Returns the category list data, as a mapping from key to {@link BytesRef} - * which includes the encoded data. Every ordinal in {@code ordinals} - * corrspond to a {@link FacetLabel} returned from {@code categories}. - */ - protected Map getCategoryListData(CategoryListParams categoryListParams, - IntsRef ordinals, Iterable categories /* needed for AssociationsFacetFields */) - throws IOException { - return new CountingListBuilder(categoryListParams, indexingParams, taxonomyWriter).build(ordinals, categories); - } - - /** - * Returns a {@link DrillDownStream} for writing the categories drill-down - * terms. - */ - protected DrillDownStream getDrillDownStream(Iterable categories) { - return new DrillDownStream(categories, indexingParams); - } - - /** - * Returns the {@link FieldType} with which the drill-down terms should be - * indexed. The default is {@link IndexOptions#DOCS_ONLY}. - */ - protected FieldType drillDownFieldType() { - return DRILL_DOWN_TYPE; - } - - /** - * Add the counting list data to the document under the given field. Note that - * the field is determined by the {@link CategoryListParams}. - */ - protected void addCountingListData(Document doc, Map categoriesData, String field) { - for (Entry entry : categoriesData.entrySet()) { - doc.add(new BinaryDocValuesField(field + entry.getKey(), entry.getValue())); - } - } - - /** Adds the needed facet fields to the document. */ - public void addFields(Document doc, Iterable categories) throws IOException { - if (categories == null) { - throw new IllegalArgumentException("categories should not be null"); - } - - // TODO: add reuse capabilities to this class, per CLP objects: - // - drill-down field - // - counting list field - // - DrillDownStream - // - CountingListStream - - final Map> categoryLists = createCategoryListMapping(categories); - - // for each CLP we add a different field for drill-down terms as well as for - // counting list data. - IntsRef ordinals = new IntsRef(32); // should be enough for most common applications - for (Entry> e : categoryLists.entrySet()) { - final CategoryListParams clp = e.getKey(); - final String field = clp.field; - - // build category list data - ordinals.length = 0; // reset - int maxNumOrds = 0; - for (FacetLabel cp : e.getValue()) { - int ordinal = taxonomyWriter.addCategory(cp); - maxNumOrds += cp.length; // ordinal and potentially all parents - if (ordinals.ints.length < maxNumOrds) { - ordinals.grow(maxNumOrds); - } - ordinals.ints[ordinals.length++] = ordinal; - } - Map categoriesData = getCategoryListData(clp, ordinals, e.getValue()); - - // add the counting list data - addCountingListData(doc, categoriesData, field); - - // add the drill-down field - DrillDownStream drillDownStream = getDrillDownStream(e.getValue()); - Field drillDown = new Field(field, drillDownStream, drillDownFieldType()); - doc.add(drillDown); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/index/package.html b/lucene/facet/src/java/org/apache/lucene/facet/index/package.html deleted file mode 100644 index bc9b2ee6c70..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/index/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets indexing code - - -Facets indexing code. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/AdaptiveFacetsAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/AdaptiveFacetsAccumulator.java deleted file mode 100644 index fb9b377f527..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/AdaptiveFacetsAccumulator.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; -import java.util.List; - -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.sampling.RandomSampler; -import org.apache.lucene.facet.sampling.Sampler; -import org.apache.lucene.facet.sampling.SamplingAccumulator; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetsAccumulator; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * {@link FacetsAccumulator} whose behavior regarding complements, sampling, - * etc. is not set up front but rather is determined at accumulation time - * according to the statistics of the accumulated set of documents and the - * index. - *

- * Note: Sampling accumulation (Accumulation over a sampled-set of the results), - * does not guarantee accurate values for - * {@link FacetResult#getNumValidDescendants()}. - * - * @lucene.experimental - */ -public final class AdaptiveFacetsAccumulator extends OldFacetsAccumulator { - - private Sampler sampler = new RandomSampler(); - - /** - * Create an {@link AdaptiveFacetsAccumulator} - * @see OldFacetsAccumulator#OldFacetsAccumulator(FacetSearchParams, IndexReader, TaxonomyReader) - */ - public AdaptiveFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader) { - super(searchParams, indexReader, taxonomyReader); - } - - /** - * Create an {@link AdaptiveFacetsAccumulator} - * - * @see OldFacetsAccumulator#OldFacetsAccumulator(FacetSearchParams, - * IndexReader, TaxonomyReader, FacetArrays) - */ - public AdaptiveFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader, FacetArrays facetArrays) { - super(searchParams, indexReader, taxonomyReader, facetArrays); - } - - /** - * Set the sampler. - * @param sampler sampler to set - */ - public void setSampler(Sampler sampler) { - this.sampler = sampler; - } - - @Override - public List accumulate(ScoredDocIDs docids) throws IOException { - OldFacetsAccumulator delegee = appropriateFacetCountingAccumulator(docids); - - if (delegee == this) { - return super.accumulate(docids); - } - - return delegee.accumulate(docids); - } - - /** - * Compute the appropriate facet accumulator to use. - * If no special/clever adaptation is possible/needed return this (self). - */ - private OldFacetsAccumulator appropriateFacetCountingAccumulator(ScoredDocIDs docids) { - // Verify that searchPareams permit sampling/complement/etc... otherwise do default - if (!mayComplement()) { - return this; - } - - // Now we're sure we can use the sampling methods as we're in a counting only mode - - // Verify that sampling is enabled and required ... otherwise do default - if (sampler == null || !sampler.shouldSample(docids)) { - return this; - } - - SamplingAccumulator samplingAccumulator = new SamplingAccumulator(sampler, searchParams, indexReader, taxonomyReader); - samplingAccumulator.setComplementThreshold(getComplementThreshold()); - return samplingAccumulator; - } - - /** - * @return the sampler in effect - */ - public final Sampler getSampler() { - return sampler; - } -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/Aggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/Aggregator.java deleted file mode 100644 index 5ac80bf049d..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/Aggregator.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * Aggregates the categories of documents given to - * {@link #aggregate(int, float, IntsRef)}. Note that the document IDs are local - * to the reader given to {@link #setNextReader(AtomicReaderContext)}. - * - * @lucene.experimental - */ -public interface Aggregator { - - /** - * Sets the {@link AtomicReaderContext} for which - * {@link #aggregate(int, float, IntsRef)} calls will be made. If this method - * returns false, {@link #aggregate(int, float, IntsRef)} should not be called - * for this reader. - */ - public boolean setNextReader(AtomicReaderContext context) throws IOException; - - /** - * Aggregate the ordinals of the given document ID (and its score). The given - * ordinals offset is always zero. - */ - public void aggregate(int docID, float score, IntsRef ordinals) throws IOException; - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/ComplementCountingAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/ComplementCountingAggregator.java deleted file mode 100644 index d5db7d4e96e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/ComplementCountingAggregator.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; - -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link CountingAggregator} used during complement counting. - * - * @lucene.experimental - */ -public class ComplementCountingAggregator extends CountingAggregator { - - public ComplementCountingAggregator(int[] counterArray) { - super(counterArray); - } - - @Override - public void aggregate(int docID, float score, IntsRef ordinals) throws IOException { - for (int i = 0; i < ordinals.length; i++) { - int ord = ordinals.ints[i]; - assert counterArray[ord] != 0 : "complement aggregation: count is about to become negative for ordinal " + ord; - --counterArray[ord]; - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/CountingAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/CountingAggregator.java deleted file mode 100644 index 90be8be18b1..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/CountingAggregator.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link Aggregator} which updates a counter array with the size of the - * whole taxonomy, counting the number of times each category appears in the - * given set of documents. - * - * @lucene.experimental - */ -public class CountingAggregator implements Aggregator { - - protected int[] counterArray; - - public CountingAggregator(int[] counterArray) { - this.counterArray = counterArray; - } - - @Override - public void aggregate(int docID, float score, IntsRef ordinals) throws IOException { - for (int i = 0; i < ordinals.length; i++) { - counterArray[ordinals.ints[i]]++; - } - } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != this.getClass()) { - return false; - } - CountingAggregator that = (CountingAggregator) obj; - return that.counterArray == this.counterArray; - } - - @Override - public int hashCode() { - return counterArray == null ? 0 : counterArray.hashCode(); - } - - @Override - public boolean setNextReader(AtomicReaderContext context) throws IOException { - return true; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/MatchingDocsAsScoredDocIDs.java b/lucene/facet/src/java/org/apache/lucene/facet/old/MatchingDocsAsScoredDocIDs.java deleted file mode 100644 index 505ac655401..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/MatchingDocsAsScoredDocIDs.java +++ /dev/null @@ -1,174 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; - -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.search.DocIdSet; -import org.apache.lucene.search.DocIdSetIterator; - -/* - * 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. - */ - -/** - * Represents {@link MatchingDocs} as {@link ScoredDocIDs}. - * - * @lucene.experimental - */ -public class MatchingDocsAsScoredDocIDs implements ScoredDocIDs { - - // TODO remove this class once we get rid of ScoredDocIDs - - final List matchingDocs; - final int size; - - public MatchingDocsAsScoredDocIDs(List matchingDocs) { - this.matchingDocs = matchingDocs; - int totalSize = 0; - for (MatchingDocs md : matchingDocs) { - totalSize += md.totalHits; - } - this.size = totalSize; - } - - @Override - public ScoredDocIDsIterator iterator() throws IOException { - return new ScoredDocIDsIterator() { - - final Iterator mdIter = matchingDocs.iterator(); - - int scoresIdx = 0; - int doc = 0; - MatchingDocs current; - int currentLength; - boolean done = false; - - @Override - public boolean next() { - if (done) { - return false; - } - - while (current == null) { - if (!mdIter.hasNext()) { - done = true; - return false; - } - current = mdIter.next(); - currentLength = current.bits.length(); - doc = 0; - scoresIdx = 0; - - if (doc >= currentLength || (doc = current.bits.nextSetBit(doc)) == -1) { - current = null; - } else { - doc = -1; // we're calling nextSetBit later on - } - } - - ++doc; - if (doc >= currentLength || (doc = current.bits.nextSetBit(doc)) == -1) { - current = null; - return next(); - } - - return true; - } - - @Override - public float getScore() { - return current.scores == null ? ScoredDocIDsIterator.DEFAULT_SCORE : current.scores[scoresIdx++]; - } - - @Override - public int getDocID() { - return done ? DocIdSetIterator.NO_MORE_DOCS : doc + current.context.docBase; - } - }; - } - - @Override - public DocIdSet getDocIDs() { - return new DocIdSet() { - - final Iterator mdIter = matchingDocs.iterator(); - int doc = 0; - MatchingDocs current; - int currentLength; - boolean done = false; - - @Override - public DocIdSetIterator iterator() throws IOException { - return new DocIdSetIterator() { - - @Override - public int nextDoc() throws IOException { - if (done) { - return DocIdSetIterator.NO_MORE_DOCS; - } - - while (current == null) { - if (!mdIter.hasNext()) { - done = true; - return DocIdSetIterator.NO_MORE_DOCS; - } - current = mdIter.next(); - currentLength = current.bits.length(); - doc = 0; - - if (doc >= currentLength || (doc = current.bits.nextSetBit(doc)) == -1) { - current = null; - } else { - doc = -1; // we're calling nextSetBit later on - } - } - - ++doc; - if (doc >= currentLength || (doc = current.bits.nextSetBit(doc)) == -1) { - current = null; - return nextDoc(); - } - - return doc + current.context.docBase; - } - - @Override - public int docID() { - return doc + current.context.docBase; - } - - @Override - public long cost() { - return size; - } - - @Override - public int advance(int target) throws IOException { - throw new UnsupportedOperationException("not supported"); - } - }; - } - }; - } - - @Override - public int size() { - return size; - } - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/OldFacetsAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/OldFacetsAccumulator.java deleted file mode 100644 index a102b7cefbb..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/OldFacetsAccumulator.java +++ /dev/null @@ -1,457 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import org.apache.lucene.facet.complements.TotalFacetCounts; -import org.apache.lucene.facet.complements.TotalFacetCountsCache; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.partitions.IntermediateFacetResult; -import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; -import org.apache.lucene.facet.sampling.Sampler.OverSampledFacetRequest; -import org.apache.lucene.facet.search.CategoryListIterator; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetsAccumulator; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver; -import org.apache.lucene.facet.search.OrdinalValueResolver.FloatValueResolver; -import org.apache.lucene.facet.search.OrdinalValueResolver.IntValueResolver; -import org.apache.lucene.facet.search.SumScoreFacetRequest; -import org.apache.lucene.facet.search.TaxonomyFacetsAccumulator; -import org.apache.lucene.facet.search.TopKFacetResultsHandler; -import org.apache.lucene.facet.search.TopKInEachNodeHandler; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.util.PartitionsUtils; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAccumulator} which supports partitions, sampling and - * complement counting. - *

- * NOTE: this accumulator still uses the old API and will be removed - * eventually in favor of dedicated accumulators which support the above - * features ovee the new {@link FacetsAggregator} API. It provides - * {@link Aggregator} implementations for {@link CountFacetRequest}, - * {@link SumScoreFacetRequest} and {@link OverSampledFacetRequest}. If you need - * to use it in conjunction with other facet requests, you should override - * {@link #createAggregator(FacetRequest, FacetArrays)}. - * - * @lucene.experimental - */ -public class OldFacetsAccumulator extends TaxonomyFacetsAccumulator { - - /** - * Default threshold for using the complements optimization. - * If accumulating facets for a document set larger than this ratio of the index size than - * perform the complement optimization. - * @see #setComplementThreshold(double) for more info on the complements optimization. - */ - public static final double DEFAULT_COMPLEMENT_THRESHOLD = 0.6; - - /** - * Passing this to {@link #setComplementThreshold(double)} will disable using complement optimization. - */ - public static final double DISABLE_COMPLEMENT = Double.POSITIVE_INFINITY; // > 1 actually - - /** - * Passing this to {@link #setComplementThreshold(double)} will force using complement optimization. - */ - public static final double FORCE_COMPLEMENT = 0; // <=0 - - protected int partitionSize; - protected int maxPartitions; - protected boolean isUsingComplements; - - private TotalFacetCounts totalFacetCounts; - - private Object accumulateGuard; - - private double complementThreshold = DEFAULT_COMPLEMENT_THRESHOLD; - - private static FacetArrays createFacetArrays(FacetSearchParams searchParams, TaxonomyReader taxoReader) { - return new FacetArrays(PartitionsUtils.partitionSize(searchParams.indexingParams, taxoReader)); - } - - public OldFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader) { - this(searchParams, indexReader, taxonomyReader, null); - } - - public OldFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader, FacetArrays facetArrays) { - super(searchParams, indexReader, taxonomyReader, facetArrays == null ? createFacetArrays(searchParams, taxonomyReader) : facetArrays); - - // can only be computed later when docids size is known - isUsingComplements = false; - partitionSize = PartitionsUtils.partitionSize(searchParams.indexingParams, taxonomyReader); - maxPartitions = (int) Math.ceil(this.taxonomyReader.getSize() / (double) partitionSize); - accumulateGuard = new Object(); - } - - // TODO: this should be removed once we clean the API - public List accumulate(ScoredDocIDs docids) throws IOException { - - // synchronize to prevent calling two accumulate()'s at the same time. - // We decided not to synchronize the method because that might mislead - // users to feel encouraged to call this method simultaneously. - synchronized (accumulateGuard) { - - // only now we can compute this - isUsingComplements = shouldComplement(docids); - - if (isUsingComplements) { - try { - totalFacetCounts = TotalFacetCountsCache.getSingleton().getTotalCounts(indexReader, taxonomyReader, searchParams.indexingParams); - if (totalFacetCounts != null) { - docids = ScoredDocIdsUtils.getComplementSet(docids, indexReader); - } else { - isUsingComplements = false; - } - } catch (UnsupportedOperationException e) { - // TODO (Facet): this exception is thrown from TotalCountsKey if the - // IndexReader used does not support getVersion(). We should re-think - // this: is this tiny detail worth disabling total counts completely - // for such readers? Currently, it's not supported by Parallel and - // MultiReader, which might be problematic for several applications. - // We could, for example, base our "isCurrent" logic on something else - // than the reader's version. Need to think more deeply about it. - isUsingComplements = false; - } catch (IOException e) { - // silently fail if for some reason failed to load/save from/to dir - isUsingComplements = false; - } catch (Exception e) { - // give up: this should not happen! - throw new IOException("PANIC: Got unexpected exception while trying to get/calculate total counts", e); - } - } - - docids = actualDocsToAccumulate(docids); - - HashMap fr2tmpRes = new HashMap(); - - try { - for (int part = 0; part < maxPartitions; part++) { - - // fill arrays from category lists - fillArraysForPartition(docids, facetArrays, part); - - int offset = part * partitionSize; - - // for each partition we go over all requests and handle - // each, where the request maintains the merged result. - // In this implementation merges happen after each partition, - // but other impl could merge only at the end. - final HashSet handledRequests = new HashSet(); - for (FacetRequest fr : searchParams.facetRequests) { - // Handle and merge only facet requests which were not already handled. - if (handledRequests.add(fr)) { - PartitionsFacetResultsHandler frHndlr = createFacetResultsHandler(fr, createOrdinalValueResolver(fr)); - IntermediateFacetResult res4fr = frHndlr.fetchPartitionResult(offset); - IntermediateFacetResult oldRes = fr2tmpRes.get(fr); - if (oldRes != null) { - res4fr = frHndlr.mergeResults(oldRes, res4fr); - } - fr2tmpRes.put(fr, res4fr); - } - } - } - } finally { - facetArrays.free(); - } - - // gather results from all requests into a list for returning them - List res = new ArrayList(); - for (FacetRequest fr : searchParams.facetRequests) { - PartitionsFacetResultsHandler frHndlr = createFacetResultsHandler(fr, createOrdinalValueResolver(fr)); - IntermediateFacetResult tmpResult = fr2tmpRes.get(fr); - if (tmpResult == null) { - // Add empty FacetResult: - res.add(emptyResult(taxonomyReader.getOrdinal(fr.categoryPath), fr)); - continue; - } - FacetResult facetRes = frHndlr.renderFacetResult(tmpResult); - // final labeling if allowed (because labeling is a costly operation) - frHndlr.labelResult(facetRes); - res.add(facetRes); - } - - return res; - } - } - - /** check if all requests are complementable */ - protected boolean mayComplement() { - for (FacetRequest freq : searchParams.facetRequests) { - if (!(freq instanceof CountFacetRequest)) { - return false; - } - } - return true; - } - - @Override - public PartitionsFacetResultsHandler createFacetResultsHandler(FacetRequest fr, OrdinalValueResolver resolver) { - if (fr.getResultMode() == ResultMode.PER_NODE_IN_TREE) { - return new TopKInEachNodeHandler(taxonomyReader, fr, resolver, facetArrays); - } else { - return new TopKFacetResultsHandler(taxonomyReader, fr, resolver, facetArrays); - } - } - - /** - * Set the actual set of documents over which accumulation should take place. - *

- * Allows to override the set of documents to accumulate for. Invoked just - * before actual accumulating starts. From this point that set of documents - * remains unmodified. Default implementation just returns the input - * unchanged. - * - * @param docids - * candidate documents to accumulate for - * @return actual documents to accumulate for - */ - protected ScoredDocIDs actualDocsToAccumulate(ScoredDocIDs docids) throws IOException { - return docids; - } - - /** Check if it is worth to use complements */ - protected boolean shouldComplement(ScoredDocIDs docids) { - return mayComplement() && (docids.size() > indexReader.numDocs() * getComplementThreshold()) ; - } - - /** - * Creates an {@link OrdinalValueResolver} for the given {@link FacetRequest}. - * By default this method supports {@link CountFacetRequest} and - * {@link SumScoreFacetRequest}. You should override if you are using other - * requests with this accumulator. - */ - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest fr) { - if (fr instanceof CountFacetRequest) { - return new IntValueResolver(facetArrays); - } else if (fr instanceof SumScoreFacetRequest) { - return new FloatValueResolver(facetArrays); - } else if (fr instanceof OverSampledFacetRequest) { - return createOrdinalValueResolver(((OverSampledFacetRequest) fr).orig); - } else { - throw new IllegalArgumentException("unrecognized FacetRequest " + fr.getClass()); - } - } - - /** - * Iterate over the documents for this partition and fill the facet arrays with the correct - * count/complement count/value. - */ - private final void fillArraysForPartition(ScoredDocIDs docids, FacetArrays facetArrays, int partition) - throws IOException { - - if (isUsingComplements) { - initArraysByTotalCounts(facetArrays, partition, docids.size()); - } else { - facetArrays.free(); // to get a cleared array for this partition - } - - HashMap categoryLists = getCategoryListMap(facetArrays, partition); - - IntsRef ordinals = new IntsRef(32); // a reasonable start capacity for most common apps - for (Entry entry : categoryLists.entrySet()) { - final ScoredDocIDsIterator iterator = docids.iterator(); - final CategoryListIterator categoryListIter = entry.getKey(); - final Aggregator aggregator = entry.getValue(); - Iterator contexts = indexReader.leaves().iterator(); - AtomicReaderContext current = null; - int maxDoc = -1; - while (iterator.next()) { - int docID = iterator.getDocID(); - if (docID >= maxDoc) { - boolean iteratorDone = false; - do { // find the segment which contains this document - if (!contexts.hasNext()) { - throw new RuntimeException("ScoredDocIDs contains documents outside this reader's segments !?"); - } - current = contexts.next(); - maxDoc = current.docBase + current.reader().maxDoc(); - if (docID < maxDoc) { // segment has docs, check if it has categories - boolean validSegment = categoryListIter.setNextReader(current); - validSegment &= aggregator.setNextReader(current); - if (!validSegment) { // if categoryList or aggregtor say it's an invalid segment, skip all docs - while (docID < maxDoc && iterator.next()) { - docID = iterator.getDocID(); - } - if (docID < maxDoc) { - iteratorDone = true; - } - } - } - } while (docID >= maxDoc); - if (iteratorDone) { // iterator finished, terminate the loop - break; - } - } - docID -= current.docBase; - categoryListIter.getOrdinals(docID, ordinals); - if (ordinals.length == 0) { - continue; // document does not have category ordinals - } - aggregator.aggregate(docID, iterator.getScore(), ordinals); - } - } - } - - /** Init arrays for partition by total counts, optionally applying a factor */ - private final void initArraysByTotalCounts(FacetArrays facetArrays, int partition, int nAccumulatedDocs) { - int[] intArray = facetArrays.getIntArray(); - totalFacetCounts.fillTotalCountsForPartition(intArray, partition); - double totalCountsFactor = getTotalCountsFactor(); - // fix total counts, but only if the effect of this would be meaningful. - if (totalCountsFactor < 0.99999) { - int delta = nAccumulatedDocs + 1; - for (int i = 0; i < intArray.length; i++) { - intArray[i] *= totalCountsFactor; - // also translate to prevent loss of non-positive values - // due to complement sampling (ie if sampled docs all decremented a certain category). - intArray[i] += delta; - } - } - } - - /** - * Expert: factor by which counts should be multiplied when initializing - * the count arrays from total counts. - * Default implementation for this returns 1, which is a no op. - * @return a factor by which total counts should be multiplied - */ - protected double getTotalCountsFactor() { - return 1; - } - - protected Aggregator createAggregator(FacetRequest fr, FacetArrays facetArrays) { - if (fr instanceof CountFacetRequest) { - // we rely on that, if needed, result is cleared by arrays! - int[] a = facetArrays.getIntArray(); - if (isUsingComplements) { - return new ComplementCountingAggregator(a); - } else { - return new CountingAggregator(a); - } - } else if (fr instanceof SumScoreFacetRequest) { - if (isUsingComplements) { - throw new IllegalArgumentException("complements are not supported by SumScoreFacetRequest"); - } else { - return new ScoringAggregator(facetArrays.getFloatArray()); - } - } else if (fr instanceof OverSampledFacetRequest) { - return createAggregator(((OverSampledFacetRequest) fr).orig, facetArrays); - } else { - throw new IllegalArgumentException("unknown Aggregator implementation for request " + fr.getClass()); - } - } - - /** - * Create an {@link Aggregator} and a {@link CategoryListIterator} for each - * and every {@link FacetRequest}. Generating a map, matching each - * categoryListIterator to its matching aggregator. - *

- * If two CategoryListIterators are served by the same aggregator, a single - * aggregator is returned for both. - * - * NOTE: If a given category list iterator is needed with two different - * aggregators (e.g counting and association) - an exception is thrown as this - * functionality is not supported at this time. - */ - protected HashMap getCategoryListMap(FacetArrays facetArrays, - int partition) throws IOException { - - HashMap categoryLists = new HashMap(); - - FacetIndexingParams indexingParams = searchParams.indexingParams; - for (FacetRequest facetRequest : searchParams.facetRequests) { - Aggregator categoryAggregator = createAggregator(facetRequest, facetArrays); - - CategoryListIterator cli = indexingParams.getCategoryListParams(facetRequest.categoryPath).createCategoryListIterator(partition); - - // get the aggregator - Aggregator old = categoryLists.put(cli, categoryAggregator); - - if (old != null && !old.equals(categoryAggregator)) { - throw new RuntimeException("Overriding existing category list with different aggregator"); - } - // if the aggregator is the same we're covered - } - - return categoryLists; - } - - @Override - public List accumulate(List matchingDocs) throws IOException { - return accumulate(new MatchingDocsAsScoredDocIDs(matchingDocs)); - } - - /** - * Returns the complement threshold. - * @see #setComplementThreshold(double) - */ - public double getComplementThreshold() { - return complementThreshold; - } - - /** - * Set the complement threshold. - * This threshold will dictate whether the complements optimization is applied. - * The optimization is to count for less documents. It is useful when the same - * FacetSearchParams are used for varying sets of documents. The first time - * complements is used the "total counts" are computed - counting for all the - * documents in the collection. Then, only the complementing set of documents - * is considered, and used to decrement from the overall counts, thereby - * walking through less documents, which is faster. - *

- * For the default settings see {@link #DEFAULT_COMPLEMENT_THRESHOLD}. - *

- * To forcing complements in all cases pass {@link #FORCE_COMPLEMENT}. - * This is mostly useful for testing purposes, as forcing complements when only - * tiny fraction of available documents match the query does not make sense and - * would incur performance degradations. - *

- * To disable complements pass {@link #DISABLE_COMPLEMENT}. - * @param complementThreshold the complement threshold to set - * @see #getComplementThreshold() - */ - public void setComplementThreshold(double complementThreshold) { - this.complementThreshold = complementThreshold; - } - - /** Returns true if complements are enabled. */ - public boolean isUsingComplements() { - return isUsingComplements; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDs.java b/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDs.java deleted file mode 100644 index 06f5ceec7ad..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDs.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; - -import org.apache.lucene.search.DocIdSet; - -/* - * 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. - */ - -/** - * Document IDs with scores for each, driving facets accumulation. Document - * scores are optionally used in the process of facets scoring. - * - * @see OldFacetsAccumulator#accumulate(ScoredDocIDs) - * @lucene.experimental - */ -public interface ScoredDocIDs { - - /** Returns an iterator over the document IDs and their scores. */ - public ScoredDocIDsIterator iterator() throws IOException; - - /** Returns the set of doc IDs. */ - public DocIdSet getDocIDs(); - - /** Returns the number of scored documents. */ - public int size(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDsIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDsIterator.java deleted file mode 100644 index fe0905808dc..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIDsIterator.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.apache.lucene.facet.old; - -/* - * 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. - */ - -/** - * Iterator over document IDs and their scores. Each {@link #next()} retrieves - * the next docID and its score which can be later be retrieved by - * {@link #getDocID()} and {@link #getScore()}. NOTE: you must call - * {@link #next()} before {@link #getDocID()} and/or {@link #getScore()}, or - * otherwise the returned values are unexpected. - * - * @lucene.experimental - */ -public interface ScoredDocIDsIterator { - - /** Default score used in case scoring is disabled. */ - public static final float DEFAULT_SCORE = 1.0f; - - /** Iterate to the next document/score pair. Returns true iff there is such a pair. */ - public abstract boolean next(); - - /** Returns the ID of the current document. */ - public abstract int getDocID(); - - /** Returns the score of the current document. */ - public abstract float getScore(); - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIdsUtils.java b/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIdsUtils.java deleted file mode 100644 index 7983c1fb5c9..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoredDocIdsUtils.java +++ /dev/null @@ -1,446 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; -import java.util.Arrays; - -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.old.ScoredDocIDsIterator; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiFields; -import org.apache.lucene.search.DocIdSet; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.util.Bits; -import org.apache.lucene.util.FixedBitSet; -import org.apache.lucene.util.OpenBitSetDISI; - -/* - * 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. - */ - -/** - * Utility methods for Scored Doc IDs. - * - * @lucene.experimental - */ -public class ScoredDocIdsUtils { - - /** - * Create a complement of the input set. The returned {@link ScoredDocIDs} - * does not contain any scores, which makes sense given that the complementing - * documents were not scored. - * - * Note: the complement set does NOT contain doc ids which are noted as deleted by the given reader - * - * @param docids to be complemented. - * @param reader holding the number of documents & information about deletions. - */ - public final static ScoredDocIDs getComplementSet(final ScoredDocIDs docids, final IndexReader reader) - throws IOException { - final int maxDoc = reader.maxDoc(); - - DocIdSet docIdSet = docids.getDocIDs(); - final FixedBitSet complement; - if (docIdSet instanceof FixedBitSet) { - // That is the most common case, if ScoredDocIdsCollector was used. - complement = ((FixedBitSet) docIdSet).clone(); - } else { - complement = new FixedBitSet(maxDoc); - DocIdSetIterator iter = docIdSet.iterator(); - int doc; - while ((doc = iter.nextDoc()) < maxDoc) { - complement.set(doc); - } - } - complement.flip(0, maxDoc); - clearDeleted(reader, complement); - - return createScoredDocIds(complement, maxDoc); - } - - /** Clear all deleted documents from a given open-bit-set according to a given reader */ - private static void clearDeleted(final IndexReader reader, final FixedBitSet set) throws IOException { - // TODO use BitsFilteredDocIdSet? - - // If there are no deleted docs - if (!reader.hasDeletions()) { - return; // return immediately - } - - DocIdSetIterator it = set.iterator(); - int doc = it.nextDoc(); - for (AtomicReaderContext context : reader.leaves()) { - AtomicReader r = context.reader(); - final int maxDoc = r.maxDoc() + context.docBase; - if (doc >= maxDoc) { // skip this segment - continue; - } - if (!r.hasDeletions()) { // skip all docs that belong to this reader as it has no deletions - while ((doc = it.nextDoc()) < maxDoc) {} - continue; - } - Bits liveDocs = r.getLiveDocs(); - do { - if (!liveDocs.get(doc - context.docBase)) { - set.clear(doc); - } - } while ((doc = it.nextDoc()) < maxDoc); - } - } - - /** - * Create a subset of an existing ScoredDocIDs object. - * - * @param allDocIds orginal set - * @param sampleSet Doc Ids of the subset. - */ - public static final ScoredDocIDs createScoredDocIDsSubset(final ScoredDocIDs allDocIds, - final int[] sampleSet) throws IOException { - - // sort so that we can scan docs in order - final int[] docids = sampleSet; - Arrays.sort(docids); - final float[] scores = new float[docids.length]; - // fetch scores and compute size - ScoredDocIDsIterator it = allDocIds.iterator(); - int n = 0; - while (it.next() && n < docids.length) { - int doc = it.getDocID(); - if (doc == docids[n]) { - scores[n] = it.getScore(); - ++n; - } - } - final int size = n; - - return new ScoredDocIDs() { - - @Override - public DocIdSet getDocIDs() { - return new DocIdSet() { - - @Override - public boolean isCacheable() { return true; } - - @Override - public DocIdSetIterator iterator() { - return new DocIdSetIterator() { - - private int next = -1; - - @Override - public int advance(int target) { - while (next < size && docids[next++] < target) { - } - return next == size ? NO_MORE_DOCS : docids[next]; - } - - @Override - public int docID() { - return docids[next]; - } - - @Override - public int nextDoc() { - if (++next >= size) { - return NO_MORE_DOCS; - } - return docids[next]; - } - - @Override - public long cost() { - return size; - } - }; - } - }; - } - - @Override - public ScoredDocIDsIterator iterator() { - return new ScoredDocIDsIterator() { - - int next = -1; - - @Override - public boolean next() { return ++next < size; } - - @Override - public float getScore() { return scores[next]; } - - @Override - public int getDocID() { return docids[next]; } - }; - } - - @Override - public int size() { return size; } - - }; - } - - /** - * Creates a {@link ScoredDocIDs} which returns document IDs all non-deleted doc ids - * according to the given reader. - * The returned set contains the range of [0 .. reader.maxDoc ) doc ids - */ - public static final ScoredDocIDs createAllDocsScoredDocIDs (final IndexReader reader) { - if (reader.hasDeletions()) { - return new AllLiveDocsScoredDocIDs(reader); - } - return new AllDocsScoredDocIDs(reader); - } - - /** - * Create a ScoredDocIDs out of a given docIdSet and the total number of documents in an index - */ - public static final ScoredDocIDs createScoredDocIds(final DocIdSet docIdSet, final int maxDoc) { - return new ScoredDocIDs() { - private int size = -1; - @Override - public DocIdSet getDocIDs() { return docIdSet; } - - @Override - public ScoredDocIDsIterator iterator() throws IOException { - final DocIdSetIterator docIterator = docIdSet.iterator(); - return new ScoredDocIDsIterator() { - @Override - public boolean next() { - try { - return docIterator.nextDoc() != DocIdSetIterator.NO_MORE_DOCS; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public float getScore() { return DEFAULT_SCORE; } - - @Override - public int getDocID() { return docIterator.docID(); } - }; - } - - @Override - public int size() { - // lazy size computation - if (size < 0) { - OpenBitSetDISI openBitSetDISI; - try { - openBitSetDISI = new OpenBitSetDISI(docIdSet.iterator(), maxDoc); - } catch (IOException e) { - throw new RuntimeException(e); - } - size = (int) openBitSetDISI.cardinality(); - } - return size; - } - }; - } - - /** - * All docs ScoredDocsIDs - this one is simply an 'all 1' bitset. Used when - * there are no deletions in the index and we wish to go through each and - * every document - */ - private static class AllDocsScoredDocIDs implements ScoredDocIDs { - final int maxDoc; - - public AllDocsScoredDocIDs(IndexReader reader) { - this.maxDoc = reader.maxDoc(); - } - - @Override - public int size() { - return maxDoc; - } - - @Override - public DocIdSet getDocIDs() { - return new DocIdSet() { - - @Override - public boolean isCacheable() { - return true; - } - - @Override - public DocIdSetIterator iterator() { - return new DocIdSetIterator() { - private int next = -1; - - @Override - public int advance(int target) { - if (target <= next) { - target = next + 1; - } - return next = target >= maxDoc ? NO_MORE_DOCS : target; - } - - @Override - public int docID() { - return next; - } - - @Override - public int nextDoc() { - return ++next < maxDoc ? next : NO_MORE_DOCS; - } - - @Override - public long cost() { - return maxDoc; - } - }; - } - }; - } - - @Override - public ScoredDocIDsIterator iterator() { - try { - final DocIdSetIterator iter = getDocIDs().iterator(); - return new ScoredDocIDsIterator() { - @Override - public boolean next() { - try { - return iter.nextDoc() != DocIdSetIterator.NO_MORE_DOCS; - } catch (IOException e) { - // cannot happen - return false; - } - } - - @Override - public float getScore() { - return DEFAULT_SCORE; - } - - @Override - public int getDocID() { - return iter.docID(); - } - }; - } catch (IOException e) { - // cannot happen - throw new RuntimeException(e); - } - } - } - - /** - * An All-docs bitset which has '0' for deleted documents and '1' for the - * rest. Useful for iterating over all 'live' documents in a given index. - *

- * NOTE: this class would work for indexes with no deletions at all, - * although it is recommended to use {@link AllDocsScoredDocIDs} to ease - * the performance cost of validating isDeleted() on each and every docId - */ - private static final class AllLiveDocsScoredDocIDs implements ScoredDocIDs { - final int maxDoc; - final IndexReader reader; - - AllLiveDocsScoredDocIDs(IndexReader reader) { - this.maxDoc = reader.maxDoc(); - this.reader = reader; - } - - @Override - public int size() { - return reader.numDocs(); - } - - @Override - public DocIdSet getDocIDs() { - return new DocIdSet() { - - @Override - public boolean isCacheable() { - return true; - } - - @Override - public DocIdSetIterator iterator() { - return new DocIdSetIterator() { - final Bits liveDocs = MultiFields.getLiveDocs(reader); - private int next = -1; - - @Override - public int advance(int target) { - if (target > next) { - next = target - 1; - } - return nextDoc(); - } - - @Override - public int docID() { - return next; - } - - @Override - public int nextDoc() { - do { - ++next; - } while (next < maxDoc && liveDocs != null && !liveDocs.get(next)); - - return next < maxDoc ? next : NO_MORE_DOCS; - } - - @Override - public long cost() { - return maxDoc; - } - }; - } - }; - } - - @Override - public ScoredDocIDsIterator iterator() { - try { - final DocIdSetIterator iter = getDocIDs().iterator(); - return new ScoredDocIDsIterator() { - @Override - public boolean next() { - try { - return iter.nextDoc() != DocIdSetIterator.NO_MORE_DOCS; - } catch (IOException e) { - // cannot happen - return false; - } - } - - @Override - public float getScore() { - return DEFAULT_SCORE; - } - - @Override - public int getDocID() { - return iter.docID(); - } - }; - } catch (IOException e) { - // cannot happen - throw new RuntimeException(e); - } - } - } - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoringAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/old/ScoringAggregator.java deleted file mode 100644 index 4c065f9422e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/ScoringAggregator.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An {@link Aggregator} which updates the weight of a category according to the - * scores of the documents it was found in. - * - * @lucene.experimental - */ -public class ScoringAggregator implements Aggregator { - - private final float[] scoreArray; - private final int hashCode; - - public ScoringAggregator(float[] counterArray) { - this.scoreArray = counterArray; - this.hashCode = scoreArray == null ? 0 : scoreArray.hashCode(); - } - - @Override - public void aggregate(int docID, float score, IntsRef ordinals) throws IOException { - for (int i = 0; i < ordinals.length; i++) { - scoreArray[ordinals.ints[i]] += score; - } - } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != this.getClass()) { - return false; - } - ScoringAggregator that = (ScoringAggregator) obj; - return that.scoreArray == this.scoreArray; - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean setNextReader(AtomicReaderContext context) throws IOException { - return true; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/old/package.html b/lucene/facet/src/java/org/apache/lucene/facet/old/package.html deleted file mode 100644 index a2b28be175f..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/old/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Old Faceted Search API - - -Old faceted search API, kept until complements, sampling and partitions are migrated to the new API. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/CategoryListParams.java b/lucene/facet/src/java/org/apache/lucene/facet/params/CategoryListParams.java deleted file mode 100644 index 3034f6a24ff..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/CategoryListParams.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.apache.lucene.facet.params; - -import java.io.IOException; - -import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder; -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.encoding.SortingIntEncoder; -import org.apache.lucene.facet.encoding.UniqueValuesIntEncoder; -import org.apache.lucene.facet.search.CategoryListIterator; -import org.apache.lucene.facet.search.DocValuesCategoryListIterator; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.util.PartitionsUtils; - -/* - * 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. - */ - -/** - * Contains parameters for a category list * - * - * @lucene.experimental - */ -public class CategoryListParams { - - /** - * Defines which category ordinals are encoded for every document. This also - * affects how category ordinals are aggregated, check the different policies - * for more details. - */ - public static enum OrdinalPolicy { - /** - * Encodes only the ordinals of leaf nodes. That is, for the category A/B/C, - * the ordinals of A and A/B will not be encoded. This policy is efficient - * for hierarchical dimensions, as it reduces the number of ordinals that - * are visited per document. During faceted search, this policy behaves - * exactly like {@link #ALL_PARENTS}, and the counts of all path components - * will be computed as well. - * - *

- * NOTE: this {@link OrdinalPolicy} requires a special collector or - * accumulator, which will fix the parents' counts. - * - *

- * NOTE: since only leaf nodes are encoded for the document, you - * should use this policy when the same document doesn't share two - * categories that have a mutual parent, or otherwise the counts will be - * wrong (the mutual parent will be over-counted). For example, if a - * document has the categories A/B/C and A/B/D, then with this policy the - * counts of "A" and "B" will be 2, which is wrong. If you intend to index - * hierarchical dimensions, with more than one category per document, you - * should use either {@link #ALL_PARENTS} or {@link #ALL_BUT_DIMENSION}. - */ - NO_PARENTS, - - /** - * Encodes the ordinals of all path components. That is, the category A/B/C - * will encode the ordinals of A and A/B as well. If you don't require the - * dimension's count during search, consider using - * {@link #ALL_BUT_DIMENSION}. - */ - ALL_PARENTS, - - /** - * Encodes the ordinals of all path components except the dimension. The - * dimension of a category is defined to be the first components in - * {@link FacetLabel#components}. For the category A/B/C, the ordinal of - * A/B will be encoded as well, however not the ordinal of A. - * - *

- * NOTE: when facets are aggregated, this policy behaves exactly like - * {@link #ALL_PARENTS}, except that the dimension is never counted. I.e. if - * you ask to count the facet "A", then while in {@link #ALL_PARENTS} you - * will get counts for "A" and its children, with this policy you - * will get counts for only its children. This policy is the default - * one, and makes sense for using with flat dimensions, whenever your - * application does not require the dimension's count. Otherwise, use - * {@link #ALL_PARENTS}. - */ - ALL_BUT_DIMENSION - } - - /** The default field used to store the facets information. */ - public static final String DEFAULT_FIELD = "$facets"; - - /** - * The default {@link OrdinalPolicy} that's used when encoding a document's - * category ordinals. - */ - public static final OrdinalPolicy DEFAULT_ORDINAL_POLICY = OrdinalPolicy.ALL_BUT_DIMENSION; - - public final String field; - - private final int hashCode; - - /** Constructs a default category list parameters object, using {@link #DEFAULT_FIELD}. */ - public CategoryListParams() { - this(DEFAULT_FIELD); - } - - /** Constructs a category list parameters object, using the given field. */ - public CategoryListParams(String field) { - this.field = field; - // Pre-compute the hashCode because these objects are immutable. Saves - // some time on the comparisons later. - this.hashCode = field.hashCode(); - } - - /** - * Allows to override how categories are encoded and decoded. A matching - * {@link IntDecoder} is provided by the {@link IntEncoder}. - *

- * Default implementation creates a new Sorting(Unique(DGap)) encoder. - * Uniqueness in this regard means when the same category appears twice in a - * document, only one appearance would be encoded. This has effect on facet - * counting results. - *

- * Some possible considerations when overriding may be: - *

    - *
  • an application "knows" that all categories are unique. So no need to - * pass through the unique filter.
  • - *
  • Another application might wish to count multiple occurrences of the - * same category, or, use a faster encoding which will consume more space.
  • - *
- * In any event when changing this value make sure you know what you are - * doing, and test the results - e.g. counts, if the application is about - * counting facets. - */ - public IntEncoder createEncoder() { - return new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapVInt8IntEncoder())); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof CategoryListParams)) { - return false; - } - CategoryListParams other = (CategoryListParams) o; - if (hashCode != other.hashCode) { - return false; - } - return field.equals(other.field); - } - - @Override - public int hashCode() { - return hashCode; - } - - /** Create the {@link CategoryListIterator} for the specified partition. */ - public CategoryListIterator createCategoryListIterator(int partition) throws IOException { - String categoryListTermStr = PartitionsUtils.partitionName(partition); - String docValuesField = field + categoryListTermStr; - return new DocValuesCategoryListIterator(docValuesField, createEncoder().createMatchingDecoder()); - } - - /** - * Returns the {@link OrdinalPolicy} to use for the given dimension. This - * {@link CategoryListParams} always returns {@link #DEFAULT_ORDINAL_POLICY} - * for all dimensions. - */ - public OrdinalPolicy getOrdinalPolicy(String dimension) { - return DEFAULT_ORDINAL_POLICY; - } - - @Override - public String toString() { - return "field=" + field + " encoder=" + createEncoder() + " ordinalPolicy=" + getOrdinalPolicy(null); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/FacetIndexingParams.java b/lucene/facet/src/java/org/apache/lucene/facet/params/FacetIndexingParams.java deleted file mode 100644 index 1eaf9367149..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/FacetIndexingParams.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.apache.lucene.facet.params; - -import java.util.Collections; -import java.util.List; - -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * Defines parameters that are needed for facets indexing. Note that this class - * does not have any setters. That's because overriding the default parameters - * is considered expert. If you wish to override them, simply extend this class - * and override the relevant getter. - * - *

- * NOTE: This class is also used during faceted search in order to e.g. - * know which field holds the drill-down terms or the fulltree posting. - * Therefore this class should be initialized once and you should refrain from - * changing it. Also note that if you make any changes to it (e.g. suddenly - * deciding that drill-down terms should be read from a different field) and use - * it on an existing index, things may not work as expected. - * - * @lucene.experimental - */ -public class FacetIndexingParams { - - // the default CLP, can be a singleton - protected static final CategoryListParams DEFAULT_CATEGORY_LIST_PARAMS = new CategoryListParams(); - - /** - * A {@link FacetIndexingParams} which fixes a single - * {@link CategoryListParams} with - * {@link CategoryListParams#DEFAULT_ORDINAL_POLICY}. - */ - public static final FacetIndexingParams DEFAULT = new FacetIndexingParams(); - - /** - * The default delimiter with which {@link FacetLabel#components} are - * concatenated when written to the index, e.g. as drill-down terms. If you - * choose to override it by overiding {@link #getFacetDelimChar()}, you should - * make sure that you return a character that's not found in any path - * component. - */ - public static final char DEFAULT_FACET_DELIM_CHAR = '\u001F'; - - private final int partitionSize = Integer.MAX_VALUE; - - protected final CategoryListParams clParams; - - /** - * Initializes new default params. You should use this constructor only if you - * intend to override any of the getters, otherwise you can use - * {@link #DEFAULT} to save unnecessary object allocations. - */ - public FacetIndexingParams() { - this(DEFAULT_CATEGORY_LIST_PARAMS); - } - - /** Initializes new params with the given {@link CategoryListParams}. */ - public FacetIndexingParams(CategoryListParams categoryListParams) { - clParams = categoryListParams; - } - - /** - * Returns the {@link CategoryListParams} for this {@link FacetLabel}. The - * default implementation returns the same {@link CategoryListParams} for all - * categories (even if {@code category} is {@code null}). - * - * @see PerDimensionIndexingParams - */ - public CategoryListParams getCategoryListParams(FacetLabel category) { - return clParams; - } - - /** - * Copies the text required to execute a drill-down query on the given - * category to the given {@code char[]}, and returns the number of characters - * that were written. - *

- * NOTE: You should make sure that the {@code char[]} is large enough, - * by e.g. calling {@link FacetLabel#fullPathLength()}. - */ - public int drillDownTermText(FacetLabel path, char[] buffer) { - return path.copyFullPath(buffer, 0, getFacetDelimChar()); - } - - /** - * Returns the size of a partition. Partitions allow you to divide - * (hence, partition) the categories space into small sets to e.g. improve RAM - * consumption during faceted search. For instance, {@code partitionSize=100K} - * would mean that if your taxonomy index contains 420K categories, they will - * be divided into 5 groups and at search time a {@link FacetArrays} will be - * allocated at the size of the partition. - * - *

- * This is real advanced setting and should be changed with care. By default, - * all categories are put in one partition. You should modify this setting if - * you have really large taxonomies (e.g. 1M+ nodes). - */ - public int getPartitionSize() { - return partitionSize; - } - - /** - * Returns a list of all {@link CategoryListParams categoryListParams} that - * are used for facets indexing. - */ - public List getAllCategoryListParams() { - return Collections.singletonList(clParams); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((clParams == null) ? 0 : clParams.hashCode()); - result = prime * result + partitionSize; - - for (CategoryListParams clp : getAllCategoryListParams()) { - result ^= clp.hashCode(); - } - - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof FacetIndexingParams)) { - return false; - } - FacetIndexingParams other = (FacetIndexingParams) obj; - if (clParams == null) { - if (other.clParams != null) { - return false; - } - } else if (!clParams.equals(other.clParams)) { - return false; - } - if (partitionSize != other.partitionSize) { - return false; - } - - Iterable cLs = getAllCategoryListParams(); - Iterable otherCLs = other.getAllCategoryListParams(); - - return cLs.equals(otherCLs); - } - - /** - * Returns the delimiter character used internally for concatenating category - * path components, e.g. for drill-down terms. - */ - public char getFacetDelimChar() { - return DEFAULT_FACET_DELIM_CHAR; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java b/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java deleted file mode 100644 index c4bfc224da5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.apache.lucene.facet.params; - -import java.util.Arrays; -import java.util.List; - -import org.apache.lucene.facet.search.FacetRequest; - -/* - * 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. - */ - -/** - * Defines parameters that are needed for faceted search: the list of facet - * {@link FacetRequest facet requests} which should be aggregated as well as the - * {@link FacetIndexingParams indexing params} that were used to index them. - * - * @lucene.experimental - */ -public class FacetSearchParams { - - public final FacetIndexingParams indexingParams; - public final List facetRequests; - - /** - * Initializes with the given {@link FacetRequest requests} and default - * {@link FacetIndexingParams#DEFAULT}. If you used a different - * {@link FacetIndexingParams}, you should use - * {@link #FacetSearchParams(FacetIndexingParams, List)}. - */ - public FacetSearchParams(FacetRequest... facetRequests) { - this(FacetIndexingParams.DEFAULT, Arrays.asList(facetRequests)); - } - - /** - * Initializes with the given {@link FacetRequest requests} and default - * {@link FacetIndexingParams#DEFAULT}. If you used a different - * {@link FacetIndexingParams}, you should use - * {@link #FacetSearchParams(FacetIndexingParams, List)}. - */ - public FacetSearchParams(List facetRequests) { - this(FacetIndexingParams.DEFAULT, facetRequests); - } - - /** - * Initializes with the given {@link FacetRequest requests} and - * {@link FacetIndexingParams}. - */ - public FacetSearchParams(FacetIndexingParams indexingParams, FacetRequest... facetRequests) { - this(indexingParams, Arrays.asList(facetRequests)); - } - - /** - * Initializes with the given {@link FacetRequest requests} and - * {@link FacetIndexingParams}. - */ - public FacetSearchParams(FacetIndexingParams indexingParams, List facetRequests) { - if (facetRequests == null || facetRequests.size() == 0) { - throw new IllegalArgumentException("at least one FacetRequest must be defined"); - } - this.facetRequests = facetRequests; - this.indexingParams = indexingParams; - } - - @Override - public String toString() { - final String INDENT = " "; - final char NEWLINE = '\n'; - - StringBuilder sb = new StringBuilder("IndexingParams: "); - sb.append(NEWLINE).append(INDENT).append(indexingParams); - - sb.append(NEWLINE).append("FacetRequests:"); - for (FacetRequest facetRequest : facetRequests) { - sb.append(NEWLINE).append(INDENT).append(facetRequest); - } - - return sb.toString(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionIndexingParams.java b/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionIndexingParams.java deleted file mode 100644 index 9fb2b0a5164..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionIndexingParams.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apache.lucene.facet.params; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link FacetIndexingParams} that utilizes different category lists, defined - * by the dimension specified by a {@link FacetLabel category} (see - * {@link #PerDimensionIndexingParams(Map, CategoryListParams)}. - *

- * A 'dimension' is defined as the first or "zero-th" component in a - * {@link FacetLabel}. For example, if a category is defined as - * "Author/American/Mark Twain", then the dimension would be "Author". - * - * @lucene.experimental - */ -public class PerDimensionIndexingParams extends FacetIndexingParams { - - private final Map clParamsMap; - - /** - * Initializes a new instance with the given dimension-to-params mapping. The - * dimension is considered as what's returned by - * {@link FacetLabel#components cp.components[0]}. - * - *

- * NOTE: for any dimension whose {@link CategoryListParams} is not - * defined in the mapping, a default {@link CategoryListParams} will be used. - * - * @see #PerDimensionIndexingParams(Map, CategoryListParams) - */ - public PerDimensionIndexingParams(Map paramsMap) { - this(paramsMap, DEFAULT_CATEGORY_LIST_PARAMS); - } - - /** - * Same as {@link #PerDimensionIndexingParams(Map)}, only the given - * {@link CategoryListParams} will be used for any dimension that is not - * specified in the given mapping. - */ - public PerDimensionIndexingParams(Map paramsMap, - CategoryListParams categoryListParams) { - super(categoryListParams); - clParamsMap = new HashMap(); - for (Entry e : paramsMap.entrySet()) { - clParamsMap.put(e.getKey().components[0], e.getValue()); - } - } - - @Override - public List getAllCategoryListParams() { - ArrayList vals = new ArrayList(clParamsMap.values()); - vals.add(clParams); // add the default too - return vals; - } - - /** - * Returns the {@link CategoryListParams} for the corresponding dimension - * which is returned by {@code category.getComponent(0)}. If {@code category} - * is {@code null}, or was not specified in the map given to the constructor, - * returns the default {@link CategoryListParams}. - */ - @Override - public CategoryListParams getCategoryListParams(FacetLabel category) { - if (category != null) { - CategoryListParams clParams = clParamsMap.get(category.components[0]); - if (clParams != null) { - return clParams; - } - } - return clParams; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionOrdinalPolicy.java b/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionOrdinalPolicy.java deleted file mode 100644 index 98568fbf549..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/PerDimensionOrdinalPolicy.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.apache.lucene.facet.params; - -import java.util.Map; - -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link CategoryListParams} which allow controlling the - * {@link CategoryListParams.OrdinalPolicy} used for each dimension. The - * dimension is specified as the first component in - * {@link FacetLabel#components}. - */ -public class PerDimensionOrdinalPolicy extends CategoryListParams { - - private final Map policies; - private final OrdinalPolicy defaultOP; - - public PerDimensionOrdinalPolicy(Map policies) { - this(policies, DEFAULT_ORDINAL_POLICY); - } - - public PerDimensionOrdinalPolicy(Map policies, OrdinalPolicy defaultOP) { - this.defaultOP = defaultOP; - this.policies = policies; - } - - @Override - public OrdinalPolicy getOrdinalPolicy(String dimension) { - OrdinalPolicy op = policies.get(dimension); - return op == null ? defaultOP : op; - } - - @Override - public String toString() { - return super.toString() + " policies=" + policies; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/params/package.html b/lucene/facet/src/java/org/apache/lucene/facet/params/package.html deleted file mode 100644 index dd2d8a41d1c..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/params/package.html +++ /dev/null @@ -1,25 +0,0 @@ - - - -Facets indexing and search parameters - - -Facets indexing and search parameters. Define how facets are indexed -as well as which categories need to be aggregated. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/partitions/IntermediateFacetResult.java b/lucene/facet/src/java/org/apache/lucene/facet/partitions/IntermediateFacetResult.java deleted file mode 100644 index 5434c298a66..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/partitions/IntermediateFacetResult.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.apache.lucene.facet.partitions; - -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultsHandler; - -/* - * 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. - */ - -/** - * Intermediate {@link FacetResult} of faceted search. - *

- * This is an empty interface on purpose. - *

- * It allows {@link FacetResultsHandler} to return intermediate result objects - * that only it knows how to interpret, and so the handler has maximal freedom - * in defining what an intermediate result is, depending on its specific logic. - * - * @lucene.experimental - */ -public interface IntermediateFacetResult { - - /** - * Facet request for which this temporary result was created. - */ - FacetRequest getFacetRequest(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/partitions/PartitionsFacetResultsHandler.java b/lucene/facet/src/java/org/apache/lucene/facet/partitions/PartitionsFacetResultsHandler.java deleted file mode 100644 index 13ed1b26bb6..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/partitions/PartitionsFacetResultsHandler.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.apache.lucene.facet.partitions; - -import java.io.IOException; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetResultsHandler; -import org.apache.lucene.facet.search.OrdinalValueResolver; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * A {@link FacetResultsHandler} designed to work with facet partitions. - * - * @lucene.experimental - */ -public abstract class PartitionsFacetResultsHandler extends FacetResultsHandler { - - public PartitionsFacetResultsHandler(TaxonomyReader taxonomyReader, FacetRequest facetRequest, - OrdinalValueResolver resolver, FacetArrays facetArrays) { - super(taxonomyReader, facetRequest, resolver, facetArrays); - } - - /** - * Fetch results of a single partition, given facet arrays for that partition, - * and based on the matching documents and faceted search parameters. - * @param offset - * offset in input arrays where partition starts - * - * @return temporary facet result, potentially, to be passed back to - * this result handler for merging, or null in case that - * constructor parameter, facetRequest, requests an - * illegal FacetResult, like, e.g., a root node category path that - * does not exist in constructor parameter taxonomyReader - * . - * @throws IOException - * on error - */ - public abstract IntermediateFacetResult fetchPartitionResult(int offset) throws IOException; - - /** - * Merge results of several facet partitions. Logic of the merge is undefined - * and open for interpretations. For example, a merge implementation could - * keep top K results. Passed {@link IntermediateFacetResult} must be ones - * that were created by this handler otherwise a {@link ClassCastException} is - * thrown. In addition, all passed {@link IntermediateFacetResult} must have - * the same {@link FacetRequest} otherwise an {@link IllegalArgumentException} - * is thrown. - * - * @param tmpResults one or more temporary results created by this - * handler. - * @return temporary facet result that represents to union, as specified by - * this handler, of the input temporary facet results. - * @throws IOException on error. - * @throws ClassCastException if the temporary result passed was not created - * by this handler - * @throws IllegalArgumentException if passed facetResults do not - * have the same {@link FacetRequest} - * @see IntermediateFacetResult#getFacetRequest() - */ - public abstract IntermediateFacetResult mergeResults(IntermediateFacetResult... tmpResults) throws IOException; - - /** - * Create a facet result from the temporary result. - * @param tmpResult temporary result to be rendered as a {@link FacetResult} - * @throws IOException on error. - */ - public abstract FacetResult renderFacetResult(IntermediateFacetResult tmpResult) throws IOException ; - - /** - * Perform any rearrangement as required on a facet result that has changed after - * it was rendered. - *

- * Possible use case: a sampling facets accumulator invoked another - * other facets accumulator on a sample set of documents, obtained - * rendered facet results, fixed their counts, and now it is needed - * to sort the results differently according to the fixed counts. - * @param facetResult result to be rearranged. - * @see FacetResultNode#value - */ - public abstract FacetResult rearrangeFacetResult(FacetResult facetResult); - - /** - * Label results according to settings in {@link FacetRequest}, such as - * {@link FacetRequest#getNumLabel()}. Usually invoked by - * {@link OldFacetsAccumulator#accumulate(ScoredDocIDs)} - * - * @param facetResult - * facet result to be labeled. - * @throws IOException - * on error - */ - public abstract void labelResult(FacetResult facetResult) throws IOException; - - /** - * Check if an array contains the partition which contains ordinal - * - * @param ordinal - * checked facet - * @param facetArrays - * facet arrays for the certain partition - * @param offset - * offset in input arrays where partition starts - */ - protected boolean isSelfPartition (int ordinal, FacetArrays facetArrays, int offset) { - int partitionSize = facetArrays.arrayLength; - return ordinal / partitionSize == offset / partitionSize; - } - - @Override - public final FacetResult compute() throws IOException { - FacetResult res = renderFacetResult(fetchPartitionResult(0)); - labelResult(res); - return res; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/partitions/package.html b/lucene/facet/src/java/org/apache/lucene/facet/partitions/package.html deleted file mode 100644 index a4d8d6234e1..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/partitions/package.html +++ /dev/null @@ -1,27 +0,0 @@ - - - -Category Partitions - - -

Category Partitions

- -Allows partitioning the category ordinals space, so that less RAM is consumed during search. -Only meaningful for very large taxonomies (tens of millions of categories). - - diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetResultNode.java b/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetResultNode.java deleted file mode 100644 index 7a380aaa5fb..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetResultNode.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.apache.lucene.facet.range; - -/* - * 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. - */ - -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/** Holds the facet results for a {@link - * RangeFacetRequest}. */ -public class RangeFacetResultNode extends FacetResultNode { - public final Range range; - - RangeFacetResultNode(String field, Range range, int count) { - super(-1, count); - this.range = range; - this.label = new FacetLabel(field, range.label); - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/package.html b/lucene/facet/src/java/org/apache/lucene/facet/range/package.html deleted file mode 100644 index f42b3461565..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets numeric range code - - -Code to compute facets for numeric ranges. - - diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/RandomSampler.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/RandomSampler.java deleted file mode 100644 index 1ce68dc63b7..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/RandomSampler.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; -import java.util.Random; - -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.old.ScoredDocIDsIterator; -import org.apache.lucene.facet.old.ScoredDocIdsUtils; - -/* - * 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. - */ - -/** - * Simple random sampler - */ -public class RandomSampler extends Sampler { - - private final Random random; - - public RandomSampler() { - super(); - this.random = new Random(); - } - - public RandomSampler(SamplingParams params, Random random) throws IllegalArgumentException { - super(params); - this.random = random; - } - - @Override - protected SampleResult createSample(ScoredDocIDs docids, int actualSize, int sampleSetSize) throws IOException { - final int[] sample = new int[sampleSetSize]; - final int maxStep = (actualSize * 2 ) / sampleSetSize; //floor - int remaining = actualSize; - ScoredDocIDsIterator it = docids.iterator(); - int i = 0; - // select sample docs with random skipStep, make sure to leave sufficient #docs for selection after last skip - while (i(sampleSetSize-maxStep-i)) { - int skipStep = 1 + random.nextInt(maxStep); - // Skip over 'skipStep' documents - for (int j=0; jsampleSize values from the first collectionSize - * locations of collection, chosen using - * the TRAVERSAL algorithm. The sample values are not sorted. - * @param collection The values from which a sample is wanted. - * @param collectionSize The number of values (from the first) from which to draw the sample. - * @param sampleSize The number of values to return. - * @return An array of values chosen from the collection. - * @see Algorithm#TRAVERSAL - */ - private static int[] repeatableSample(ScoredDocIDs collection, - int collectionSize, int sampleSize) - throws IOException { - return repeatableSample(collection, collectionSize, - sampleSize, Algorithm.HASHING, Sorted.NO); - } - - /** - * Returns sampleSize values from the first collectionSize - * locations of collection, chosen using algorithm. - * @param collection The values from which a sample is wanted. - * @param collectionSize The number of values (from the first) from which to draw the sample. - * @param sampleSize The number of values to return. - * @param algorithm Which algorithm to use. - * @param sorted Sorted.YES to sort the sample values in ascending order before returning; - * Sorted.NO to return them in essentially random order. - * @return An array of values chosen from the collection. - */ - private static int[] repeatableSample(ScoredDocIDs collection, - int collectionSize, int sampleSize, - Algorithm algorithm, Sorted sorted) - throws IOException { - if (collection == null) { - throw new IOException("docIdSet is null"); - } - if (sampleSize < 1) { - throw new IOException("sampleSize < 1 (" + sampleSize + ")"); - } - if (collectionSize < sampleSize) { - throw new IOException("collectionSize (" + collectionSize + ") less than sampleSize (" + sampleSize + ")"); - } - int[] sample = new int[sampleSize]; - long[] times = new long[4]; - if (algorithm == Algorithm.TRAVERSAL) { - sample1(collection, collectionSize, sample, times); - } else if (algorithm == Algorithm.HASHING) { - sample2(collection, collectionSize, sample, times); - } else { - throw new IllegalArgumentException("Invalid algorithm selection"); - } - if (sorted == Sorted.YES) { - Arrays.sort(sample); - } - if (returnTimings) { - times[3] = System.currentTimeMillis(); - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Times: " + (times[1] - times[0]) + "ms, " - + (times[2] - times[1]) + "ms, " + (times[3] - times[2])+"ms"); - } - } - return sample; - } - - /** - * Returns sample.length values chosen from the first collectionSize - * locations of collection, using the TRAVERSAL algorithm. The sample is - * pseudorandom: no subset of the original collection - * is in principle more likely to occur than any other, but for a given collection - * and sample size, the same sample will always be returned. This algorithm walks the - * original collection in a methodical way that is guaranteed not to visit any location - * more than once, which makes sampling without replacement faster because removals don't - * have to be tracked, and the number of operations is proportional to the sample size, - * not the collection size. - * Times for performance measurement - * are returned in times, which must be an array of at least three longs, containing - * nanosecond event times. The first - * is set when the algorithm starts; the second, when the step size has been calculated; - * and the third when the sample has been taken. - * @param collection The set to be sampled. - * @param collectionSize The number of values to use (starting from first). - * @param sample The array in which to return the sample. - * @param times The times of three events, for measuring performance. - */ - private static void sample1(ScoredDocIDs collection, int collectionSize, int[] sample, long[] times) - throws IOException { - ScoredDocIDsIterator it = collection.iterator(); - if (returnTimings) { - times[0] = System.currentTimeMillis(); - } - int sampleSize = sample.length; - int prime = findGoodStepSize(collectionSize, sampleSize); - int mod = prime % collectionSize; - if (returnTimings) { - times[1] = System.currentTimeMillis(); - } - int sampleCount = 0; - int index = 0; - for (; sampleCount < sampleSize;) { - if (index + mod < collectionSize) { - for (int i = 0; i < mod; i++, index++) { - it.next(); - } - } else { - index = index + mod - collectionSize; - it = collection.iterator(); - for (int i = 0; i < index; i++) { - it.next(); - } - } - sample[sampleCount++] = it.getDocID(); - } - if (returnTimings) { - times[2] = System.currentTimeMillis(); - } - } - - /** - * Returns a value which will allow the caller to walk - * a collection of collectionSize values, without repeating or missing - * any, and spanning the collection from beginning to end at least once with - * sampleSize visited locations. Choosing a value - * that is relatively prime to the collection size ensures that stepping by that size (modulo - * the collection size) will hit all locations without repeating, eliminating the need to - * track previously visited locations for a "without replacement" sample. Starting with the - * square root of the collection size ensures that either the first or second prime tried will - * work (they can't both divide the collection size). It also has the property that N steps of - * size N will span a collection of N**2 elements once. If the sample is bigger than N, it will - * wrap multiple times (without repeating). If the sample is smaller, a step size is chosen - * that will result in at least one spanning of the collection. - * - * @param collectionSize The number of values in the collection to be sampled. - * @param sampleSize The number of values wanted in the sample. - * @return A good increment value for walking the collection. - */ - private static int findGoodStepSize(int collectionSize, int sampleSize) { - int i = (int) Math.sqrt(collectionSize); - if (sampleSize < i) { - i = collectionSize / sampleSize; - } - do { - i = findNextPrimeAfter(i); - } while (collectionSize % i == 0); - return i; - } - - /** - * Returns the first prime number that is larger than n. - * @param n A number less than the prime to be returned. - * @return The smallest prime larger than n. - */ - private static int findNextPrimeAfter(int n) { - n += (n % 2 == 0) ? 1 : 2; // next odd - foundFactor: for (;; n += 2) { //TODO labels??!! - int sri = (int) (Math.sqrt(n)); - for (int primeIndex = 0; primeIndex < N_PRIMES; primeIndex++) { - int p = primes[primeIndex]; - if (p > sri) { - return n; - } - if (n % p == 0) { - continue foundFactor; - } - } - for (int p = primes[N_PRIMES - 1] + 2;; p += 2) { - if (p > sri) { - return n; - } - if (n % p == 0) { - continue foundFactor; - } - } - } - } - - /** - * The first N_PRIMES primes, after 2. - */ - private static final int N_PRIMES = 4000; - private static int[] primes = new int[N_PRIMES]; - static { - primes[0] = 3; - for (int count = 1; count < N_PRIMES; count++) { - primes[count] = findNextPrimeAfter(primes[count - 1]); - } - } - - /** - * Returns sample.length values chosen from the first collectionSize - * locations of collection, using the HASHING algorithm. Performance measurements - * are returned in times, which must be an array of at least three longs. The first - * will be set when the algorithm starts; the second, when a hash key has been calculated and - * inserted into the priority queue for every element in the collection; and the third when the - * original elements associated with the keys remaining in the PQ have been stored in the sample - * array for return. - *

- * This algorithm slows as the sample size becomes a significant fraction of the collection - * size, because the PQ is as large as the sample set, and will not do early rejection of values - * below the minimum until it fills up, and a larger PQ contains more small values to be purged, - * resulting in less early rejection and more logN insertions. - * - * @param collection The set to be sampled. - * @param collectionSize The number of values to use (starting from first). - * @param sample The array in which to return the sample. - * @param times The times of three events, for measuring performance. - */ - private static void sample2(ScoredDocIDs collection, int collectionSize, int[] sample, long[] times) - throws IOException { - if (returnTimings) { - times[0] = System.currentTimeMillis(); - } - int sampleSize = sample.length; - IntPriorityQueue pq = new IntPriorityQueue(sampleSize); - /* - * Convert every value in the collection to a hashed "weight" value, and insert - * into a bounded PQ (retains only sampleSize highest weights). - */ - ScoredDocIDsIterator it = collection.iterator(); - MI mi = null; - while (it.next()) { - if (mi == null) { - mi = new MI(); - } - mi.value = (int) (it.getDocID() * PHI_32) & 0x7FFFFFFF; - mi = pq.insertWithOverflow(mi); - } - if (returnTimings) { - times[1] = System.currentTimeMillis(); - } - /* - * Extract heap, convert weights back to original values, and return as integers. - */ - Object[] heap = pq.getHeap(); - for (int si = 0; si < sampleSize; si++) { - sample[si] = (int)(((MI) heap[si+1]).value * PHI_32I) & 0x7FFFFFFF; - } - if (returnTimings) { - times[2] = System.currentTimeMillis(); - } - } - - /** - * A mutable integer that lets queue objects be reused once they start overflowing. - */ - private static class MI { - MI() { } - public int value; - } - - /** - * A bounded priority queue for Integers, to retain a specified number of - * the highest-weighted values for return as a random sample. - */ - private static class IntPriorityQueue extends PriorityQueue { - - /** - * Creates a bounded PQ of size size. - * @param size The number of elements to retain. - */ - public IntPriorityQueue(int size) { - super(size); - } - - /** - * Returns the underlying data structure for faster access. Extracting elements - * one at a time would require N logN time, and since we want the elements sorted - * in ascending order by value (not weight), the array is useful as-is. - * @return The underlying heap array. - */ - public Object[] getHeap() { - return getHeapArray(); - } - - /** - * Returns true if o1's weight is less than that of o2, for - * ordering in the PQ. - * @return True if o1 weighs less than o2. - */ - @Override - public boolean lessThan(MI o1, MI o2) { - return o1.value < o2.value; - } - - } - - /** - * For specifying which sampling algorithm to use. - */ - private enum Algorithm { - - /** - * Specifies a methodical traversal algorithm, which is guaranteed to span the collection - * at least once, and never to return duplicates. Faster than the hashing algorithm and - * uses much less space, but the randomness of the sample may be affected by systematic - * variations in the collection. Requires only an array for the sample, and visits only - * the number of elements in the sample set, not the full set. - */ - // TODO (Facet): This one produces a bimodal distribution (very flat around - // each peak!) for collection size 10M and sample sizes 10k and 10544. - // Figure out why. - TRAVERSAL, - - /** - * Specifies a Fibonacci-style hash algorithm (see Knuth, S&S), which generates a less - * systematically distributed subset of the sampled collection than the traversal method, - * but requires a bounded priority queue the size of the sample, and creates an object - * containing a sampled value and its hash, for every element in the full set. - */ - HASHING - } - - /** - * For specifying whether to sort the sample. - */ - private enum Sorted { - - /** - * Sort resulting sample before returning. - */ - YES, - - /** - *Do not sort the resulting sample. - */ - NO - } - - /** - * Magic number 1: prime closest to phi, in 32 bits. - */ - private static final long PHI_32 = 2654435769L; - - /** - * Magic number 2: multiplicative inverse of PHI_32, modulo 2**32. - */ - private static final long PHI_32I = 340573321L; - - /** - * Switch to cause methods to return timings. - */ - private static boolean returnTimings = false; - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SampleFixer.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/SampleFixer.java deleted file mode 100644 index e04427cef86..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SampleFixer.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; - -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; - -/* - * 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. - */ - -/** - * Fixer of sample facet accumulation results. - * - * @lucene.experimental - */ -public abstract class SampleFixer { - - /** - * Alter the input result, fixing it to account for the sampling. This - * implementation can compute accurate or estimated counts for the sampled - * facets. For example, a faster correction could just multiply by a - * compensating factor. - * - * @param origDocIds - * full set of matching documents. - * @param fres - * sample result to be fixed. - * @throws IOException - * If there is a low-level I/O error. - */ - public void fixResult(ScoredDocIDs origDocIds, FacetResult fres, double samplingRatio) throws IOException { - FacetResultNode topRes = fres.getFacetResultNode(); - fixResultNode(topRes, origDocIds, samplingRatio); - } - - /** - * Fix result node count, and, recursively, fix all its children - * - * @param facetResNode - * result node to be fixed - * @param docIds - * docids in effect - * @throws IOException - * If there is a low-level I/O error. - */ - protected void fixResultNode(FacetResultNode facetResNode, ScoredDocIDs docIds, double samplingRatio) - throws IOException { - singleNodeFix(facetResNode, docIds, samplingRatio); - for (FacetResultNode frn : facetResNode.subResults) { - fixResultNode(frn, docIds, samplingRatio); - } - } - - /** Fix the given node's value. */ - protected abstract void singleNodeFix(FacetResultNode facetResNode, ScoredDocIDs docIds, double samplingRatio) - throws IOException; - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java deleted file mode 100644 index 4fe7785982b..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsAggregator; - -/* - * 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. - */ - -/** - * Sampling definition for facets accumulation - *

- * The Sampler uses TAKMI style counting to provide a 'best guess' top-K result - * set of the facets accumulated. - *

- * Note: Sampling accumulation (Accumulation over a sampled-set of the results), - * does not guarantee accurate values for - * {@link FacetResult#getNumValidDescendants()}. - * - * @lucene.experimental - */ -public abstract class Sampler { - - protected final SamplingParams samplingParams; - - /** - * Construct with {@link SamplingParams} - */ - public Sampler() { - this(new SamplingParams()); - } - - /** - * Construct with certain {@link SamplingParams} - * - * @param params sampling params in effect - * @throws IllegalArgumentException if the provided SamplingParams are not valid - */ - public Sampler(SamplingParams params) throws IllegalArgumentException { - if (!params.validate()) { - throw new IllegalArgumentException("The provided SamplingParams are not valid!!"); - } - this.samplingParams = params; - } - - /** - * Check if this sampler would complement for the input docIds - */ - public boolean shouldSample(ScoredDocIDs docIds) { - return docIds.size() > samplingParams.getSamplingThreshold(); - } - - /** - * Compute a sample set out of the input set, based on the {@link SamplingParams#getSampleRatio()} - * in effect. Sub classes can override to alter how the sample set is - * computed. - *

- * If the input set is of size smaller than {@link SamplingParams#getMinSampleSize()}, - * the input set is returned (no sampling takes place). - *

- * Other than that, the returned set size will not be larger than {@link SamplingParams#getMaxSampleSize()} - * nor smaller than {@link SamplingParams#getMinSampleSize()}. - * @param docids - * full set of matching documents out of which a sample is needed. - */ - public SampleResult getSampleSet(ScoredDocIDs docids) throws IOException { - if (!shouldSample(docids)) { - return new SampleResult(docids, 1d); - } - - int actualSize = docids.size(); - int sampleSetSize = (int) (actualSize * samplingParams.getSampleRatio()); - sampleSetSize = Math.max(sampleSetSize, samplingParams.getMinSampleSize()); - sampleSetSize = Math.min(sampleSetSize, samplingParams.getMaxSampleSize()); - - return createSample(docids, actualSize, sampleSetSize); - } - - /** - * Create and return a sample of the input set - * @param docids input set out of which a sample is to be created - * @param actualSize original size of set, prior to sampling - * @param sampleSetSize required size of sample set - * @return sample of the input set in the required size - */ - protected abstract SampleResult createSample(ScoredDocIDs docids, int actualSize, int sampleSetSize) - throws IOException; - - /** - * Result of sample computation - */ - public final static class SampleResult { - public final ScoredDocIDs docids; - public final double actualSampleRatio; - protected SampleResult(ScoredDocIDs docids, double actualSampleRatio) { - this.docids = docids; - this.actualSampleRatio = actualSampleRatio; - } - } - - /** - * Return the sampling params in effect - */ - public final SamplingParams getSamplingParams() { - return samplingParams; - } - - /** - * Trim the input facet result.
- * Note: It is only valid to call this method with result obtained for a - * facet request created through {@link #overSampledSearchParams(FacetSearchParams)}. - * - * @throws IllegalArgumentException - * if called with results not obtained for requests created - * through {@link #overSampledSearchParams(FacetSearchParams)} - */ - public FacetResult trimResult(FacetResult facetResult) throws IllegalArgumentException { - double overSampleFactor = getSamplingParams().getOversampleFactor(); - if (overSampleFactor <= 1) { // no factoring done? - return facetResult; - } - - OverSampledFacetRequest sampledFreq = null; - - try { - sampledFreq = (OverSampledFacetRequest) facetResult.getFacetRequest(); - } catch (ClassCastException e) { - throw new IllegalArgumentException( - "It is only valid to call this method with result obtained for a " + - "facet request created through sampler.overSamlpingSearchParams()", - e); - } - - FacetRequest origFrq = sampledFreq.orig; - - FacetResultNode trimmedRootNode = facetResult.getFacetResultNode(); - trimSubResults(trimmedRootNode, origFrq.numResults); - - return new FacetResult(origFrq, trimmedRootNode, facetResult.getNumValidDescendants()); - } - - /** Trim sub results to a given size. */ - private void trimSubResults(FacetResultNode node, int size) { - if (node.subResults == FacetResultNode.EMPTY_SUB_RESULTS || node.subResults.size() == 0) { - return; - } - - ArrayList trimmed = new ArrayList(size); - for (int i = 0; i < node.subResults.size() && i < size; i++) { - FacetResultNode trimmedNode = node.subResults.get(i); - trimSubResults(trimmedNode, size); - trimmed.add(trimmedNode); - } - - node.subResults = trimmed; - } - - /** - * Over-sampled search params, wrapping each request with an over-sampled one. - */ - public FacetSearchParams overSampledSearchParams(FacetSearchParams original) { - FacetSearchParams res = original; - // So now we can sample -> altering the searchParams to accommodate for the statistical error for the sampling - double overSampleFactor = getSamplingParams().getOversampleFactor(); - if (overSampleFactor > 1) { // any factoring to do? - List facetRequests = new ArrayList(); - for (FacetRequest frq : original.facetRequests) { - int overSampledNumResults = (int) Math.ceil(frq.numResults * overSampleFactor); - facetRequests.add(new OverSampledFacetRequest(frq, overSampledNumResults)); - } - res = new FacetSearchParams(original.indexingParams, facetRequests); - } - return res; - } - - /** Wrapping a facet request for over sampling. */ - public static class OverSampledFacetRequest extends FacetRequest { - public final FacetRequest orig; - public OverSampledFacetRequest(FacetRequest orig, int num) { - super(orig.categoryPath, num); - this.orig = orig; - setDepth(orig.getDepth()); - setNumLabel(0); // don't label anything as we're over-sampling - setResultMode(orig.getResultMode()); - setSortOrder(orig.getSortOrder()); - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - return orig.createFacetsAggregator(fip); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingAccumulator.java deleted file mode 100644 index b48554ce18a..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingAccumulator.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; -import org.apache.lucene.facet.sampling.Sampler.SampleResult; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetsAccumulator; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * Facets accumulation with sampling.
- *

- * Note two major differences between this class and {@link SamplingWrapper}: - *

    - *
  1. Latter can wrap any other {@link FacetsAccumulator} while this class - * directly extends {@link OldFacetsAccumulator}.
  2. - *
  3. This class can effectively apply sampling on the complement set of - * matching document, thereby working efficiently with the complement - * optimization - see {@link OldFacetsAccumulator#getComplementThreshold()} - * .
  4. - *
- *

- * Note: Sampling accumulation (Accumulation over a sampled-set of the results), - * does not guarantee accurate values for - * {@link FacetResult#getNumValidDescendants()}. - * - * @see Sampler - * @lucene.experimental - */ -public class SamplingAccumulator extends OldFacetsAccumulator { - - private double samplingRatio = -1d; - private final Sampler sampler; - - public SamplingAccumulator(Sampler sampler, FacetSearchParams searchParams, - IndexReader indexReader, TaxonomyReader taxonomyReader, - FacetArrays facetArrays) { - super(searchParams, indexReader, taxonomyReader, facetArrays); - this.sampler = sampler; - } - - /** - * Constructor... - */ - public SamplingAccumulator( - Sampler sampler, - FacetSearchParams searchParams, - IndexReader indexReader, TaxonomyReader taxonomyReader) { - super(searchParams, indexReader, taxonomyReader); - this.sampler = sampler; - } - - @Override - public List accumulate(ScoredDocIDs docids) throws IOException { - // Replacing the original searchParams with the over-sampled - FacetSearchParams original = searchParams; - SampleFixer samplerFixer = sampler.samplingParams.getSampleFixer(); - final boolean shouldOversample = sampler.samplingParams.shouldOverSample(); - if (shouldOversample) { - searchParams = sampler.overSampledSearchParams(original); - } - - List sampleRes = super.accumulate(docids); - - List results = new ArrayList(); - for (FacetResult fres : sampleRes) { - // for sure fres is not null because this is guaranteed by the delegee. - FacetRequest fr = fres.getFacetRequest(); - PartitionsFacetResultsHandler frh = createFacetResultsHandler(fr, createOrdinalValueResolver(fr)); - if (samplerFixer != null) { - // fix the result of current request - samplerFixer.fixResult(docids, fres, samplingRatio); - - fres = frh.rearrangeFacetResult(fres); // let delegee's handler do any arranging it needs to - - if (shouldOversample) { - // Using the sampler to trim the extra (over-sampled) results - fres = sampler.trimResult(fres); - } - } - - // final labeling if allowed (because labeling is a costly operation) - if (fres.getFacetResultNode().ordinal == TaxonomyReader.INVALID_ORDINAL) { - // category does not exist, add an empty result - results.add(emptyResult(fres.getFacetResultNode().ordinal, fr)); - } else { - frh.labelResult(fres); - results.add(fres); - } - } - - searchParams = original; // Back to original params - - return results; - } - - @Override - protected ScoredDocIDs actualDocsToAccumulate(ScoredDocIDs docids) throws IOException { - SampleResult sampleRes = sampler.getSampleSet(docids); - samplingRatio = sampleRes.actualSampleRatio; - return sampleRes.docids; - } - - @Override - protected double getTotalCountsFactor() { - if (samplingRatio<0) { - throw new IllegalStateException("Total counts ratio unavailable because actualDocsToAccumulate() was not invoked"); - } - return samplingRatio; - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingParams.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingParams.java deleted file mode 100644 index a24b8b72167..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingParams.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.apache.lucene.facet.sampling; - -/* - * 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. - */ - -/** - * Parameters for sampling, dictating whether sampling is to take place and how. - * - * @lucene.experimental - */ -public class SamplingParams { - - /** - * Default factor by which more results are requested over the sample set. - * @see SamplingParams#getOversampleFactor() - */ - public static final double DEFAULT_OVERSAMPLE_FACTOR = 1d; - - /** - * Default ratio between size of sample to original size of document set. - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public static final double DEFAULT_SAMPLE_RATIO = 0.01; - - /** - * Default maximum size of sample. - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public static final int DEFAULT_MAX_SAMPLE_SIZE = 10000; - - /** - * Default minimum size of sample. - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public static final int DEFAULT_MIN_SAMPLE_SIZE = 100; - - /** - * Default sampling threshold, if number of results is less than this number - no sampling will take place - * @see SamplingParams#getSampleRatio() - */ - public static final int DEFAULT_SAMPLING_THRESHOLD = 75000; - - private int maxSampleSize = DEFAULT_MAX_SAMPLE_SIZE; - private int minSampleSize = DEFAULT_MIN_SAMPLE_SIZE; - private double sampleRatio = DEFAULT_SAMPLE_RATIO; - private int samplingThreshold = DEFAULT_SAMPLING_THRESHOLD; - private double oversampleFactor = DEFAULT_OVERSAMPLE_FACTOR; - - private SampleFixer sampleFixer = null; - - /** - * Return the maxSampleSize. - * In no case should the resulting sample size exceed this value. - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public final int getMaxSampleSize() { - return maxSampleSize; - } - - /** - * Return the minSampleSize. - * In no case should the resulting sample size be smaller than this value. - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public final int getMinSampleSize() { - return minSampleSize; - } - - /** - * @return the sampleRatio - * @see Sampler#getSampleSet(org.apache.lucene.facet.old.ScoredDocIDs) - */ - public final double getSampleRatio() { - return sampleRatio; - } - - /** - * Return the samplingThreshold. - * Sampling would be performed only for document sets larger than this. - */ - public final int getSamplingThreshold() { - return samplingThreshold; - } - - /** - * @param maxSampleSize - * the maxSampleSize to set - * @see #getMaxSampleSize() - */ - public void setMaxSampleSize(int maxSampleSize) { - this.maxSampleSize = maxSampleSize; - } - - /** - * @param minSampleSize - * the minSampleSize to set - * @see #getMinSampleSize() - */ - public void setMinSampleSize(int minSampleSize) { - this.minSampleSize = minSampleSize; - } - - /** - * @param sampleRatio - * the sampleRatio to set - * @see #getSampleRatio() - */ - public void setSampleRatio(double sampleRatio) { - this.sampleRatio = sampleRatio; - } - - /** - * Set a sampling-threshold - * @see #getSamplingThreshold() - */ - public void setSamplingThreshold(int samplingThreshold) { - this.samplingThreshold = samplingThreshold; - } - - /** - * Check validity of sampling settings, making sure that - *

    - *
  • minSampleSize <= maxSampleSize <= samplingThreshold
  • - *
  • 0 < samplingRatio <= 1
  • - *
- * - * @return true if valid, false otherwise - */ - public boolean validate() { - return - samplingThreshold >= maxSampleSize && - maxSampleSize >= minSampleSize && - sampleRatio > 0 && - sampleRatio < 1; - } - - /** - * Return the oversampleFactor. When sampling, we would collect that much more - * results, so that later, when selecting top out of these, chances are higher - * to get actual best results. Note that having this value larger than 1 only - * makes sense when using a SampleFixer which finds accurate results, such as - * TakmiSampleFixer. When this value is smaller than 1, it is - * ignored and no oversampling takes place. - */ - public final double getOversampleFactor() { - return oversampleFactor; - } - - /** - * @param oversampleFactor the oversampleFactor to set - * @see #getOversampleFactor() - */ - public void setOversampleFactor(double oversampleFactor) { - this.oversampleFactor = oversampleFactor; - } - - /** - * @return {@link SampleFixer} to be used while fixing the sampled results, if - * null no fixing will be performed - */ - public SampleFixer getSampleFixer() { - return sampleFixer; - } - - /** - * Set a {@link SampleFixer} to be used while fixing the sampled results. - * {@code null} means no fixing will be performed - */ - public void setSampleFixer(SampleFixer sampleFixer) { - this.sampleFixer = sampleFixer; - } - - /** - * Returns whether over-sampling should be done. By default returns - * {@code true} when {@link #getSampleFixer()} is not {@code null} and - * {@link #getOversampleFactor()} > 1, {@code false} otherwise. - */ - public boolean shouldOverSample() { - return sampleFixer != null && oversampleFactor > 1d; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingWrapper.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingWrapper.java deleted file mode 100644 index 88734da6773..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/SamplingWrapper.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; -import org.apache.lucene.facet.sampling.Sampler.SampleResult; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * Wrap any Facets Accumulator with sampling. - *

- * Note: Sampling accumulation (Accumulation over a sampled-set of the results), - * does not guarantee accurate values for - * {@link FacetResult#getNumValidDescendants()}. - * - * @lucene.experimental - */ -public class SamplingWrapper extends OldFacetsAccumulator { - - private OldFacetsAccumulator delegee; - private Sampler sampler; - - public SamplingWrapper(OldFacetsAccumulator delegee, Sampler sampler) { - super(delegee.searchParams, delegee.indexReader, delegee.taxonomyReader); - this.delegee = delegee; - this.sampler = sampler; - } - - @Override - public List accumulate(ScoredDocIDs docids) throws IOException { - // Replacing the original searchParams with the over-sampled (and without statistics-compute) - FacetSearchParams original = delegee.searchParams; - boolean shouldOversample = sampler.samplingParams.shouldOverSample(); - - if (shouldOversample) { - delegee.searchParams = sampler.overSampledSearchParams(original); - } - - SampleResult sampleSet = sampler.getSampleSet(docids); - - List sampleRes = delegee.accumulate(sampleSet.docids); - - List results = new ArrayList(); - SampleFixer sampleFixer = sampler.samplingParams.getSampleFixer(); - - for (FacetResult fres : sampleRes) { - // for sure fres is not null because this is guaranteed by the delegee. - FacetRequest fr = fres.getFacetRequest(); - PartitionsFacetResultsHandler frh = createFacetResultsHandler(fr, createOrdinalValueResolver(fr)); - if (sampleFixer != null) { - // fix the result of current request - sampleFixer.fixResult(docids, fres, sampleSet.actualSampleRatio); - fres = frh.rearrangeFacetResult(fres); // let delegee's handler do any - } - - if (shouldOversample) { - // Using the sampler to trim the extra (over-sampled) results - fres = sampler.trimResult(fres); - } - - // final labeling if allowed (because labeling is a costly operation) - if (fres.getFacetResultNode().ordinal == TaxonomyReader.INVALID_ORDINAL) { - // category does not exist, add an empty result - results.add(emptyResult(fres.getFacetResultNode().ordinal, fr)); - } else { - frh.labelResult(fres); - results.add(fres); - } - } - - if (shouldOversample) { - delegee.searchParams = original; // Back to original params - } - - return results; - } - - @Override - public double getComplementThreshold() { - return delegee.getComplementThreshold(); - } - - @Override - public void setComplementThreshold(double complementThreshold) { - delegee.setComplementThreshold(complementThreshold); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/TakmiSampleFixer.java b/lucene/facet/src/java/org/apache/lucene/facet/sampling/TakmiSampleFixer.java deleted file mode 100644 index b0b3a263f66..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/TakmiSampleFixer.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; - -import org.apache.lucene.facet.old.ScoredDocIDs; -import org.apache.lucene.facet.old.ScoredDocIDsIterator; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.DrillDownQuery; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiFields; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.util.Bits; - -/* - * 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. - */ - -/** - * Fix sampling results by correct results, by counting the intersection between - * two lists: a TermDocs (list of documents in a certain category) and a - * DocIdSetIterator (list of documents matching the query). - *

- * This fixer is suitable for scenarios which prioritize accuracy over - * performance. - *

- * Note: for statistically more accurate top-k selection, set - * {@link SamplingParams#setOversampleFactor(double) oversampleFactor} to at - * least 2, so that the top-k categories would have better chance of showing up - * in the sampled top-cK results (see {@link SamplingParams#getOversampleFactor} - * - * @lucene.experimental - */ -public class TakmiSampleFixer extends SampleFixer { - - private TaxonomyReader taxonomyReader; - private IndexReader indexReader; - private FacetSearchParams searchParams; - - public TakmiSampleFixer(IndexReader indexReader, - TaxonomyReader taxonomyReader, FacetSearchParams searchParams) { - this.indexReader = indexReader; - this.taxonomyReader = taxonomyReader; - this.searchParams = searchParams; - } - - @Override - public void singleNodeFix(FacetResultNode facetResNode, ScoredDocIDs docIds, double samplingRatio) throws IOException { - recount(facetResNode, docIds); - } - - /** - * Internal utility: recount for a facet result node - * - * @param fresNode - * result node to be recounted - * @param docIds - * full set of matching documents. - * @throws IOException If there is a low-level I/O error. - */ - private void recount(FacetResultNode fresNode, ScoredDocIDs docIds) throws IOException { - // TODO (Facet): change from void to return the new, smaller docSet, and use - // that for the children, as this will make their intersection ops faster. - // can do this only when the new set is "sufficiently" smaller. - - /* We need the category's path name in order to do its recounting. - * If it is missing, because the option to label only part of the - * facet results was exercise, we need to calculate them anyway, so - * in essence sampling with recounting spends some extra cycles for - * labeling results for which labels are not required. */ - if (fresNode.label == null) { - fresNode.label = taxonomyReader.getPath(fresNode.ordinal); - } - FacetLabel catPath = fresNode.label; - - Term drillDownTerm = DrillDownQuery.term(searchParams.indexingParams, catPath); - // TODO (Facet): avoid Multi*? - Bits liveDocs = MultiFields.getLiveDocs(indexReader); - int updatedCount = countIntersection(MultiFields.getTermDocsEnum(indexReader, liveDocs, - drillDownTerm.field(), drillDownTerm.bytes(), - 0), docIds.iterator()); - fresNode.value = updatedCount; - } - - /** - * Count the size of the intersection between two lists: a TermDocs (list of - * documents in a certain category) and a DocIdSetIterator (list of documents - * matching a query). - */ - private static int countIntersection(DocsEnum p1, ScoredDocIDsIterator p2) - throws IOException { - // The documentation of of both TermDocs and DocIdSetIterator claim - // that we must do next() before doc(). So we do, and if one of the - // lists is empty, obviously return 0; - if (p1 == null || p1.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) { - return 0; - } - if (!p2.next()) { - return 0; - } - - int d1 = p1.docID(); - int d2 = p2.getDocID(); - - int count = 0; - for (;;) { - if (d1 == d2) { - ++count; - if (p1.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) { - break; // end of list 1, nothing more in intersection - } - d1 = p1.docID(); - if (!advance(p2, d1)) { - break; // end of list 2, nothing more in intersection - } - d2 = p2.getDocID(); - } else if (d1 < d2) { - if (p1.advance(d2) == DocIdSetIterator.NO_MORE_DOCS) { - break; // end of list 1, nothing more in intersection - } - d1 = p1.docID(); - } else /* d1>d2 */ { - if (!advance(p2, d1)) { - break; // end of list 2, nothing more in intersection - } - d2 = p2.getDocID(); - } - } - return count; - } - - /** - * utility: advance the iterator until finding (or exceeding) specific - * document - * - * @param iterator - * iterator being advanced - * @param targetDoc - * target of advancing - * @return false if iterator exhausted, true otherwise. - */ - private static boolean advance(ScoredDocIDsIterator iterator, int targetDoc) { - while (iterator.next()) { - if (iterator.getDocID() >= targetDoc) { - return true; // target reached - } - } - return false; // exhausted - } - -} \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sampling/package.html b/lucene/facet/src/java/org/apache/lucene/facet/sampling/package.html deleted file mode 100644 index 2d34182afad..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sampling/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets sampling - - -Facets sampling. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/ArraysPool.java b/lucene/facet/src/java/org/apache/lucene/facet/search/ArraysPool.java deleted file mode 100644 index 69c8af30348..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/ArraysPool.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.util.Arrays; -import java.util.concurrent.ArrayBlockingQueue; - -/* - * 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. - */ - -/** - * A thread-safe pool of {@code int[]} and {@code float[]} arrays. One specifies - * the maximum number of arrays in the constructor. Calls to - * {@link #allocateFloatArray()} or {@link #allocateIntArray()} take an array - * from the pool, and if one is not available, allocate a new one. When you are - * done using the array, you should {@link #free(int[]) free} it. - *

- * This class is used by {@link ReusingFacetArrays} for temporal facet - * aggregation arrays, which can be reused across searches instead of being - * allocated afresh on every search. - * - * @lucene.experimental - */ -public final class ArraysPool { - - private final ArrayBlockingQueue intsPool; - private final ArrayBlockingQueue floatsPool; - - public final int arrayLength; - - /** - * Specifies the max number of arrays to pool, as well as the length of each - * array to allocate. - * - * @param arrayLength the size of the arrays to allocate - * @param maxArrays the maximum number of arrays to pool, from each type - * - * @throws IllegalArgumentException if maxArrays is set to 0. - */ - public ArraysPool(int arrayLength, int maxArrays) { - if (maxArrays == 0) { - throw new IllegalArgumentException( - "maxArrays cannot be 0 - don't use this class if you don't intend to pool arrays"); - } - this.arrayLength = arrayLength; - this.intsPool = new ArrayBlockingQueue(maxArrays); - this.floatsPool = new ArrayBlockingQueue(maxArrays); - } - - /** - * Allocates a new {@code int[]}. If there's an available array in the pool, - * it is used, otherwise a new array is allocated. - */ - public final int[] allocateIntArray() { - int[] arr = intsPool.poll(); - if (arr == null) { - return new int[arrayLength]; - } - Arrays.fill(arr, 0); // reset array - return arr; - } - - /** - * Allocates a new {@code float[]}. If there's an available array in the pool, - * it is used, otherwise a new array is allocated. - */ - public final float[] allocateFloatArray() { - float[] arr = floatsPool.poll(); - if (arr == null) { - return new float[arrayLength]; - } - Arrays.fill(arr, 0f); // reset array - return arr; - } - - /** - * Frees a no-longer-needed array. If there's room in the pool, the array is - * added to it, otherwise discarded. - */ - public final void free(int[] arr) { - if (arr != null) { - // use offer - if there isn't room, we don't want to wait - intsPool.offer(arr); - } - } - - /** - * Frees a no-longer-needed array. If there's room in the pool, the array is - * added to it, otherwise discarded. - */ - public final void free(float[] arr) { - if (arr != null) { - // use offer - if there isn't room, we don't want to wait - floatsPool.offer(arr); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/CachedOrdsCountingFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/CachedOrdsCountingFacetsAggregator.java deleted file mode 100644 index 4bc46973ff0..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/CachedOrdsCountingFacetsAggregator.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalsCache.CachedOrds; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which updates categories values by counting their - * occurrences in matching documents. Uses {@link OrdinalsCache} to obtain the - * category ordinals of each segment. - * - * @lucene.experimental - */ -public class CachedOrdsCountingFacetsAggregator extends IntRollupFacetsAggregator { - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - final CachedOrds ords = OrdinalsCache.getCachedOrds(matchingDocs.context, clp); - if (ords == null) { - return; // this segment has no ordinals for the given category list - } - final int[] counts = facetArrays.getIntArray(); - int doc = 0; - int length = matchingDocs.bits.length(); - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - int start = ords.offsets[doc]; - int end = ords.offsets[doc + 1]; - for (int i = start; i < end; i++) { - ++counts[ords.ordinals[i]]; - } - ++doc; - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/CategoryListIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/CategoryListIterator.java deleted file mode 100644 index 91ca03655ae..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/CategoryListIterator.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * An interface for obtaining the category ordinals of documents. - * {@link #getOrdinals(int, IntsRef)} calls are done with document IDs that are - * local to the reader given to {@link #setNextReader(AtomicReaderContext)}. - *

- * NOTE: this class operates as a key to a map, and therefore you should - * implement {@code equals()} and {@code hashCode()} for proper behavior. - * - * @lucene.experimental - */ -public interface CategoryListIterator { - - /** - * Sets the {@link AtomicReaderContext} for which - * {@link #getOrdinals(int, IntsRef)} calls will be made. Returns true iff any - * of the documents in this reader have category ordinals. This method must be - * called before any calls to {@link #getOrdinals(int, IntsRef)}. - */ - public boolean setNextReader(AtomicReaderContext context) throws IOException; - - /** - * Stores the category ordinals of the given document ID in the given - * {@link IntsRef}, starting at position 0 upto {@link IntsRef#length}. Grows - * the {@link IntsRef} if it is not large enough. - * - *

- * NOTE: if the requested document does not have category ordinals - * associated with it, {@link IntsRef#length} is set to zero. - */ - public void getOrdinals(int docID, IntsRef ints) throws IOException; - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java deleted file mode 100644 index 6daf5332800..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.apache.lucene.facet.search; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * Facet request for counting facets. - * - * @lucene.experimental - */ -public class CountFacetRequest extends FacetRequest { - - public CountFacetRequest(FacetLabel path, int num) { - super(path, num); - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - return CountingFacetsAggregator.create(fip.getCategoryListParams(categoryPath)); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java deleted file mode 100644 index 26c3fe1c9b6..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which counts the number of times each category - * appears in the given set of documents. This aggregator uses the - * {@link CategoryListIterator} to read the encoded categories. If you used the - * default settings while idnexing, you can use - * {@link FastCountingFacetsAggregator} for better performance. - * - * @lucene.experimental - */ -public class CountingFacetsAggregator extends IntRollupFacetsAggregator { - - /** - * Returns a {@link FacetsAggregator} suitable for counting categories given - * the {@link CategoryListParams}. - */ - public static FacetsAggregator create(CategoryListParams clp) { - if (clp.createEncoder().createMatchingDecoder().getClass() == DGapVInt8IntDecoder.class) { - return new FastCountingFacetsAggregator(); - } else { - return new CountingFacetsAggregator(); - } - } - - private final IntsRef ordinals = new IntsRef(32); - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - final CategoryListIterator cli = clp.createCategoryListIterator(0); - if (!cli.setNextReader(matchingDocs.context)) { - return; - } - - final int length = matchingDocs.bits.length(); - final int[] counts = facetArrays.getIntArray(); - int doc = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - cli.getOrdinals(doc, ordinals); - final int upto = ordinals.offset + ordinals.length; - for (int i = ordinals.offset; i < upto; i++) { - ++counts[ordinals.ints[i]]; - } - ++doc; - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java b/lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java deleted file mode 100644 index 6a51b983732..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/DepthOneFacetResultsHandler.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; - -import org.apache.lucene.facet.search.FacetRequest.SortOrder; -import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.util.CollectionUtil; -import org.apache.lucene.util.PriorityQueue; - -/* - * 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. - */ - -/** - * A {@link FacetResultsHandler} which counts the top-K facets at depth 1 only - * and always labels all result categories. The results are always sorted by - * value, in descending order. - * - * @lucene.experimental - */ -public class DepthOneFacetResultsHandler extends FacetResultsHandler { - - private static class FacetResultNodeQueue extends PriorityQueue { - - public FacetResultNodeQueue(int maxSize, boolean prepopulate) { - super(maxSize, prepopulate); - } - - @Override - protected FacetResultNode getSentinelObject() { - return new FacetResultNode(TaxonomyReader.INVALID_ORDINAL, 0); - } - - @Override - protected boolean lessThan(FacetResultNode a, FacetResultNode b) { - return a.compareTo(b) < 0; - } - - } - - public DepthOneFacetResultsHandler(TaxonomyReader taxonomyReader, FacetRequest facetRequest, FacetArrays facetArrays, - OrdinalValueResolver resolver) { - super(taxonomyReader, facetRequest, resolver, facetArrays); - assert facetRequest.getDepth() == 1 : "this handler only computes the top-K facets at depth 1"; - assert facetRequest.numResults == facetRequest.getNumLabel() : "this handler always labels all top-K results"; - assert facetRequest.getSortOrder() == SortOrder.DESCENDING : "this handler always sorts results in descending order"; - } - - @Override - public final FacetResult compute() throws IOException { - ParallelTaxonomyArrays arrays = taxonomyReader.getParallelTaxonomyArrays(); - final int[] children = arrays.children(); - final int[] siblings = arrays.siblings(); - - int rootOrd = taxonomyReader.getOrdinal(facetRequest.categoryPath); - - FacetResultNode root = new FacetResultNode(rootOrd, resolver.valueOf(rootOrd)); - root.label = facetRequest.categoryPath; - if (facetRequest.numResults > taxonomyReader.getSize()) { - // specialize this case, user is interested in all available results - ArrayList nodes = new ArrayList(); - int ordinal = children[rootOrd]; - while (ordinal != TaxonomyReader.INVALID_ORDINAL) { - double value = resolver.valueOf(ordinal); - if (value > 0) { - FacetResultNode node = new FacetResultNode(ordinal, value); - node.label = taxonomyReader.getPath(ordinal); - nodes.add(node); - } - ordinal = siblings[ordinal]; - } - - CollectionUtil.introSort(nodes, Collections.reverseOrder(new Comparator() { - @Override - public int compare(FacetResultNode o1, FacetResultNode o2) { - return o1.compareTo(o2); - } - })); - - root.subResults = nodes; - return new FacetResult(facetRequest, root, nodes.size()); - } - - // since we use sentinel objects, we cannot reuse PQ. but that's ok because it's not big - PriorityQueue pq = new FacetResultNodeQueue(facetRequest.numResults, true); - int ordinal = children[rootOrd]; - FacetResultNode top = pq.top(); - int numSiblings = 0; - while (ordinal != TaxonomyReader.INVALID_ORDINAL) { - double value = resolver.valueOf(ordinal); - if (value > 0) { - ++numSiblings; - if (value > top.value) { - top.value = value; - top.ordinal = ordinal; - top = pq.updateTop(); - } - } - ordinal = siblings[ordinal]; - } - - // pop() the least (sentinel) elements - int pqsize = pq.size(); - int size = numSiblings < pqsize ? numSiblings : pqsize; - for (int i = pqsize - size; i > 0; i--) { pq.pop(); } - - // create the FacetResultNodes. - FacetResultNode[] subResults = new FacetResultNode[size]; - for (int i = size - 1; i >= 0; i--) { - FacetResultNode node = pq.pop(); - node.label = taxonomyReader.getPath(node.ordinal); - subResults[i] = node; - } - root.subResults = Arrays.asList(subResults); - return new FacetResult(facetRequest, root, numSiblings); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/DocValuesCategoryListIterator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/DocValuesCategoryListIterator.java deleted file mode 100644 index 916aec2263e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/DocValuesCategoryListIterator.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** A {@link CategoryListIterator} which reads the ordinals from a {@link BinaryDocValues}. */ -public class DocValuesCategoryListIterator implements CategoryListIterator { - - private final IntDecoder decoder; - private final String field; - private final int hashCode; - private final BytesRef bytes = new BytesRef(32); - - private BinaryDocValues current; - - /** - * Constructs a new {@link DocValuesCategoryListIterator}. - */ - public DocValuesCategoryListIterator(String field, IntDecoder decoder) { - this.field = field; - this.decoder = decoder; - this.hashCode = field.hashCode(); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof DocValuesCategoryListIterator)) { - return false; - } - DocValuesCategoryListIterator other = (DocValuesCategoryListIterator) o; - if (hashCode != other.hashCode) { - return false; - } - - // Hash codes are the same, check equals() to avoid cases of hash-collisions. - return field.equals(other.field); - } - - @Override - public boolean setNextReader(AtomicReaderContext context) throws IOException { - current = context.reader().getBinaryDocValues(field); - return current != null; - } - - @Override - public void getOrdinals(int docID, IntsRef ints) throws IOException { - assert current != null : "don't call this if setNextReader returned false"; - current.get(docID, bytes); - ints.length = 0; - if (bytes.length > 0) { - decoder.decode(bytes, ints); - } - } - - @Override - public String toString() { - return field; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDownQuery.java b/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDownQuery.java deleted file mode 100644 index 6c4576ff40c..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDownQuery.java +++ /dev/null @@ -1,222 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.BooleanClause.Occur; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.ConstantScoreQuery; -import org.apache.lucene.search.Filter; -import org.apache.lucene.search.FilteredQuery; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; - -/** - * A {@link Query} for drill-down over {@link FacetLabel categories}. You - * should call {@link #add(FacetLabel...)} for every group of categories you - * want to drill-down over. Each category in the group is {@code OR'ed} with - * the others, and groups are {@code AND'ed}. - *

- * NOTE: if you choose to create your own {@link Query} by calling - * {@link #term}, it is recommended to wrap it with {@link ConstantScoreQuery} - * and set the {@link ConstantScoreQuery#setBoost(float) boost} to {@code 0.0f}, - * so that it does not affect the scores of the documents. - * - * @lucene.experimental - */ -public final class DrillDownQuery extends Query { - - /** Return a drill-down {@link Term} for a category. */ - public static Term term(FacetIndexingParams iParams, FacetLabel path) { - CategoryListParams clp = iParams.getCategoryListParams(path); - char[] buffer = new char[path.fullPathLength()]; - iParams.drillDownTermText(path, buffer); - return new Term(clp.field, String.valueOf(buffer)); - } - - private final BooleanQuery query; - private final Map drillDownDims = new LinkedHashMap(); - final FacetIndexingParams fip; - - /** Used by clone() */ - DrillDownQuery(FacetIndexingParams fip, BooleanQuery query, Map drillDownDims) { - this.fip = fip; - this.query = query.clone(); - this.drillDownDims.putAll(drillDownDims); - } - - /** Used by DrillSideways */ - DrillDownQuery(Filter filter, DrillDownQuery other) { - query = new BooleanQuery(true); // disable coord - - BooleanClause[] clauses = other.query.getClauses(); - if (clauses.length == other.drillDownDims.size()) { - throw new IllegalArgumentException("cannot apply filter unless baseQuery isn't null; pass ConstantScoreQuery instead"); - } - assert clauses.length == 1+other.drillDownDims.size(): clauses.length + " vs " + (1+other.drillDownDims.size()); - drillDownDims.putAll(other.drillDownDims); - query.add(new FilteredQuery(clauses[0].getQuery(), filter), Occur.MUST); - for(int i=1;i clauses, Map drillDownDims) { - this.fip = fip; - this.query = new BooleanQuery(true); - if (baseQuery != null) { - query.add(baseQuery, Occur.MUST); - } - for(Query clause : clauses) { - query.add(clause, Occur.MUST); - } - this.drillDownDims.putAll(drillDownDims); - } - - /** - * Creates a new {@link DrillDownQuery} without a base query, - * to perform a pure browsing query (equivalent to using - * {@link MatchAllDocsQuery} as base). - */ - public DrillDownQuery(FacetIndexingParams fip) { - this(fip, null); - } - - /** - * Creates a new {@link DrillDownQuery} over the given base query. Can be - * {@code null}, in which case the result {@link Query} from - * {@link #rewrite(IndexReader)} will be a pure browsing query, filtering on - * the added categories only. - */ - public DrillDownQuery(FacetIndexingParams fip, Query baseQuery) { - query = new BooleanQuery(true); // disable coord - if (baseQuery != null) { - query.add(baseQuery, Occur.MUST); - } - this.fip = fip; - } - - /** - * Adds one dimension of drill downs; if you pass multiple values they are - * OR'd, and then the entire dimension is AND'd against the base query. - */ - public void add(FacetLabel... paths) { - Query q; - if (paths[0].length == 0) { - throw new IllegalArgumentException("all CategoryPaths must have length > 0"); - } - String dim = paths[0].components[0]; - if (drillDownDims.containsKey(dim)) { - throw new IllegalArgumentException("dimension '" + dim + "' was already added"); - } - if (paths.length == 1) { - q = new TermQuery(term(fip, paths[0])); - } else { - BooleanQuery bq = new BooleanQuery(true); // disable coord - for (FacetLabel cp : paths) { - if (cp.length == 0) { - throw new IllegalArgumentException("all CategoryPaths must have length > 0"); - } - if (!cp.components[0].equals(dim)) { - throw new IllegalArgumentException("multiple (OR'd) drill-down paths must be under same dimension; got '" - + dim + "' and '" + cp.components[0] + "'"); - } - bq.add(new TermQuery(term(fip, cp)), Occur.SHOULD); - } - q = bq; - } - - add(dim, q); - } - - /** Expert: add a custom drill-down subQuery. Use this - * when you have a separate way to drill-down on the - * dimension than the indexed facet ordinals. */ - public void add(String dim, Query subQuery) { - - // TODO: we should use FilteredQuery? - - // So scores of the drill-down query don't have an - // effect: - final ConstantScoreQuery drillDownQuery = new ConstantScoreQuery(subQuery); - drillDownQuery.setBoost(0.0f); - - query.add(drillDownQuery, Occur.MUST); - - drillDownDims.put(dim, drillDownDims.size()); - } - - @Override - public DrillDownQuery clone() { - return new DrillDownQuery(fip, query, drillDownDims); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - return prime * result + query.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof DrillDownQuery)) { - return false; - } - - DrillDownQuery other = (DrillDownQuery) obj; - return query.equals(other.query) && super.equals(other); - } - - @Override - public Query rewrite(IndexReader r) throws IOException { - if (query.clauses().size() == 0) { - // baseQuery given to the ctor was null + no drill-downs were added - // note that if only baseQuery was given to the ctor, but no drill-down terms - // is fine, since the rewritten query will be the original base query. - throw new IllegalStateException("no base query or drill-down categories given"); - } - return query; - } - - @Override - public String toString(String field) { - return query.toString(field); - } - - BooleanQuery getBooleanQuery() { - return query; - } - - Map getDims() { - return drillDownDims; - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysCollector.java b/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysCollector.java deleted file mode 100644 index 01dded79e13..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysCollector.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.Arrays; -import java.util.IdentityHashMap; -import java.util.Map; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.Scorer.ChildScorer; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Weight; - -/** Collector that scrutinizes each hit to determine if it - * passed all constraints (a true hit) or if it missed - * exactly one dimension (a near-miss, to count for - * drill-sideways counts on that dimension). */ -class DrillSidewaysCollector extends Collector { - - private final Collector hitCollector; - private final Collector drillDownCollector; - private final Collector[] drillSidewaysCollectors; - private final Scorer[] subScorers; - private final int exactCount; - - // Maps Weight to either -1 (mainQuery) or to integer - // index of the dims drillDown. We needs this when - // visiting the child scorers to correlate back to the - // right scorers: - private final Map weightToIndex = new IdentityHashMap(); - - private Scorer mainScorer; - - public DrillSidewaysCollector(Collector hitCollector, Collector drillDownCollector, Collector[] drillSidewaysCollectors, - Map dims) { - this.hitCollector = hitCollector; - this.drillDownCollector = drillDownCollector; - this.drillSidewaysCollectors = drillSidewaysCollectors; - subScorers = new Scorer[dims.size()]; - - if (dims.size() == 1) { - // When we have only one dim, we insert the - // MatchAllDocsQuery, bringing the clause count to - // 2: - exactCount = 2; - } else { - exactCount = dims.size(); - } - } - - @Override - public void collect(int doc) throws IOException { - //System.out.println("collect doc=" + doc + " main.freq=" + mainScorer.freq() + " main.doc=" + mainScorer.docID() + " exactCount=" + exactCount); - - if (mainScorer == null) { - // This segment did not have any docs with any - // drill-down field & value: - return; - } - - if (mainScorer.freq() == exactCount) { - // All sub-clauses from the drill-down filters - // matched, so this is a "real" hit, so we first - // collect in both the hitCollector and the - // drillDown collector: - //System.out.println(" hit " + drillDownCollector); - hitCollector.collect(doc); - if (drillDownCollector != null) { - drillDownCollector.collect(doc); - } - - // Also collect across all drill-sideways counts so - // we "merge in" drill-down counts for this - // dimension. - for(int i=0;i doc: "subDoc=" + subDoc + " doc=" + doc; - drillSidewaysCollectors[i].collect(doc); - assert allMatchesFrom(i+1, doc); - found = true; - break; - } - } - assert found; - } - } - - // Only used by assert: - private boolean allMatchesFrom(int startFrom, int doc) { - for(int i=startFrom;i 1 || (nullCount == 1 && dims.length == 1)) { - return null; - } - - // Sort drill-downs by most restrictive first: - Arrays.sort(dims); - - // TODO: it could be better if we take acceptDocs - // into account instead of baseScorer? - Scorer baseScorer = baseWeight.scorer(context, scoreDocsInOrder, false, acceptDocs); - - if (baseScorer == null) { - return null; - } - - return new DrillSidewaysScorer(this, context, - baseScorer, - drillDownCollector, dims); - } - }; - } - - // TODO: these should do "deeper" equals/hash on the 2-D drillDownTerms array - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((baseQuery == null) ? 0 : baseQuery.hashCode()); - result = prime * result - + ((drillDownCollector == null) ? 0 : drillDownCollector.hashCode()); - result = prime * result + Arrays.hashCode(drillDownTerms); - result = prime * result + Arrays.hashCode(drillSidewaysCollectors); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (!super.equals(obj)) return false; - if (getClass() != obj.getClass()) return false; - DrillSidewaysQuery other = (DrillSidewaysQuery) obj; - if (baseQuery == null) { - if (other.baseQuery != null) return false; - } else if (!baseQuery.equals(other.baseQuery)) return false; - if (drillDownCollector == null) { - if (other.drillDownCollector != null) return false; - } else if (!drillDownCollector.equals(other.drillDownCollector)) return false; - if (!Arrays.equals(drillDownTerms, other.drillDownTerms)) return false; - if (!Arrays.equals(drillSidewaysCollectors, other.drillSidewaysCollectors)) return false; - return true; - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java b/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java deleted file mode 100644 index 42f53905935..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java +++ /dev/null @@ -1,654 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Weight; -import org.apache.lucene.util.FixedBitSet; - -class DrillSidewaysScorer extends Scorer { - - //private static boolean DEBUG = false; - - private final Collector drillDownCollector; - - private final DocsEnumsAndFreq[] dims; - - // DrillDown DocsEnums: - private final Scorer baseScorer; - - private final AtomicReaderContext context; - - private static final int CHUNK = 2048; - private static final int MASK = CHUNK-1; - - private int collectDocID = -1; - private float collectScore; - - DrillSidewaysScorer(Weight w, AtomicReaderContext context, Scorer baseScorer, Collector drillDownCollector, - DocsEnumsAndFreq[] dims) { - super(w); - this.dims = dims; - this.context = context; - this.baseScorer = baseScorer; - this.drillDownCollector = drillDownCollector; - } - - @Override - public void score(Collector collector) throws IOException { - //if (DEBUG) { - // System.out.println("\nscore: reader=" + context.reader()); - //} - //System.out.println("score r=" + context.reader()); - collector.setScorer(this); - if (drillDownCollector != null) { - drillDownCollector.setScorer(this); - drillDownCollector.setNextReader(context); - } - for(DocsEnumsAndFreq dim : dims) { - dim.sidewaysCollector.setScorer(this); - dim.sidewaysCollector.setNextReader(context); - } - - // TODO: if we ever allow null baseScorer ... it will - // mean we DO score docs out of order ... hmm, or if we - // change up the order of the conjuntions below - assert baseScorer != null; - - // Position all scorers to their first matching doc: - baseScorer.nextDoc(); - for(DocsEnumsAndFreq dim : dims) { - for (DocsEnum docsEnum : dim.docsEnums) { - if (docsEnum != null) { - docsEnum.nextDoc(); - } - } - } - - final int numDims = dims.length; - - DocsEnum[][] docsEnums = new DocsEnum[numDims][]; - Collector[] sidewaysCollectors = new Collector[numDims]; - long drillDownCost = 0; - for(int dim=0;dim 1 && (dims[1].maxCost < baseQueryCost/10)) { - //System.out.println("drillDownAdvance"); - doDrillDownAdvanceScoring(collector, docsEnums, sidewaysCollectors); - } else { - //System.out.println("union"); - doUnionScoring(collector, docsEnums, sidewaysCollectors); - } - } - - /** Used when drill downs are highly constraining vs - * baseQuery. */ - private void doDrillDownAdvanceScoring(Collector collector, DocsEnum[][] docsEnums, Collector[] sidewaysCollectors) throws IOException { - final int maxDoc = context.reader().maxDoc(); - final int numDims = dims.length; - - //if (DEBUG) { - // System.out.println(" doDrillDownAdvanceScoring"); - //} - - // TODO: maybe a class like BS, instead of parallel arrays - int[] filledSlots = new int[CHUNK]; - int[] docIDs = new int[CHUNK]; - float[] scores = new float[CHUNK]; - int[] missingDims = new int[CHUNK]; - int[] counts = new int[CHUNK]; - - docIDs[0] = -1; - int nextChunkStart = CHUNK; - - final FixedBitSet seen = new FixedBitSet(CHUNK); - - while (true) { - //if (DEBUG) { - // System.out.println("\ncycle nextChunkStart=" + nextChunkStart + " docIds[0]=" + docIDs[0]); - //} - - // First dim: - //if (DEBUG) { - // System.out.println(" dim0"); - //} - for(DocsEnum docsEnum : docsEnums[0]) { - if (docsEnum == null) { - continue; - } - int docID = docsEnum.docID(); - while (docID < nextChunkStart) { - int slot = docID & MASK; - - if (docIDs[slot] != docID) { - seen.set(slot); - // Mark slot as valid: - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " id=" + context.reader().document(docID).get("id")); - //} - docIDs[slot] = docID; - missingDims[slot] = 1; - counts[slot] = 1; - } - - docID = docsEnum.nextDoc(); - } - } - - // Second dim: - //if (DEBUG) { - // System.out.println(" dim1"); - //} - for(DocsEnum docsEnum : docsEnums[1]) { - if (docsEnum == null) { - continue; - } - int docID = docsEnum.docID(); - while (docID < nextChunkStart) { - int slot = docID & MASK; - - if (docIDs[slot] != docID) { - // Mark slot as valid: - seen.set(slot); - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " missingDim=0 id=" + context.reader().document(docID).get("id")); - //} - docIDs[slot] = docID; - missingDims[slot] = 0; - counts[slot] = 1; - } else { - // TODO: single-valued dims will always be true - // below; we could somehow specialize - if (missingDims[slot] >= 1) { - missingDims[slot] = 2; - counts[slot] = 2; - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " missingDim=2 id=" + context.reader().document(docID).get("id")); - //} - } else { - counts[slot] = 1; - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " missingDim=" + missingDims[slot] + " id=" + context.reader().document(docID).get("id")); - //} - } - } - - docID = docsEnum.nextDoc(); - } - } - - // After this we can "upgrade" to conjunction, because - // any doc not seen by either dim 0 or dim 1 cannot be - // a hit or a near miss: - - //if (DEBUG) { - // System.out.println(" baseScorer"); - //} - - // Fold in baseScorer, using advance: - int filledCount = 0; - int slot0 = 0; - while (slot0 < CHUNK && (slot0 = seen.nextSetBit(slot0)) != -1) { - int ddDocID = docIDs[slot0]; - assert ddDocID != -1; - - int baseDocID = baseScorer.docID(); - if (baseDocID < ddDocID) { - baseDocID = baseScorer.advance(ddDocID); - } - if (baseDocID == ddDocID) { - //if (DEBUG) { - // System.out.println(" keep docID=" + ddDocID + " id=" + context.reader().document(ddDocID).get("id")); - //} - scores[slot0] = baseScorer.score(); - filledSlots[filledCount++] = slot0; - counts[slot0]++; - } else { - //if (DEBUG) { - // System.out.println(" no docID=" + ddDocID + " id=" + context.reader().document(ddDocID).get("id")); - //} - docIDs[slot0] = -1; - - // TODO: we could jump slot0 forward to the - // baseDocID ... but we'd need to set docIDs for - // intervening slots to -1 - } - slot0++; - } - seen.clear(0, CHUNK); - - if (filledCount == 0) { - if (nextChunkStart >= maxDoc) { - break; - } - nextChunkStart += CHUNK; - continue; - } - - // TODO: factor this out & share w/ union scorer, - // except we start from dim=2 instead: - for(int dim=2;dim= dim) { - // TODO: single-valued dims will always be true - // below; we could somehow specialize - if (missingDims[slot] >= dim) { - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " count=" + (dim+2)); - //} - missingDims[slot] = dim+1; - counts[slot] = dim+2; - } else { - //if (DEBUG) { - // System.out.println(" set docID=" + docID + " missing count=" + (dim+1)); - //} - counts[slot] = dim+1; - } - } - // TODO: sometimes use advance? - docID = docsEnum.nextDoc(); - } - } - } - - // Collect: - //if (DEBUG) { - // System.out.println(" now collect: " + filledCount + " hits"); - //} - for(int i=0;i= maxDoc) { - break; - } - - nextChunkStart += CHUNK; - } - } - - @Override - public int docID() { - return collectDocID; - } - - @Override - public float score() { - return collectScore; - } - - @Override - public int freq() { - return 1+dims.length; - } - - @Override - public int nextDoc() { - throw new UnsupportedOperationException(); - } - - @Override - public int advance(int target) { - throw new UnsupportedOperationException(); - } - - @Override - public long cost() { - return baseScorer.cost(); - } - - @Override - public Collection getChildren() { - return Collections.singletonList(new ChildScorer(baseScorer, "MUST")); - } - - static class DocsEnumsAndFreq implements Comparable { - DocsEnum[] docsEnums; - // Max cost for all docsEnums for this dim: - long maxCost; - Collector sidewaysCollector; - String dim; - - @Override - public int compareTo(DocsEnumsAndFreq other) { - if (maxCost < other.maxCost) { - return -1; - } else if (maxCost > other.maxCost) { - return 1; - } else { - return 0; - } - } - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetArrays.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetArrays.java deleted file mode 100644 index c28ced75314..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetArrays.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -/** - * Provider of arrays used for facets aggregation. Returns either an - * {@code int[]} or {@code float[]} of the specified array length. When the - * arrays are no longer needed, you should call {@link #free()}, so that e.g. - * they will be reclaimed. - * - *

- * NOTE: if you need to reuse the allocated arrays between search - * requests, use {@link ReusingFacetArrays}. - * - *

- * NOTE: this class is not thread safe. You typically allocate it per - * search. - * - * @lucene.experimental - */ -public class FacetArrays { - - private int[] ints; - private float[] floats; - - public final int arrayLength; - - /** Arrays will be allocated at the specified length. */ - public FacetArrays(int arrayLength) { - this.arrayLength = arrayLength; - } - - protected float[] newFloatArray() { - return new float[arrayLength]; - } - - protected int[] newIntArray() { - return new int[arrayLength]; - } - - protected void doFree(float[] floats, int[] ints) { - } - - /** - * Notifies that the arrays obtained from {@link #getIntArray()} - * or {@link #getFloatArray()} are no longer needed and can be freed. - */ - public final void free() { - doFree(floats, ints); - ints = null; - floats = null; - } - - public final int[] getIntArray() { - if (ints == null) { - ints = newIntArray(); - } - return ints; - } - - public final float[] getFloatArray() { - if (floats == null) { - floats = newFloatArray(); - } - return floats; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java deleted file mode 100644 index 687e7e1d61e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.apache.lucene.facet.search; - -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * Defines an aggregation request for a category. Allows specifying the - * {@link #numResults number of child categories} to return as well as - * {@link #getSortOrder() which} categories to consider the "top" (highest or - * lowest ranking ones). - *

- * If the category being aggregated is hierarchical, you can also specify the - * {@link #setDepth(int) depth} up which to aggregate child categories as well - * as how the result should be {@link #setResultMode(ResultMode) constructed}. - * - * @lucene.experimental - */ -public abstract class FacetRequest { - - /** - * When {@link FacetRequest#getDepth()} is greater than 1, defines the - * structure of the result as well as how constraints such as - * {@link FacetRequest#numResults} and {@link FacetRequest#getNumLabel()} are - * applied. - */ - public enum ResultMode { - /** - * Constraints are applied per node, and the result has a full tree - * structure. Default result mode. - */ - PER_NODE_IN_TREE, - - /** - * Constraints are applied globally, on total number of results, and the - * result has a flat structure. - */ - GLOBAL_FLAT - } - - /** - * Defines which categories to return. If {@link #DESCENDING} (the default), - * the highest {@link FacetRequest#numResults} weighted categories will be - * returned, otherwise the lowest ones. - */ - public enum SortOrder { ASCENDING, DESCENDING } - - /** The category being aggregated in this facet request. */ - public final FacetLabel categoryPath; - - /** The number of child categories to return for {@link #categoryPath}. */ - public final int numResults; - - private int numLabel; - private int depth = 1; - private SortOrder sortOrder = SortOrder.DESCENDING; - private ResultMode resultMode = ResultMode.PER_NODE_IN_TREE; - - // Computed at construction; based on categoryPath and numResults. - private final int hashCode; - - /** - * Constructor with the given category to aggregate and the number of child - * categories to return. - * - * @param path - * the category to aggregate. Cannot be {@code null}. - * @param numResults - * the number of child categories to return. If set to - * {@code Integer.MAX_VALUE}, all immediate child categories will be - * returned. Must be greater than 0. - */ - public FacetRequest(FacetLabel path, int numResults) { - if (numResults <= 0) { - throw new IllegalArgumentException("num results must be a positive (>0) number: " + numResults); - } - if (path == null) { - throw new IllegalArgumentException("category path cannot be null!"); - } - categoryPath = path; - this.numResults = numResults; - numLabel = numResults; - hashCode = categoryPath.hashCode() ^ this.numResults; - } - - /** - * Returns the {@link FacetsAggregator} which can aggregate the categories of - * this facet request. The aggregator is expected to aggregate category values - * into {@link FacetArrays}. If the facet request does not support that, e.g. - * {@link RangeFacetRequest}, it can return {@code null}. Note though that - * such requests require a dedicated {@link FacetsAccumulator}. - */ - public abstract FacetsAggregator createFacetsAggregator(FacetIndexingParams fip); - - @Override - public boolean equals(Object o) { - if (o instanceof FacetRequest) { - FacetRequest that = (FacetRequest) o; - return that.hashCode == this.hashCode && - that.categoryPath.equals(this.categoryPath) && - that.numResults == this.numResults && - that.depth == this.depth && - that.resultMode == this.resultMode && - that.numLabel == this.numLabel && - that.sortOrder == this.sortOrder; - } - return false; - } - - /** - * How deeply to look under {@link #categoryPath}. By default, only its - * immediate children are aggregated (depth=1). If set to - * {@code Integer.MAX_VALUE}, the entire sub-tree of the category will be - * aggregated. - *

- * NOTE: setting depth to 0 means that only the category itself should - * be aggregated. In that case, make sure to index the category with - * {@link OrdinalPolicy#ALL_PARENTS}, unless it is not the root category (the - * dimension), in which case {@link OrdinalPolicy#ALL_BUT_DIMENSION} is fine - * too. - */ - public final int getDepth() { - // TODO an AUTO_EXPAND option could be useful - return depth; - } - - /** - * Allows to specify the number of categories to label. By default all - * returned categories are labeled. - *

- * This allows an app to request a large number of results to return, while - * labeling them on-demand (e.g. when the UI requests to show more - * categories). - */ - public final int getNumLabel() { - return numLabel; - } - - /** Return the requested result mode (defaults to {@link ResultMode#PER_NODE_IN_TREE}. */ - public final ResultMode getResultMode() { - return resultMode; - } - - /** Return the requested order of results (defaults to {@link SortOrder#DESCENDING}. */ - public final SortOrder getSortOrder() { - return sortOrder; - } - - @Override - public int hashCode() { - return hashCode; - } - - /** - * Sets the depth up to which to aggregate facets. - * - * @see #getDepth() - */ - public void setDepth(int depth) { - this.depth = depth; - } - - /** - * Sets the number of categories to label. - * - * @see #getNumLabel() - */ - public void setNumLabel(int numLabel) { - this.numLabel = numLabel; - } - - /** - * Sets the {@link ResultMode} for this request. - * - * @see #getResultMode() - */ - public void setResultMode(ResultMode resultMode) { - this.resultMode = resultMode; - } - - /** - * Sets the {@link SortOrder} for this request. - * - * @see #getSortOrder() - */ - public void setSortOrder(SortOrder sortOrder) { - this.sortOrder = sortOrder; - } - - @Override - public String toString() { - return categoryPath.toString() + " nRes=" + numResults + " nLbl=" + numLabel; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java deleted file mode 100644 index 447ebfa4c2a..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.util.CollectionUtil; - -/* - * 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. - */ - -/** - * Result of faceted search. - * - * @lucene.experimental - */ -public class FacetResult { - - private static FacetResultNode addIfNotExist(Map nodes, FacetResultNode node) { - FacetResultNode n = nodes.get(node.label); - if (n == null) { - nodes.put(node.label, node); - n = node; - } - return n; - } - - private final FacetRequest facetRequest; - private final FacetResultNode rootNode; - private final int numValidDescendants; - - public FacetResult(FacetRequest facetRequest, FacetResultNode rootNode, int numValidDescendants) { - this.facetRequest = facetRequest; - this.rootNode = rootNode; - this.numValidDescendants = numValidDescendants; - } - - /** - * Facet result node matching the root of the {@link #getFacetRequest() facet request}. - * @see #getFacetRequest() - * @see FacetRequest#categoryPath - */ - public final FacetResultNode getFacetResultNode() { - return rootNode; - } - - /** - * Number of descendants of {@link #getFacetResultNode() root facet result - * node}, up till the requested depth. - */ - public final int getNumValidDescendants() { - return numValidDescendants; - } - - /** - * Request for which this result was obtained. - */ - public final FacetRequest getFacetRequest() { - return this.facetRequest; - } - - /** - * String representation of this facet result. - * Use with caution: might return a very long string. - * @param prefix prefix for each result line - * @see #toString() - */ - public String toString(String prefix) { - StringBuilder sb = new StringBuilder(); - String nl = ""; - - // request - if (this.facetRequest != null) { - sb.append(nl).append(prefix).append("Request: ").append( - this.facetRequest.toString()); - nl = "\n"; - } - - // total facets - sb.append(nl).append(prefix).append("Num valid Descendants (up to specified depth): ").append( - this.numValidDescendants); - nl = "\n"; - - // result node - if (this.rootNode != null) { - sb.append(nl).append(this.rootNode.toString(prefix + "\t")); - } - - return sb.toString(); - } - - @Override - public String toString() { - return toString(""); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultNode.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultNode.java deleted file mode 100644 index 4e55c0b8973..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultNode.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.util.Collections; -import java.util.List; - -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * Result of faceted search for a certain taxonomy node. This class serves as a - * bin of different attributes of the result node, such as its {@link #ordinal} - * as well as {@link #label}. You are not expected to modify those values. - *

- * This class implements {@link Comparable} for easy comparisons of result - * nodes, e.g. when sorting or computing top-K nodes. - * - * @lucene.experimental - */ -public class FacetResultNode implements Comparable { - - public static final List EMPTY_SUB_RESULTS = Collections.emptyList(); - - /** The category ordinal of this node. */ - public int ordinal; - - /** - * The {@link FacetLabel label} of this result. May be {@code null} if not - * computed, in which case use {@link TaxonomyReader#getPath(int)} to label - * it. - *

- * NOTE: by default, all nodes are labeled. Only when - * {@link FacetRequest#getNumLabel()} < - * {@link FacetRequest#numResults} there will be unlabeled nodes. - */ - public FacetLabel label; - - /** - * The value of this result. Its actual type depends on the - * {@link FacetRequest} used (e.g. in case of {@link CountFacetRequest} it is - * {@code int}). - */ - public double value; - - /** - * The sub-results of this result. If {@link FacetRequest#getResultMode()} is - * {@link ResultMode#PER_NODE_IN_TREE}, every sub result denotes an immediate - * child of this node. Otherwise, it is a descendant of any level. - *

- * NOTE: this member should not be {@code null}. To denote that a - * result does not have sub results, set it to {@link #EMPTY_SUB_RESULTS} (or - * don't modify it). - */ - public List subResults = EMPTY_SUB_RESULTS; - - public FacetResultNode(int ordinal, double value) { - this.ordinal = ordinal; - this.value = value; - } - - @Override - public int compareTo(FacetResultNode o) { - int res = Double.compare(value, o.value); - if (res == 0) { - res = ordinal - o.ordinal; - } - return res; - } - - @Override - public String toString() { - return toString(""); - } - - /** Returns a String representation of this facet result node. */ - public String toString(String prefix) { - StringBuilder sb = new StringBuilder(prefix); - if (label == null) { - sb.append("not labeled (ordinal=").append(ordinal).append(")"); - } else { - sb.append(label.toString()); - } - sb.append(" (").append(Double.toString(value)).append(")"); - for (FacetResultNode sub : subResults) { - sb.append("\n").append(prefix).append(sub.toString(prefix + " ")); - } - return sb.toString(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultsHandler.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultsHandler.java deleted file mode 100644 index 9992d2dfce5..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResultsHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * Computes the top categories for a given {@link FacetRequest}. - * - * @lucene.experimental - */ -public abstract class FacetResultsHandler { - - public final TaxonomyReader taxonomyReader; - public final FacetRequest facetRequest; - - protected final OrdinalValueResolver resolver; - protected final FacetArrays facetArrays; - - public FacetResultsHandler(TaxonomyReader taxonomyReader, FacetRequest facetRequest, OrdinalValueResolver resolver, - FacetArrays facetArrays) { - this.taxonomyReader = taxonomyReader; - this.facetRequest = facetRequest; - this.facetArrays = facetArrays; - this.resolver = resolver; - } - - /** Computes the {@link FacetResult} for the given {@link FacetArrays}. */ - public abstract FacetResult compute() throws IOException; - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java deleted file mode 100644 index 9494c71a232..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * Accumulates the facets defined in the {@link FacetSearchParams}. - * - * @lucene.experimental - */ -public abstract class FacetsAccumulator { - - // TODO this should be final, but currently SamplingAccumulator modifies the params. - // need to review the class and if it's resolved, make it final - public /*final*/ FacetSearchParams searchParams; - - /** Constructor with the given search params. */ - protected FacetsAccumulator(FacetSearchParams fsp) { - this.searchParams = fsp; - } - - /** - * Creates a {@link FacetsAccumulator} for the given facet requests. This - * method supports {@link RangeAccumulator} and - * {@link TaxonomyFacetsAccumulator} by dividing the facet requests into - * {@link RangeFacetRequest} and the rest. - *

- * If both types of facet requests are used, it returns a - * {@link MultiFacetsAccumulator} and the facet results returned from - * {@link #accumulate(List)} may not be in the same order as the given facet - * requests. - * - * @param fsp - * the search params define the facet requests and the - * {@link FacetIndexingParams} - * @param indexReader - * the {@link IndexReader} used for search - * @param taxoReader - * the {@link TaxonomyReader} used for search - * @param arrays - * the {@link FacetArrays} which the accumulator should use to store - * the categories weights in. Can be {@code null}. - */ - public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader, - FacetArrays arrays) { - if (fsp.indexingParams.getPartitionSize() != Integer.MAX_VALUE) { - return new OldFacetsAccumulator(fsp, indexReader, taxoReader, arrays); - } - - return new TaxonomyFacetsAccumulator(fsp, indexReader, taxoReader, arrays); - } - - /** Returns an empty {@link FacetResult}. */ - protected static FacetResult emptyResult(int ordinal, FacetRequest fr) { - FacetResultNode root = new FacetResultNode(ordinal, 0); - root.label = fr.categoryPath; - return new FacetResult(fr, root, 0); - } - - /** - * Used by {@link FacetsCollector} to build the list of {@link FacetResult - * facet results} that match the {@link FacetRequest facet requests} that were - * given in the constructor. - * - * @param matchingDocs - * the documents that matched the query, per-segment. - */ - public abstract List accumulate(List matchingDocs) throws IOException; - - /** - * Used by {@link FacetsCollector} to determine if document scores need to be - * collected in addition to matching documents. - */ - public abstract boolean requiresDocScores(); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAggregator.java deleted file mode 100644 index 16cc9f47355..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAggregator.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; - -/* - * 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. - */ - -/** - * Aggregates categories that were found in result documents (specified by - * {@link MatchingDocs}). If the aggregator requires document scores too, it - * should return {@code true} from {@link #requiresDocScores()}. - * - * @lucene.experimental - */ -public interface FacetsAggregator { - - /** Aggregate the facets found in the given matching documents. */ - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException; - - /** - * Rollup the values of the given ordinal. This method is called when a - * category was indexed with {@link OrdinalPolicy#NO_PARENTS}. The given - * ordinal is the requested category, and you should use the children and - * siblings arrays to traverse its sub-tree. - */ - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays); - - /** Returns {@code true} if this aggregator requires document scores. */ - public boolean requiresDocScores(); - - /** - * Creates the appropriate {@link OrdinalValueResolver} for this aggregator - * and the given {@link FacetRequest}. The request is passed so that compound - * aggregators can return the correct {@link OrdinalValueResolver}. - */ - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java deleted file mode 100644 index 1b1f838e78b..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java +++ /dev/null @@ -1,249 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.FixedBitSet; - -/* - * 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. - */ - -/** - * A {@link Collector} which executes faceted search and computes the weight of - * requested facets. To get the facet results you should call - * {@link #getFacetResults()}. - * {@link #create(FacetSearchParams, IndexReader, TaxonomyReader)} returns the - * most optimized {@link FacetsCollector} for the given parameters. - * - * @lucene.experimental - */ -public abstract class FacetsCollector extends Collector { - - private static final class DocsAndScoresCollector extends FacetsCollector { - - private AtomicReaderContext context; - private Scorer scorer; - private FixedBitSet bits; - private int totalHits; - private float[] scores; - - public DocsAndScoresCollector(FacetsAccumulator accumulator) { - super(accumulator); - } - - @Override - protected final void finish() { - if (bits != null) { - matchingDocs.add(new MatchingDocs(this.context, bits, totalHits, scores)); - bits = null; - scores = null; - context = null; - } - } - - @Override - public final boolean acceptsDocsOutOfOrder() { - return false; - } - - @Override - public final void collect(int doc) throws IOException { - bits.set(doc); - if (totalHits >= scores.length) { - float[] newScores = new float[ArrayUtil.oversize(totalHits + 1, 4)]; - System.arraycopy(scores, 0, newScores, 0, totalHits); - scores = newScores; - } - scores[totalHits] = scorer.score(); - totalHits++; - } - - @Override - public final void setScorer(Scorer scorer) throws IOException { - this.scorer = scorer; - } - - @Override - protected final void doSetNextReader(AtomicReaderContext context) throws IOException { - if (bits != null) { - matchingDocs.add(new MatchingDocs(this.context, bits, totalHits, scores)); - } - bits = new FixedBitSet(context.reader().maxDoc()); - totalHits = 0; - scores = new float[64]; // some initial size - this.context = context; - } - - } - - private final static class DocsOnlyCollector extends FacetsCollector { - - private AtomicReaderContext context; - private FixedBitSet bits; - private int totalHits; - - public DocsOnlyCollector(FacetsAccumulator accumulator) { - super(accumulator); - } - - @Override - protected final void finish() { - if (bits != null) { - matchingDocs.add(new MatchingDocs(this.context, bits, totalHits, null)); - bits = null; - context = null; - } - } - - @Override - public final boolean acceptsDocsOutOfOrder() { - return true; - } - - @Override - public final void collect(int doc) throws IOException { - totalHits++; - bits.set(doc); - } - - @Override - public final void setScorer(Scorer scorer) throws IOException {} - - @Override - protected final void doSetNextReader(AtomicReaderContext context) throws IOException { - if (bits != null) { - matchingDocs.add(new MatchingDocs(this.context, bits, totalHits, null)); - } - bits = new FixedBitSet(context.reader().maxDoc()); - totalHits = 0; - this.context = context; - } - } - - /** - * Holds the documents that were matched in the {@link AtomicReaderContext}. - * If scores were required, then {@code scores} is not null. - */ - public final static class MatchingDocs { - - public final AtomicReaderContext context; - public final FixedBitSet bits; - public final float[] scores; - public final int totalHits; - - public MatchingDocs(AtomicReaderContext context, FixedBitSet bits, int totalHits, float[] scores) { - this.context = context; - this.bits = bits; - this.scores = scores; - this.totalHits = totalHits; - } - } - - /** - * Creates a {@link FacetsCollector} using the {@link - * FacetsAccumulator} from {@link FacetsAccumulator#create}. - */ - public static FacetsCollector create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) { - return create(FacetsAccumulator.create(fsp, indexReader, taxoReader, null)); - } - - /** - * Creates a {@link FacetsCollector} that satisfies the requirements of the - * given {@link FacetsAccumulator}. - */ - public static FacetsCollector create(FacetsAccumulator accumulator) { - if (accumulator.requiresDocScores()) { - return new DocsAndScoresCollector(accumulator); - } else { - return new DocsOnlyCollector(accumulator); - } - } - - private final FacetsAccumulator accumulator; - private List cachedResults; - - protected final List matchingDocs = new ArrayList(); - - protected FacetsCollector(FacetsAccumulator accumulator) { - this.accumulator = accumulator; - } - - /** - * Called when the Collector has finished, so that the last - * {@link MatchingDocs} can be added. - */ - protected abstract void finish(); - - /** Performs the actual work of {@link #setNextReader(AtomicReaderContext)}. */ - protected abstract void doSetNextReader(AtomicReaderContext context) throws IOException; - - /** - * Returns a {@link FacetResult} per {@link FacetRequest} set in - * {@link FacetSearchParams}. Note that if a {@link FacetRequest} defines a - * {@link FacetLabel} which does not exist in the taxonomy, an empty - * {@link FacetResult} will be returned for it. - */ - public final List getFacetResults() throws IOException { - // LUCENE-4893: if results are not cached, counts are multiplied as many - // times as this method is called. - if (cachedResults == null) { - finish(); - cachedResults = accumulator.accumulate(matchingDocs); - } - - return cachedResults; - } - - /** - * Returns the documents matched by the query, one {@link MatchingDocs} per - * visited segment. - */ - public final List getMatchingDocs() { - finish(); - return matchingDocs; - } - - /** - * Allows to reuse the collector between search requests. This method simply - * clears all collected documents (and scores) information (as well as cached - * results), and does not attempt to reuse allocated memory spaces. - */ - public final void reset() { - finish(); - matchingDocs.clear(); - cachedResults = null; - } - - @Override - public final void setNextReader(AtomicReaderContext context) throws IOException { - // clear cachedResults - needed in case someone called getFacetResults() - // before doing a search and didn't call reset(). Defensive code to prevent - // traps. - cachedResults = null; - doSetNextReader(context); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java deleted file mode 100644 index fdb81a60cca..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder; -import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.util.BytesRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which counts the number of times each category - * appears in the given set of documents. This aggregator reads the categories - * from the {@link BinaryDocValues} field defined by - * {@link CategoryListParams#field}, and assumes that the category ordinals were - * encoded with {@link DGapVInt8IntEncoder}. - * - * @lucene.experimental - */ -public final class FastCountingFacetsAggregator extends IntRollupFacetsAggregator { - - private final BytesRef buf = new BytesRef(32); - - @Override - public final void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) - throws IOException { - assert clp.createEncoder().createMatchingDecoder().getClass() == DGapVInt8IntDecoder.class - : "this aggregator assumes ordinals were encoded as dgap+vint"; - - final BinaryDocValues dv = matchingDocs.context.reader().getBinaryDocValues(clp.field); - if (dv == null) { // this reader does not have DocValues for the requested category list - return; - } - - final int length = matchingDocs.bits.length(); - final int[] counts = facetArrays.getIntArray(); - int doc = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - dv.get(doc, buf); - if (buf.length > 0) { - // this document has facets - final int upto = buf.offset + buf.length; - int ord = 0; - int offset = buf.offset; - int prev = 0; - while (offset < upto) { - byte b = buf.bytes[offset++]; - if (b >= 0) { - prev = ord = ((ord << 7) | b) + prev; - assert ord < counts.length: "ord=" + ord + " vs maxOrd=" + counts.length; - ++counts[ord]; - ord = 0; - } else { - ord = (ord << 7) | (b & 0x7F); - } - } - } - ++doc; - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/Heap.java b/lucene/facet/src/java/org/apache/lucene/facet/search/Heap.java deleted file mode 100644 index 070bd84dad9..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/Heap.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -/** - * Declares an interface for heap (and heap alike) structures, - * handling a given type T - * - * @lucene.experimental - */ -public interface Heap { - /** - * Get and remove the top of the Heap
- * NOTE: Once {@link #pop()} is called no other {@link #add(Object)} or - * {@link #insertWithOverflow(Object)} should be called. - */ - public T pop(); - - /** Get (But not remove) the top of the Heap */ - public T top(); - - /** - * Insert a new value, returning the overflowen object
- * NOTE: This method should not be called after invoking {@link #pop()} - */ - public T insertWithOverflow(T value); - - /** - * Add a new value to the heap, return the new top().
- * Some implementations may choose to not implement this functionality. - * In such a case null should be returned.
- * NOTE: This method should not be called after invoking {@link #pop()} - */ - public T add(T frn); - - /** Clear the heap */ - public void clear(); - - /** Return the amount of objects currently in the heap */ - public int size(); -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/IntRollupFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/IntRollupFacetsAggregator.java deleted file mode 100644 index 4947f683aa3..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/IntRollupFacetsAggregator.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver.IntValueResolver; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which implements - * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)} by - * summing the values from {@link FacetArrays#getIntArray()}. Extending classes - * should only implement {@link #aggregate}. Also, {@link #requiresDocScores()} - * always returns false. - * - * @lucene.experimental - */ -public abstract class IntRollupFacetsAggregator implements FacetsAggregator { - - @Override - public abstract void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException; - - private int rollupValues(int ordinal, int[] children, int[] siblings, int[] values) { - int value = 0; - while (ordinal != TaxonomyReader.INVALID_ORDINAL) { - int childValue = values[ordinal]; - childValue += rollupValues(children[ordinal], children, siblings, values); - values[ordinal] = childValue; - value += childValue; - ordinal = siblings[ordinal]; - } - return value; - } - - @Override - public final void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - final int[] values = facetArrays.getIntArray(); - values[ordinal] += rollupValues(children[ordinal], children, siblings, values); - } - - @Override - public final boolean requiresDocScores() { - return false; - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return new IntValueResolver(arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java deleted file mode 100644 index e82f76bf828..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetsAccumulator; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; - -/** - * Wraps multiple {@link FacetsAccumulator} and returns a merged list of - * {@link FacetResult}, in the order the accumulators were given. - */ -public class MultiFacetsAccumulator extends FacetsAccumulator { - - private final FacetsAccumulator[] accumulators; - - /** Wraps the given {@link FacetsAccumulator accumulators}. */ - public static FacetsAccumulator wrap(FacetsAccumulator... accumulators) { - if (accumulators.length == 0) { - return accumulators[0]; - } else { - return new MultiFacetsAccumulator(accumulators); - } - } - - private MultiFacetsAccumulator(FacetsAccumulator... accumulators) { - super((FacetSearchParams) null); - this.accumulators = accumulators; - } - - @Override - public boolean requiresDocScores() { - for (FacetsAccumulator fa : accumulators) { - if (fa.requiresDocScores()) { - return true; - } - } - return false; - } - - @Override - public List accumulate(List matchingDocs) throws IOException { - List merged = new ArrayList(); - for (FacetsAccumulator fa : accumulators) { - merged.addAll(fa.accumulate(matchingDocs)); - } - return merged; - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java deleted file mode 100644 index cf966296fce..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetArrays; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetsAggregator; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which chains multiple aggregators for aggregating - * the association values of categories that belong to the same category list. - * While nothing prevents you from chaining general purpose aggregators, it is - * only useful for aggregating association values, as each association type is - * written in its own list. - * - * @lucene.experimental - */ -public class MultiFacetsAggregator implements FacetsAggregator { - - private final Map categoryAggregators; - private final List aggregators; - - /** - * Constructor. - *

- * The mapping is used to rollup the values of the specific category by the - * corresponding {@link FacetsAggregator}. It is ok to pass differnet - * {@link FacetsAggregator} instances for each {@link FacetLabel} - the - * constructor ensures that each aggregator type (determined by its - * class) is invoked only once. - */ - public MultiFacetsAggregator(Map aggregators) { - this.categoryAggregators = aggregators; - - // make sure that each FacetsAggregator class is invoked only once, or - // otherwise categories may be aggregated multiple times. - Map, FacetsAggregator> aggsClasses = - new HashMap,FacetsAggregator>(); - for (FacetsAggregator fa : aggregators.values()) { - aggsClasses.put(fa.getClass(), fa); - } - this.aggregators = new ArrayList(aggsClasses.values()); - } - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - for (FacetsAggregator fa : aggregators) { - fa.aggregate(matchingDocs, clp, facetArrays); - } - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - categoryAggregators.get(fr.categoryPath).rollupValues(fr, ordinal, children, siblings, facetArrays); - } - - @Override - public boolean requiresDocScores() { - for (FacetsAggregator fa : aggregators) { - if (fa.requiresDocScores()) { - return true; - } - } - return false; - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return categoryAggregators.get(facetRequest.categoryPath).createOrdinalValueResolver(facetRequest, arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalValueResolver.java b/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalValueResolver.java deleted file mode 100644 index e2285011fd3..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalValueResolver.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -/** - * Resolves an ordinal's value to given the {@link FacetArrays}. - * Implementations of this class are encouraged to initialize the needed array - * from {@link FacetArrays} in the constructor. - */ -public abstract class OrdinalValueResolver { - - /** - * An {@link OrdinalValueResolver} which resolves ordinals value from - * {@link FacetArrays#getIntArray()}, by returning the value in the array. - */ - public static final class IntValueResolver extends OrdinalValueResolver { - - private final int[] values; - - public IntValueResolver(FacetArrays arrays) { - super(arrays); - this.values = arrays.getIntArray(); - } - - @Override - public final double valueOf(int ordinal) { - return values[ordinal]; - } - - } - - /** - * An {@link OrdinalValueResolver} which resolves ordinals value from - * {@link FacetArrays#getFloatArray()}, by returning the value in the array. - */ - public static final class FloatValueResolver extends OrdinalValueResolver { - - private final float[] values; - - public FloatValueResolver(FacetArrays arrays) { - super(arrays); - this.values = arrays.getFloatArray(); - } - - @Override - public final double valueOf(int ordinal) { - return values[ordinal]; - } - - } - - protected final FacetArrays arrays; - - protected OrdinalValueResolver(FacetArrays arrays) { - this.arrays = arrays; - } - - /** Returns the value of the given ordinal. */ - public abstract double valueOf(int ordinal); - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalsCache.java b/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalsCache.java deleted file mode 100644 index 8b423fbc3da..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/OrdinalsCache.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -import org.apache.lucene.codecs.DocValuesFormat; -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; -import org.apache.lucene.util.RamUsageEstimator; - -/* - * 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. - */ - -/** - * A per-segment cache of documents' category ordinals. Every {@link CachedOrds} - * holds the ordinals in a raw {@code int[]}, and therefore consumes as much RAM - * as the total number of ordinals found in the segment. - * - *

- * NOTE: every {@link CachedOrds} is limited to 2.1B total ordinals. If - * that is a limitation for you then consider limiting the segment size to less - * documents, or use an alternative cache which pages through the category - * ordinals. - * - *

- * NOTE: when using this cache, it is advised to use a - * {@link DocValuesFormat} that does not cache the data in memory, at least for - * the category lists fields, or otherwise you'll be doing double-caching. - */ -public class OrdinalsCache { - - /** Holds the cached ordinals in two paralel {@code int[]} arrays. */ - public static final class CachedOrds { - - public final int[] offsets; - public final int[] ordinals; - - /** - * Creates a new {@link CachedOrds} from the {@link BinaryDocValues}. - * Assumes that the {@link BinaryDocValues} is not {@code null}. - */ - public CachedOrds(BinaryDocValues dv, int maxDoc, CategoryListParams clp) { - final BytesRef buf = new BytesRef(); - - offsets = new int[maxDoc + 1]; - int[] ords = new int[maxDoc]; // let's assume one ordinal per-document as an initial size - - // this aggregator is limited to Integer.MAX_VALUE total ordinals. - int totOrds = 0; - final IntDecoder decoder = clp.createEncoder().createMatchingDecoder(); - final IntsRef values = new IntsRef(32); - for (int docID = 0; docID < maxDoc; docID++) { - offsets[docID] = totOrds; - dv.get(docID, buf); - if (buf.length > 0) { - // this document has facets - decoder.decode(buf, values); - if (totOrds + values.length >= ords.length) { - ords = ArrayUtil.grow(ords, totOrds + values.length + 1); - } - for (int i = 0; i < values.length; i++) { - ords[totOrds++] = values.ints[i]; - } - } - } - offsets[maxDoc] = totOrds; - - // if ords array is bigger by more than 10% of what we really need, shrink it - if ((double) totOrds / ords.length < 0.9) { - this.ordinals = new int[totOrds]; - System.arraycopy(ords, 0, this.ordinals, 0, totOrds); - } else { - this.ordinals = ords; - } - } - } - - // outer map is a WeakHashMap which uses reader.getCoreCacheKey() as the weak - // reference. When it's no longer referenced, the entire inner map can be - // evicted. - private static final Map> ordsCache = new WeakHashMap>(); - - /** - * Returns the {@link CachedOrds} relevant to the given - * {@link AtomicReaderContext}, or {@code null} if there is no - * {@link BinaryDocValues} in this reader for the requested - * {@link CategoryListParams#field}. - */ - public static synchronized CachedOrds getCachedOrds(AtomicReaderContext context, CategoryListParams clp) throws IOException { - BinaryDocValues dv = context.reader().getBinaryDocValues(clp.field); - if (dv == null) { - return null; - } - Map fieldCache = ordsCache.get(context.reader().getCoreCacheKey()); - if (fieldCache == null) { - fieldCache = new HashMap(); - ordsCache.put(context.reader().getCoreCacheKey(), fieldCache); - } - CachedOrds co = fieldCache.get(clp.field); - if (co == null) { - co = new CachedOrds(dv, context.reader().maxDoc(), clp); - fieldCache.put(clp.field, co); - } - return co; - } - - /** Returns how many bytes the static ords cache is - * consuming. */ - public synchronized static long ramBytesUsed() { - long size = 0; - for (Map e : ordsCache.values()) { - for (CachedOrds co : e.values()) { - size += RamUsageEstimator.NUM_BYTES_OBJECT_REF // CachedOrds reference in the map - + RamUsageEstimator.NUM_BYTES_OBJECT_HEADER // CachedOrds object header - + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER * 2 // 2 int[] (header) - + RamUsageEstimator.NUM_BYTES_OBJECT_REF * 2 // 2 int[] (ref) - + RamUsageEstimator.NUM_BYTES_INT * co.offsets.length // sizeOf(offsets) - + RamUsageEstimator.NUM_BYTES_INT * co.ordinals.length; // sizeOf(ordinals) - } - } - return size; - } - - /** Clears all entries from the cache. */ - public synchronized static void clear() { - ordsCache.clear(); - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java deleted file mode 100644 index 810740912bb..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.Map; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which invokes the proper aggregator per - * {@link CategoryListParams}. - * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)} is - * delegated to the proper aggregator which handles the - * {@link CategoryListParams} the given {@link FacetRequest} belongs to. - */ -public class PerCategoryListAggregator implements FacetsAggregator { - - private final Map aggregators; - private final FacetIndexingParams fip; - - public PerCategoryListAggregator(Map aggregators, FacetIndexingParams fip) { - this.aggregators = aggregators; - this.fip = fip; - } - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - aggregators.get(clp).aggregate(matchingDocs, clp, facetArrays); - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - CategoryListParams clp = fip.getCategoryListParams(fr.categoryPath); - aggregators.get(clp).rollupValues(fr, ordinal, children, siblings, facetArrays); - } - - @Override - public boolean requiresDocScores() { - for (FacetsAggregator aggregator : aggregators.values()) { - if (aggregator.requiresDocScores()) { - return true; - } - } - return false; - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - CategoryListParams clp = fip.getCategoryListParams(facetRequest.categoryPath); - return aggregators.get(clp).createOrdinalValueResolver(facetRequest, arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/ReusingFacetArrays.java b/lucene/facet/src/java/org/apache/lucene/facet/search/ReusingFacetArrays.java deleted file mode 100644 index 29e7afc1812..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/ReusingFacetArrays.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -/** - * A {@link FacetArrays} which uses the {@link ArraysPool} to allocate new - * arrays and pool them on {@link #free()}. - * - * @lucene.experimental - */ -public class ReusingFacetArrays extends FacetArrays { - - private final ArraysPool arraysPool; - - public ReusingFacetArrays(ArraysPool arraysPool) { - super(arraysPool.arrayLength); - this.arraysPool = arraysPool; - } - - @Override - protected int[] newIntArray() { - return arraysPool.allocateIntArray(); - } - - @Override - protected float[] newFloatArray() { - return arraysPool.allocateFloatArray(); - } - - @Override - protected void doFree(float[] floats, int[] ints) { - arraysPool.free(floats); - arraysPool.free(ints); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java deleted file mode 100644 index 6703fc53ced..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.apache.lucene.facet.search; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; - -/* - * 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. - */ - -/** - * A {@link FacetRequest} for weighting facets by summing the scores of matching - * documents. - * - * @lucene.experimental - */ -public class SumScoreFacetRequest extends FacetRequest { - - /** Create a score facet request for a given node in the taxonomy. */ - public SumScoreFacetRequest(FacetLabel path, int num) { - super(path, num); - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - return new SumScoreFacetsAggregator(); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetsAggregator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetsAggregator.java deleted file mode 100644 index e89fbd3b677..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetsAggregator.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver.FloatValueResolver; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link FacetsAggregator} which updates the weight of a category by summing the - * scores of documents it was found in. - */ -public class SumScoreFacetsAggregator implements FacetsAggregator { - - private final IntsRef ordinals = new IntsRef(32); - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - CategoryListIterator cli = clp.createCategoryListIterator(0); - if (!cli.setNextReader(matchingDocs.context)) { - return; - } - - int doc = 0; - int length = matchingDocs.bits.length(); - float[] scores = facetArrays.getFloatArray(); - int scoresIdx = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - cli.getOrdinals(doc, ordinals); - int upto = ordinals.offset + ordinals.length; - final float score = matchingDocs.scores[scoresIdx++]; - for (int i = ordinals.offset; i < upto; i++) { - scores[ordinals.ints[i]] += score; - } - ++doc; - } - } - - private float rollupScores(int ordinal, int[] children, int[] siblings, float[] scores) { - float score = 0f; - while (ordinal != TaxonomyReader.INVALID_ORDINAL) { - float childScore = scores[ordinal]; - childScore += rollupScores(children[ordinal], children, siblings, scores); - scores[ordinal] = childScore; - score += childScore; - ordinal = siblings[ordinal]; - } - return score; - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - float[] scores = facetArrays.getFloatArray(); - scores[ordinal] += rollupScores(children[ordinal], children, siblings, scores); - } - - @Override - public boolean requiresDocScores() { - return true; - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return new FloatValueResolver(arrays); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/SumValueSourceFacetRequest.java b/lucene/facet/src/java/org/apache/lucene/facet/search/SumValueSourceFacetRequest.java deleted file mode 100644 index 1d2e093108e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/SumValueSourceFacetRequest.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.apache.lucene.document.NumericDocValuesField; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.search.OrdinalValueResolver.FloatValueResolver; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.queries.function.FunctionValues; -import org.apache.lucene.queries.function.ValueSource; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link FacetRequest} which aggregates categories by the sum of the values, - * returned by a {@link ValueSource}, in the documents they are associated with. - * This allows aggregating the value of a category by e.g. summing the value of - * a {@link NumericDocValuesField} indexed for the document, or a more complex - * expression (from multiple fields) using the expressions module. - * - * @lucene.experimental - */ -public class SumValueSourceFacetRequest extends FacetRequest { - - private static abstract class SumValueSourceFacetsAggregator implements FacetsAggregator { - - protected final ValueSource valueSource; - protected final IntsRef ordinals = new IntsRef(32); - - protected SumValueSourceFacetsAggregator(ValueSource valueSource) { - this.valueSource = valueSource; - } - - private float doRollup(int ordinal, int[] children, int[] siblings, float[] values) { - float value = 0f; - while (ordinal != TaxonomyReader.INVALID_ORDINAL) { - float childValue = values[ordinal]; - childValue += doRollup(children[ordinal], children, siblings, values); - values[ordinal] = childValue; - value += childValue; - ordinal = siblings[ordinal]; - } - return value; - } - - @Override - public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) { - float[] values = facetArrays.getFloatArray(); - values[ordinal] += doRollup(children[ordinal], children, siblings, values); - } - - @Override - public OrdinalValueResolver createOrdinalValueResolver(FacetRequest facetRequest, FacetArrays arrays) { - return new FloatValueResolver(arrays); - } - - } - - private static class ScoreValueSourceFacetsAggregator extends SumValueSourceFacetsAggregator { - - private static final class FakeScorer extends Scorer { - float score; - int docID; - FakeScorer() { super(null); } - @Override public float score() throws IOException { return score; } - @Override public int freq() throws IOException { throw new UnsupportedOperationException(); } - @Override public int docID() { return docID; } - @Override public int nextDoc() throws IOException { throw new UnsupportedOperationException(); } - @Override public int advance(int target) throws IOException { throw new UnsupportedOperationException(); } - @Override public long cost() { return 0; } - } - - ScoreValueSourceFacetsAggregator(ValueSource valueSource) { - super(valueSource); - } - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - final CategoryListIterator cli = clp.createCategoryListIterator(0); - if (!cli.setNextReader(matchingDocs.context)) { - return; - } - - assert matchingDocs.scores != null; - - final FakeScorer scorer = new FakeScorer(); - Map context = new HashMap(); - context.put("scorer", scorer); - - final FunctionValues fvalues = valueSource.getValues(context, matchingDocs.context); - final int length = matchingDocs.bits.length(); - final float[] aggValues = facetArrays.getFloatArray(); - int doc = 0; - int scoresIdx = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - scorer.docID = doc; - scorer.score = matchingDocs.scores[scoresIdx++]; - cli.getOrdinals(doc, ordinals); - final int upto = ordinals.offset + ordinals.length; - float val = (float) fvalues.doubleVal(doc); - for (int i = ordinals.offset; i < upto; i++) { - aggValues[ordinals.ints[i]] += val; - } - ++doc; - } - } - - @Override - public boolean requiresDocScores() { - return true; - } - } - - private static class NoScoreValueSourceFacetsAggregator extends SumValueSourceFacetsAggregator { - - NoScoreValueSourceFacetsAggregator(ValueSource valueSource) { - super(valueSource); - } - - @Override - public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - final CategoryListIterator cli = clp.createCategoryListIterator(0); - if (!cli.setNextReader(matchingDocs.context)) { - return; - } - - final FunctionValues fvalues = valueSource.getValues(Collections.emptyMap(), matchingDocs.context); - final int length = matchingDocs.bits.length(); - final float[] aggValues = facetArrays.getFloatArray(); - int doc = 0; - while (doc < length && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) { - cli.getOrdinals(doc, ordinals); - final int upto = ordinals.offset + ordinals.length; - float val = (float) fvalues.doubleVal(doc); - for (int i = ordinals.offset; i < upto; i++) { - aggValues[ordinals.ints[i]] += val; - } - ++doc; - } - } - - @Override - public boolean requiresDocScores() { - return false; - } - } - - private final ValueSource valueSource; - private final boolean requiresDocScores; - - /** - * Constructor which takes the {@link ValueSource} from which to read the - * documents' values. You can also specify if the value source requires - * document scores or not. - */ - public SumValueSourceFacetRequest(FacetLabel path, int num, ValueSource valueSource, boolean requiresDocScores) { - super(path, num); - this.valueSource = valueSource; - this.requiresDocScores = requiresDocScores; - } - - @Override - public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) { - if (requiresDocScores) { - return new ScoreValueSourceFacetsAggregator(valueSource); - } else { - return new NoScoreValueSourceFacetsAggregator(valueSource); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java b/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java deleted file mode 100644 index b9fc5d8f31e..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.search.FacetRequest.SortOrder; -import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; - -/* - * 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. - */ - -/** - * A {@link FacetsAccumulator} suitable for accumulating categories that were - * indexed into a taxonomy index. - * - * @lucene.experimental - */ -public class TaxonomyFacetsAccumulator extends FacetsAccumulator { - - public final TaxonomyReader taxonomyReader; - public final IndexReader indexReader; - public final FacetArrays facetArrays; - - /** - * Initializes the accumulator with the given search params, index reader and - * taxonomy reader. This constructor creates the default {@link FacetArrays}, - * which do not support reuse. If you want to use {@link ReusingFacetArrays}, - * you should use the - * {@link #TaxonomyFacetsAccumulator(FacetSearchParams, IndexReader, TaxonomyReader)} - * constructor. - */ - public TaxonomyFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader) { - this(searchParams, indexReader, taxonomyReader, null); - } - - /** - * Initializes the accumulator with the given parameters as well as - * {@link FacetArrays}. Note that the accumulator doesn't call - * {@link FacetArrays#free()}. If you require that (only makes sense if you - * use {@link ReusingFacetArrays}, you should do it after you've finished with - * the accumulator. - */ - public TaxonomyFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, - TaxonomyReader taxonomyReader, FacetArrays facetArrays) { - super(searchParams); - this.facetArrays = facetArrays == null ? new FacetArrays(taxonomyReader.getSize()) : facetArrays; - this.indexReader = indexReader; - this.taxonomyReader = taxonomyReader; - } - - /** Group all requests that belong to the same {@link CategoryListParams}. */ - protected Map> groupRequests() { - if (searchParams.indexingParams.getAllCategoryListParams().size() == 1) { - return Collections.singletonMap(searchParams.indexingParams.getCategoryListParams(null), searchParams.facetRequests); - } - - HashMap> requestsPerCLP = new HashMap>(); - for (FacetRequest fr : searchParams.facetRequests) { - CategoryListParams clp = searchParams.indexingParams.getCategoryListParams(fr.categoryPath); - List requests = requestsPerCLP.get(clp); - if (requests == null) { - requests = new ArrayList(); - requestsPerCLP.put(clp, requests); - } - requests.add(fr); - } - return requestsPerCLP; - } - - /** - * Returns the {@link FacetsAggregator} to use for aggregating the categories - * found in the result documents. - */ - public FacetsAggregator getAggregator() { - Map> requestsPerCLP = groupRequests(); - - // optimize for all-CountFacetRequest and single category list (common case) - if (requestsPerCLP.size() == 1) { - boolean allCount = true; - for (FacetRequest fr : searchParams.facetRequests) { - if (!(fr instanceof CountFacetRequest)) { - allCount = false; - break; - } - } - if (allCount) { - return requestsPerCLP.values().iterator().next().get(0).createFacetsAggregator(searchParams.indexingParams); - } - } - - // If we're here it means the facet requests are spread across multiple - // category lists, or there are multiple types of facet requests, or both. - // Therefore create a per-CategoryList mapping of FacetsAggregators. - Map perCLPAggregator = new HashMap(); - for (Entry> e : requestsPerCLP.entrySet()) { - CategoryListParams clp = e.getKey(); - List requests = e.getValue(); - Map,FacetsAggregator> aggClasses = new HashMap,FacetsAggregator>(); - Map perCategoryAggregator = new HashMap(); - for (FacetRequest fr : requests) { - FacetsAggregator fa = fr.createFacetsAggregator(searchParams.indexingParams); - if (fa == null) { - throw new IllegalArgumentException("this accumulator only supports requests that create a FacetsAggregator: " + fr); - } - Class faClass = fa.getClass(); - if (!aggClasses.containsKey(faClass)) { - aggClasses.put(faClass, fa); - } else { - fa = aggClasses.get(faClass); - } - perCategoryAggregator.put(fr.categoryPath, fa); - } - - if (aggClasses.size() == 1) { // only one type of facet request - perCLPAggregator.put(clp, aggClasses.values().iterator().next()); - } else { - perCLPAggregator.put(clp, new MultiFacetsAggregator(perCategoryAggregator)); - } - } - - return new PerCategoryListAggregator(perCLPAggregator, searchParams.indexingParams); - } - - /** - * Creates a {@link FacetResultsHandler} that matches the given - * {@link FacetRequest}, using the {@link OrdinalValueResolver}. - */ - protected FacetResultsHandler createFacetResultsHandler(FacetRequest fr, OrdinalValueResolver resolver) { - if (fr.getDepth() == 1 && fr.getSortOrder() == SortOrder.DESCENDING) { - return new DepthOneFacetResultsHandler(taxonomyReader, fr, facetArrays, resolver); - } - - if (fr.getResultMode() == ResultMode.PER_NODE_IN_TREE) { - return new TopKInEachNodeHandler(taxonomyReader, fr, resolver, facetArrays); - } else { - return new TopKFacetResultsHandler(taxonomyReader, fr, resolver, facetArrays); - } - } - - /** - * Used by {@link FacetsCollector} to build the list of {@link FacetResult - * facet results} that match the {@link FacetRequest facet requests} that were - * given in the constructor. - * - * @param matchingDocs - * the documents that matched the query, per-segment. - */ - @Override - public List accumulate(List matchingDocs) throws IOException { - // aggregate facets per category list (usually onle one category list) - FacetsAggregator aggregator = getAggregator(); - for (CategoryListParams clp : groupRequests().keySet()) { - for (MatchingDocs md : matchingDocs) { - aggregator.aggregate(md, clp, facetArrays); - } - } - - ParallelTaxonomyArrays arrays = taxonomyReader.getParallelTaxonomyArrays(); - - // compute top-K - final int[] children = arrays.children(); - final int[] siblings = arrays.siblings(); - List res = new ArrayList(); - for (FacetRequest fr : searchParams.facetRequests) { - int rootOrd = taxonomyReader.getOrdinal(fr.categoryPath); - if (rootOrd == TaxonomyReader.INVALID_ORDINAL) { // category does not exist - // Add empty FacetResult - res.add(emptyResult(rootOrd, fr)); - continue; - } - CategoryListParams clp = searchParams.indexingParams.getCategoryListParams(fr.categoryPath); - if (fr.categoryPath.length > 0) { // someone might ask to aggregate the ROOT category - OrdinalPolicy ordinalPolicy = clp.getOrdinalPolicy(fr.categoryPath.components[0]); - if (ordinalPolicy == OrdinalPolicy.NO_PARENTS) { - // rollup values - aggregator.rollupValues(fr, rootOrd, children, siblings, facetArrays); - } - } - - FacetResultsHandler frh = createFacetResultsHandler(fr, aggregator.createOrdinalValueResolver(fr, facetArrays)); - res.add(frh.compute()); - } - return res; - } - - @Override - public boolean requiresDocScores() { - return getAggregator().requiresDocScores(); - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java b/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java deleted file mode 100644 index 81eb1fbd702..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/TopKFacetResultsHandler.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; - -import org.apache.lucene.facet.partitions.IntermediateFacetResult; -import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; -import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.util.ResultSortUtils; - -/* - * 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. - */ - -/** - * Generate Top-K results for a particular {@link FacetRequest}. K is global - * (among all results) and is defined by {@link FacetRequest#numResults}. - * - * @lucene.experimental - */ -public class TopKFacetResultsHandler extends PartitionsFacetResultsHandler { - - /** Construct top-K results handler. */ - public TopKFacetResultsHandler(TaxonomyReader taxonomyReader, FacetRequest facetRequest, - OrdinalValueResolver resolver, FacetArrays facetArrays) { - super(taxonomyReader, facetRequest, resolver, facetArrays); - } - - // fetch top K for specific partition. - @Override - public IntermediateFacetResult fetchPartitionResult(int offset) - throws IOException { - TopKFacetResult res = null; - int ordinal = taxonomyReader.getOrdinal(facetRequest.categoryPath); - if (ordinal != TaxonomyReader.INVALID_ORDINAL) { - double value = 0; - if (isSelfPartition(ordinal, facetArrays, offset)) { - int partitionSize = facetArrays.arrayLength; - value = resolver.valueOf(ordinal % partitionSize); - } - - FacetResultNode parentResultNode = new FacetResultNode(ordinal, value); - - Heap heap = ResultSortUtils.createSuitableHeap(facetRequest); - int totalFacets = heapDescendants(ordinal, heap, parentResultNode, offset); - res = new TopKFacetResult(facetRequest, parentResultNode, totalFacets); - res.setHeap(heap); - } - return res; - } - - // merge given top K results into current - @Override - public IntermediateFacetResult mergeResults(IntermediateFacetResult... tmpResults) throws IOException { - - int ordinal = taxonomyReader.getOrdinal(facetRequest.categoryPath); - FacetResultNode resNode = new FacetResultNode(ordinal, 0); - - int totalFacets = 0; - Heap heap = null; - - // merge other results in queue - for (IntermediateFacetResult tmpFres : tmpResults) { - // cast should succeed - TopKFacetResult fres = (TopKFacetResult) tmpFres; - totalFacets += fres.getNumValidDescendants(); - // set the value for the result node representing the facet request - resNode.value += fres.getFacetResultNode().value; - Heap tmpHeap = fres.getHeap(); - if (heap == null) { - heap = tmpHeap; - continue; - } - // bring sub results from heap of tmp res into result heap - for (int i = tmpHeap.size(); i > 0; i--) { - heap.insertWithOverflow(tmpHeap.pop()); - } - } - - TopKFacetResult res = new TopKFacetResult(facetRequest, resNode, totalFacets); - res.setHeap(heap); - return res; - } - - /** - * Finds the top K descendants of ordinal, which are at most facetRequest.getDepth() - * deeper than facetRequest.getCategoryPath (whose ordinal is input parameter ordinal). - * Candidates are restricted to current "counting list" and current "partition", - * they join the overall priority queue pq of size K. - * @return total number of descendants considered here by pq, excluding ordinal itself. - */ - private int heapDescendants(int ordinal, Heap pq, FacetResultNode parentResultNode, - int offset) throws IOException { - int partitionSize = facetArrays.arrayLength; - int endOffset = offset + partitionSize; - ParallelTaxonomyArrays childrenArray = taxonomyReader.getParallelTaxonomyArrays(); - int[] children = childrenArray.children(); - int[] siblings = childrenArray.siblings(); - FacetResultNode reusable = null; - int localDepth = 0; - int depth = facetRequest.getDepth(); - int[] ordinalStack = new int[2+Math.min(Short.MAX_VALUE, depth)]; - int childrenCounter = 0; - - int tosOrdinal; // top of stack element - - int yc = children[ordinal]; - while (yc >= endOffset) { - yc = siblings[yc]; - } - // make use of the fact that TaxonomyReader.INVALID_ORDINAL == -1, < endOffset - // and it, too, can stop the loop. - ordinalStack[++localDepth] = yc; - - /* - * stack holds input parameter ordinal in position 0. - * Other elements are < endoffset. - * Only top of stack can be TaxonomyReader.INVALID_ORDINAL, and this if and only if - * the element below it exhausted all its children: has them all processed. - * - * stack elements are processed (counted and accumulated) only if they - * belong to current partition (between offset and endoffset) and first time - * they are on top of stack - * - * loop as long as stack is not empty of elements other than input ordinal, or for a little while -- it sibling - */ - while (localDepth > 0) { - tosOrdinal = ordinalStack[localDepth]; - if (tosOrdinal == TaxonomyReader.INVALID_ORDINAL) { - // element below tos has all its children, and itself, all processed - // need to proceed to its sibling - localDepth--; - // change element now on top of stack to its sibling. - ordinalStack[localDepth] = siblings[ordinalStack[localDepth]]; - continue; - } - // top of stack is not invalid, this is the first time we see it on top of stack. - // collect it, if belongs to current partition, and then push its kids on itself, if applicable - if (tosOrdinal >= offset) { // tosOrdinal resides in current partition - int relativeOrdinal = tosOrdinal % partitionSize; - double value = resolver.valueOf(relativeOrdinal); - if (value != 0 && !Double.isNaN(value)) { - // Count current ordinal -- the TOS - if (reusable == null) { - reusable = new FacetResultNode(tosOrdinal, value); - } else { - // it is safe to cast since reusable was created here. - reusable.ordinal = tosOrdinal; - reusable.value = value; - reusable.subResults.clear(); - reusable.label = null; - } - ++childrenCounter; - reusable = pq.insertWithOverflow(reusable); - } - } - if (localDepth < depth) { - // push kid of current tos - yc = children[tosOrdinal]; - while (yc >= endOffset) { - yc = siblings[yc]; - } - ordinalStack[++localDepth] = yc; - } else { // localDepth == depth; current tos exhausted its possible children, mark this by pushing INVALID_ORDINAL - ordinalStack[++localDepth] = TaxonomyReader.INVALID_ORDINAL; - } - } // endof while stack is not empty - - return childrenCounter; // we're done - } - - @Override - public FacetResult renderFacetResult(IntermediateFacetResult tmpResult) { - TopKFacetResult res = (TopKFacetResult) tmpResult; // cast is safe by contract of this class - if (res != null) { - Heap heap = res.getHeap(); - FacetResultNode resNode = res.getFacetResultNode(); - if (resNode.subResults == FacetResultNode.EMPTY_SUB_RESULTS) { - resNode.subResults = new ArrayList(); - } - for (int i = heap.size(); i > 0; i--) { - resNode.subResults.add(0, heap.pop()); - } - } - return res; - } - - @Override - public FacetResult rearrangeFacetResult(FacetResult facetResult) { - TopKFacetResult res = (TopKFacetResult) facetResult; // cast is safe by contract of this class - Heap heap = res.getHeap(); - heap.clear(); // just to be safe - FacetResultNode topFrn = res.getFacetResultNode(); - for (FacetResultNode frn : topFrn.subResults) { - heap.add(frn); - } - int size = heap.size(); - ArrayList subResults = new ArrayList(size); - for (int i = heap.size(); i > 0; i--) { - subResults.add(0,heap.pop()); - } - topFrn.subResults = subResults; - return res; - } - - @Override - public void labelResult(FacetResult facetResult) throws IOException { - if (facetResult != null) { // any result to label? - FacetResultNode facetResultNode = facetResult.getFacetResultNode(); - if (facetResultNode != null) { // any result to label? - facetResultNode.label = taxonomyReader.getPath(facetResultNode.ordinal); - int num2label = facetRequest.getNumLabel(); - for (FacetResultNode frn : facetResultNode.subResults) { - if (--num2label < 0) { - break; - } - frn.label = taxonomyReader.getPath(frn.ordinal); - } - } - } - } - - //////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////// - - /** - * Private Mutable implementation of result of faceted search. - */ - private static class TopKFacetResult extends FacetResult implements IntermediateFacetResult { - - // TODO (Facet): is it worth to override PriorityQueue.getSentinelObject() - // for any of our PQs? - private Heap heap; - - /** - * Create a Facet Result. - * @param facetRequest Request for which this result was obtained. - * @param facetResultNode top result node for this facet result. - */ - TopKFacetResult(FacetRequest facetRequest, FacetResultNode facetResultNode, int totalFacets) { - super(facetRequest, facetResultNode, totalFacets); - } - - /** - * @return the heap - */ - public Heap getHeap() { - return heap; - } - - /** - * Set the heap for this result. - * @param heap heap top be set. - */ - public void setHeap(Heap heap) { - this.heap = heap; - } - - } - - ////////////////////////////////////////////////////// -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java b/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java deleted file mode 100644 index 02c1061f572..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java +++ /dev/null @@ -1,727 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.IntToObjectMap; -import org.apache.lucene.facet.partitions.IntermediateFacetResult; -import org.apache.lucene.facet.partitions.PartitionsFacetResultsHandler; -import org.apache.lucene.facet.search.FacetRequest.SortOrder; -import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.util.PriorityQueue; - -/* - * 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. - */ - -/** - * Generates {@link FacetResult} from the {@link FacetArrays} aggregated for a - * particular {@link FacetRequest}. The generated {@link FacetResult} is a - * subtree of the taxonomy tree. Its root node, - * {@link FacetResult#getFacetResultNode()}, is the facet specified by - * {@link FacetRequest#categoryPath}, and the enumerated children, - * {@link FacetResultNode#subResults}, of each node in that {@link FacetResult} - * are the top K ( = {@link FacetRequest#numResults}) among its children in the - * taxonomy. The depth (number of levels excluding the root) of the - * {@link FacetResult} tree is specified by {@link FacetRequest#getDepth()}. - *

- * Because the number of selected children of each node is restricted, and not - * the overall number of nodes in the {@link FacetResult}, facets not selected - * into {@link FacetResult} might have better values, or ordinals, (typically, - * higher counts), than facets that are selected into the {@link FacetResult}. - *

- * The generated {@link FacetResult} also provides with - * {@link FacetResult#getNumValidDescendants()}, which returns the total number - * of facets that are descendants of the root node, no deeper than - * {@link FacetRequest#getDepth()}, and which have valid value. The rootnode - * itself is not counted here. Valid value is determined by the - * {@link FacetResultsHandler}. {@link TopKInEachNodeHandler} defines valid as - * != 0. - *

- * NOTE: this code relies on the assumption that - * {@link TaxonomyReader#INVALID_ORDINAL} == -1, a smaller value than any valid - * ordinal. - * - * @lucene.experimental - */ -public class TopKInEachNodeHandler extends PartitionsFacetResultsHandler { - - public TopKInEachNodeHandler(TaxonomyReader taxonomyReader, FacetRequest facetRequest, OrdinalValueResolver resolver, - FacetArrays facetArrays) { - super(taxonomyReader, facetRequest, resolver, facetArrays); - } - - /** - * Recursively explore all facets that can be potentially included in the - * {@link FacetResult} to be generated, and that belong to the given - * partition, so that values can be examined and collected. For each such - * node, gather its top K ({@link FacetRequest#numResults}) children among its - * children that are encountered in the given particular partition (aka - * current counting list). - * @param offset - * to offset + the length of the count arrays within - * arrays (exclusive) - * - * @return {@link IntermediateFacetResult} consisting of - * {@link IntToObjectMap} that maps potential {@link FacetResult} - * nodes to their top K children encountered in the current partition. - * Note that the mapped potential tree nodes need not belong to the - * given partition, only the top K children mapped to. The aim is to - * identify nodes that are certainly excluded from the - * {@link FacetResult} to be eventually (after going through all the - * partitions) returned by this handler, because they have K better - * siblings, already identified in this partition. For the identified - * excluded nodes, we only count number of their descendants in the - * subtree (to be included in - * {@link FacetResult#getNumValidDescendants()}), but not bother with - * selecting top K in these generations, which, by definition, are, - * too, excluded from the FacetResult tree. - * @throws IOException - * in case - * {@link TaxonomyReader#getOrdinal(org.apache.lucene.facet.taxonomy.FacetLabel)} - * does. - * @see #fetchPartitionResult(int) - */ - @Override - public IntermediateFacetResult fetchPartitionResult(int offset) throws IOException { - - // get the root of the result tree to be returned, and the depth of that result tree - // (depth means number of node levels excluding the root). - int rootNode = this.taxonomyReader.getOrdinal(facetRequest.categoryPath); - if (rootNode == TaxonomyReader.INVALID_ORDINAL) { - return null; - } - - int K = Math.min(facetRequest.numResults,taxonomyReader.getSize()); // number of best results in each node - - // this will grow into the returned IntermediateFacetResult - IntToObjectMap AACOsOfOnePartition = new IntToObjectMap(); - - // all partitions, except, possibly, the last, have the same length. Hence modulo is OK. - int partitionSize = facetArrays.arrayLength; - - int depth = facetRequest.getDepth(); - - if (depth == 0) { - // Need to only have root node. - IntermediateFacetResultWithHash tempFRWH = new IntermediateFacetResultWithHash( - facetRequest, AACOsOfOnePartition); - if (isSelfPartition(rootNode, facetArrays, offset)) { - tempFRWH.isRootNodeIncluded = true; - tempFRWH.rootNodeValue = resolver.valueOf(rootNode % partitionSize); - } - return tempFRWH; - } - - if (depth > Short.MAX_VALUE - 3) { - depth = Short.MAX_VALUE -3; - } - - int endOffset = offset + partitionSize; // one past the largest ordinal in the partition - ParallelTaxonomyArrays childrenArray = taxonomyReader.getParallelTaxonomyArrays(); - int[] children = childrenArray.children(); - int[] siblings = childrenArray.siblings(); - int totalNumOfDescendantsConsidered = 0; // total number of facets with value != 0, - // in the tree. These include those selected as top K in each node, and all the others that - // were not. Not including rootNode - - // the following priority queue will be used again and again for each node recursed into - // to select its best K children among its children encountered in the given partition - PriorityQueue pq = - new AggregatedCategoryHeap(K, this.getSuitableACComparator()); - - // reusables will feed the priority queue in each use - AggregatedCategory [] reusables = new AggregatedCategory[2+K]; - for (int i = 0; i < reusables.length; i++) { - reusables[i] = new AggregatedCategory(1,0); - } - - /* - * The returned map is built by a recursive visit of potential tree nodes. Nodes - * determined to be excluded from the FacetResult are not recursively explored as others, - * they are only recursed in order to count the number of their descendants. - * Also, nodes that they and any of their descendants can not be mapped into facets encountered - * in this partition, are, too, explored no further. These are facets whose ordinal - * numbers are greater than the ordinals of the given partition. (recall that the Taxonomy - * maintains that a parent ordinal is smaller than any of its descendants' ordinals). - * So, when scanning over all children of a potential tree node n: (1) all children with ordinal number - * greater than those in the given partition are skipped over, (2) among the children of n residing - * in this partition, the best K children are selected (using pq) for usual further recursion - * and the rest (those rejected out from the pq) are only recursed for counting total number - * of descendants, and (3) all the children of ordinal numbers smaller than the given partition - * are further explored in the usual way, since these may lead to descendants residing in this partition. - * - * ordinalStack drives the recursive descent. - * Top of stack holds the current node which we recurse from. - * ordinalStack[0] holds the root of the facetRequest, and - * it is always maintained that parent(ordianlStack[i]) = ordinalStack[i-1]. - * localDepth points to the current top of ordinalStack. - * Only top of ordinalStack can be TaxonomyReader.INVALID_ORDINAL, and this if and only if - * the element below it explored all its relevant children. - */ - int[] ordinalStack = new int[depth+2]; // for 0 and for invalid on top - ordinalStack[0] = rootNode; - int localDepth = 0; - - /* - * bestSignlingsStack[i] maintains the best K children of ordinalStack[i-1], namely, - * the best K siblings of ordinalStack[i], best K among those residing in the given partition. - * Note that the residents of ordinalStack need not belong - * to the current partition, only the residents of bestSignlingsStack. - * When exploring the children of ordianlStack[i-1] that reside in the current partition - * (after the top K of them have been determined and stored into bestSignlingsStack[i]), - * siblingExplored[i] points into bestSignlingsStack[i], to the child now explored, hence - * residing in ordinalStack[i], and firstToTheLeftOfPartition[i] holds the largest ordinal of - * a sibling smaller than the ordinals in the partition. - * When siblingExplored[i] == max int, the top K siblings of ordinalStack[i] among those siblings - * that reside in this partition have not been determined yet. - * if siblingExplored[i] < 0, the node in ordinalStack[i] is to the left of partition - * (i.e. of a smaller ordinal than the current partition) - * (step (3) above is executed for the children of ordianlStack[i-1]) - */ - int[][] bestSignlingsStack = new int[depth+2][]; - int[] siblingExplored = new int[depth+2]; - int[] firstToTheLeftOfPartition = new int [depth+2]; - - int tosOrdinal; // top of stack element, the ordinal at the top of stack - - /* - * to start the loop, complete the datastructures for root node: - * push its youngest child to ordinalStack; make a note in siblingExplored[] that the children - * of rootNode, which reside in the current partition have not been read yet to select the top - * K of them. Also, make rootNode as if, related to its parent, rootNode belongs to the children - * of ordinal numbers smaller than those of the current partition (this will ease on end condition -- - * we can continue to the older sibling of rootNode once the localDepth goes down, before we verify that - * it went that down) - */ - ordinalStack[++localDepth] = children[rootNode]; - siblingExplored[localDepth] = Integer.MAX_VALUE; // we have not verified position wrt current partition - siblingExplored[0] = -1; // as if rootNode resides to the left of current position - - /* - * now the whole recursion: loop as long as stack is not empty of elements descendants of - * facetRequest's root. - */ - - while (localDepth > 0) { - tosOrdinal = ordinalStack[localDepth]; - if (tosOrdinal == TaxonomyReader.INVALID_ORDINAL) { - // the brotherhood that has been occupying the top of stack is all exhausted. - // Hence, element below tos, namely, father of tos, has all its children, - // and itself, all explored. - localDepth--; - // replace this father, now on top of stack, by this father's sibling: - // this parent's ordinal can not be greater than current partition, as otherwise - // its child, now just removed, would not have been pushed on it. - // so the father is either inside the partition, or smaller ordinal - if (siblingExplored[localDepth] < 0 ) { - ordinalStack[localDepth] = siblings[ordinalStack[localDepth]]; - continue; - } - // in this point, siblingExplored[localDepth] between 0 and number of bestSiblings - // it can not be max int - siblingExplored[localDepth]--; - if (siblingExplored[localDepth] == -1 ) { - //siblings residing in the partition have been all processed, we now move - // to those of ordinal numbers smaller than the partition - ordinalStack[localDepth] = firstToTheLeftOfPartition[localDepth]; - } else { - // still explore siblings residing in the partition - // just move to the next one - ordinalStack[localDepth] = bestSignlingsStack[localDepth][siblingExplored[localDepth]]; - } - continue; - } // endof tosOrdinal is invalid, and hence removed, and its parent was replaced by this - // parent's sibling - - // now try to push a kid, but first look at tos whether it 'deserves' its kids explored: - // it is not to the right of current partition, and we know whether to only count or to - // select best K siblings. - if (siblingExplored[localDepth] == Integer.MAX_VALUE) { - //tosOrdinal was not examined yet for its position relative to current partition - // and the best K of current partition, among its siblings, have not been determined yet - while (tosOrdinal >= endOffset) { - tosOrdinal = siblings[tosOrdinal]; - } - // now it is inside. Run it and all its siblings inside the partition through a heap - // and in doing so, count them, find best K - pq.clear(); - - //reusables are consumed as from a stack. The stack starts full and returns full. - int tosReuslables = reusables.length -1; - - while (tosOrdinal >= offset) { // while tosOrdinal belongs to the given partition; here, too, we use the fact - // that TaxonomyReader.INVALID_ORDINAL == -1 < offset - double value = resolver.valueOf(tosOrdinal % partitionSize); - if (value != 0) { // the value of yc is not 0, it is to be considered. - totalNumOfDescendantsConsidered++; - - // consume one reusable, and push to the priority queue - AggregatedCategory ac = reusables[tosReuslables--]; - ac.ordinal = tosOrdinal; - ac.value = value; - ac = pq.insertWithOverflow(ac); - if (null != ac) { - /* when a facet is excluded from top K, because already in this partition it has - * K better siblings, it is only recursed for count only. - */ - // update totalNumOfDescendants by the now excluded node and all its descendants - totalNumOfDescendantsConsidered--; // reduce the 1 earned when the excluded node entered the heap - // and now return it and all its descendants. These will never make it to FacetResult - totalNumOfDescendantsConsidered += countOnly (ac.ordinal, children, - siblings, partitionSize, offset, endOffset, localDepth, depth); - reusables[++tosReuslables] = ac; - } - } - tosOrdinal = siblings[tosOrdinal]; - } - // now pq has best K children of ordinals that belong to the given partition. - // Populate a new AACO with them. - // tosOrdinal is now first sibling smaller than partition, make a note of that - firstToTheLeftOfPartition[localDepth] = tosOrdinal; - int aaci = pq.size(); - int[] ords = new int[aaci]; - double [] vals = new double [aaci]; - while (aaci > 0) { - AggregatedCategory ac = pq.pop(); - ords[--aaci] = ac.ordinal; - vals[aaci] = ac.value; - reusables[++tosReuslables] = ac; - } - // if more than 0 ordinals, add this AACO to the map to be returned, - // and add ords to sibling stack, and make a note in siblingExplored that these are to - // be visited now - if (ords.length > 0) { - AACOsOfOnePartition.put(ordinalStack[localDepth-1], new AACO(ords,vals)); - bestSignlingsStack[localDepth] = ords; - siblingExplored[localDepth] = ords.length-1; - ordinalStack[localDepth] = ords[ords.length-1]; - } else { - // no ordinals siblings of tosOrdinal in current partition, move to the left of it - // tosOrdinal is already there (to the left of partition). - // make a note of it in siblingExplored - ordinalStack[localDepth] = tosOrdinal; - siblingExplored[localDepth] = -1; - } - continue; - } // endof we did not check the position of a valid ordinal wrt partition - - // now tosOrdinal is a valid ordinal, inside partition or to the left of it, we need - // to push its kids on top of it, if not too deep. - // Make a note that we did not check them yet - if (localDepth >= depth) { - // localDepth == depth; current tos exhausted its possible children, mark this by pushing INVALID_ORDINAL - ordinalStack[++localDepth] = TaxonomyReader.INVALID_ORDINAL; - continue; - } - ordinalStack[++localDepth] = children[tosOrdinal]; - siblingExplored[localDepth] = Integer.MAX_VALUE; - } // endof loop while stack is not empty - - // now generate a TempFacetResult from AACOsOfOnePartition, and consider self. - IntermediateFacetResultWithHash tempFRWH = new IntermediateFacetResultWithHash( - facetRequest, AACOsOfOnePartition); - if (isSelfPartition(rootNode, facetArrays, offset)) { - tempFRWH.isRootNodeIncluded = true; - tempFRWH.rootNodeValue = resolver.valueOf(rootNode % partitionSize); - } - tempFRWH.totalNumOfFacetsConsidered = totalNumOfDescendantsConsidered; - return tempFRWH; - - } - - /** - * Recursively count ordinal, whose depth is currentDepth, - * and all its descendants down to maxDepth (including), - * descendants whose value in the count arrays, arrays, is != 0. - * The count arrays only includes the current partition, from offset, to (exclusive) - * endOffset. - * It is assumed that ordinal < endOffset, - * otherwise, not ordinal, and none of its descendants, reside in - * the current partition. ordinal < offset is allowed, - * as ordinal's descendants might be >= offeset. - * - * @param ordinal a facet ordinal. - * @param youngestChild mapping a given ordinal to its youngest child in the taxonomy (of largest ordinal number), - * or to -1 if has no children. - * @param olderSibling mapping a given ordinal to its older sibling, or to -1 - * @param partitionSize number of ordinals in the given partition - * @param offset the first (smallest) ordinal in the given partition - * @param endOffset one larger than the largest ordinal that belong to this partition - * @param currentDepth the depth or ordinal in the TaxonomyTree (relative to rootnode of the facetRequest) - * @param maxDepth maximal depth of descendants to be considered here (measured relative to rootnode of the - * facetRequest). - * @return the number of nodes, from ordinal down its descendants, of depth <= maxDepth, - * which reside in the current partition, and whose value != 0 - */ - private int countOnly(int ordinal, int[] youngestChild, int[] olderSibling, int partitionSize, int offset, - int endOffset, int currentDepth, int maxDepth) { - int ret = 0; - if (offset <= ordinal) { - // ordinal belongs to the current partition - if (0 != resolver.valueOf(ordinal % partitionSize)) { - ret++; - } - } - // now consider children of ordinal, if not too deep - if (currentDepth >= maxDepth) { - return ret; - } - - int yc = youngestChild[ordinal]; - while (yc >= endOffset) { - yc = olderSibling[yc]; - } - while (yc > TaxonomyReader.INVALID_ORDINAL) { // assuming this is -1, smaller than any legal ordinal - ret += countOnly (yc, youngestChild, olderSibling, partitionSize, - offset, endOffset, currentDepth+1, maxDepth); - yc = olderSibling[yc]; - } - return ret; - } - - /** - * Merge several partitions' {@link IntermediateFacetResult}-s into one of the - * same format - * - * @see #mergeResults(IntermediateFacetResult...) - */ - @Override - public IntermediateFacetResult mergeResults(IntermediateFacetResult... tmpResults) { - - if (tmpResults.length == 0) { - return null; - } - - int i=0; - // skip over null tmpResults - for (; (i < tmpResults.length)&&(tmpResults[i] == null); i++) {} - if (i == tmpResults.length) { - // all inputs are null - return null; - } - - // i points to the first non-null input - int K = this.facetRequest.numResults; // number of best result in each node - IntermediateFacetResultWithHash tmpToReturn = (IntermediateFacetResultWithHash)tmpResults[i++]; - - // now loop over the rest of tmpResults and merge each into tmpToReturn - for ( ; i < tmpResults.length; i++) { - IntermediateFacetResultWithHash tfr = (IntermediateFacetResultWithHash)tmpResults[i]; - tmpToReturn.totalNumOfFacetsConsidered += tfr.totalNumOfFacetsConsidered; - if (tfr.isRootNodeIncluded) { - tmpToReturn.isRootNodeIncluded = true; - tmpToReturn.rootNodeValue = tfr.rootNodeValue; - } - // now merge the HashMap of tfr into this of tmpToReturn - IntToObjectMap tmpToReturnMapToACCOs = tmpToReturn.mapToAACOs; - IntToObjectMap tfrMapToACCOs = tfr.mapToAACOs; - IntIterator tfrIntIterator = tfrMapToACCOs.keyIterator(); - //iterate over all ordinals in tfr that are maps to their children - while (tfrIntIterator.hasNext()) { - int tfrkey = tfrIntIterator.next(); - AACO tmpToReturnAACO = null; - if (null == (tmpToReturnAACO = tmpToReturnMapToACCOs.get(tfrkey))) { - // if tmpToReturn does not have any kids of tfrkey, map all the kids - // from tfr to it as one package, along with their redisude - tmpToReturnMapToACCOs.put(tfrkey, tfrMapToACCOs.get(tfrkey)); - } else { - // merge the best K children of tfrkey as appear in tmpToReturn and in tfr - AACO tfrAACO = tfrMapToACCOs.get(tfrkey); - int resLength = tfrAACO.ordinals.length + tmpToReturnAACO.ordinals.length; - if (K < resLength) { - resLength = K; - } - int[] resOrds = new int [resLength]; - double[] resVals = new double [resLength]; - int indexIntoTmpToReturn = 0; - int indexIntoTFR = 0; - ACComparator merger = getSuitableACComparator(); // by facet Request - for (int indexIntoRes = 0; indexIntoRes < resLength; indexIntoRes++) { - if (indexIntoTmpToReturn >= tmpToReturnAACO.ordinals.length) { - //tmpToReturnAACO (former result to return) ran out of indices - // it is all merged into resOrds and resVal - resOrds[indexIntoRes] = tfrAACO.ordinals[indexIntoTFR]; - resVals[indexIntoRes] = tfrAACO.values[indexIntoTFR]; - indexIntoTFR++; - continue; - } - if (indexIntoTFR >= tfrAACO.ordinals.length) { - // tfr ran out of indices - resOrds[indexIntoRes] = tmpToReturnAACO.ordinals[indexIntoTmpToReturn]; - resVals[indexIntoRes] = tmpToReturnAACO.values[indexIntoTmpToReturn]; - indexIntoTmpToReturn++; - continue; - } - // select which goes now to res: next (ord, value) from tmpToReturn or from tfr: - if (merger.leftGoesNow( tmpToReturnAACO.ordinals[indexIntoTmpToReturn], - tmpToReturnAACO.values[indexIntoTmpToReturn], - tfrAACO.ordinals[indexIntoTFR], - tfrAACO.values[indexIntoTFR])) { - resOrds[indexIntoRes] = tmpToReturnAACO.ordinals[indexIntoTmpToReturn]; - resVals[indexIntoRes] = tmpToReturnAACO.values[indexIntoTmpToReturn]; - indexIntoTmpToReturn++; - } else { - resOrds[indexIntoRes] = tfrAACO.ordinals[indexIntoTFR]; - resVals[indexIntoRes] = tfrAACO.values[indexIntoTFR]; - indexIntoTFR++; - } - } // end of merge of best kids of tfrkey that appear in tmpToReturn and its kids that appear in tfr - // altogether yielding no more that best K kids for tfrkey, not to appear in the new shape of - // tmpToReturn - - //update the list of best kids of tfrkey as appear in tmpToReturn - tmpToReturnMapToACCOs.put(tfrkey, new AACO(resOrds, resVals)); - } // endof need to merge both AACO -- children for same ordinal - - } // endof loop over all ordinals in tfr - } // endof loop over all temporary facet results to merge - - return tmpToReturn; - } - - private static class AggregatedCategoryHeap extends PriorityQueue { - - private ACComparator merger; - public AggregatedCategoryHeap(int size, ACComparator merger) { - super(size); - this.merger = merger; - } - - @Override - protected boolean lessThan(AggregatedCategory arg1, AggregatedCategory arg2) { - return merger.leftGoesNow(arg2.ordinal, arg2.value, arg1.ordinal, arg1.value); - } - - } - - private static class ResultNodeHeap extends PriorityQueue { - private ACComparator merger; - public ResultNodeHeap(int size, ACComparator merger) { - super(size); - this.merger = merger; - } - - @Override - protected boolean lessThan(FacetResultNode arg1, FacetResultNode arg2) { - return merger.leftGoesNow(arg2.ordinal, arg2.value, arg1.ordinal, arg1.value); - } - - } - - /** - * @return the {@link ACComparator} that reflects the order, - * expressed in the {@link FacetRequest}, of - * facets in the {@link FacetResult}. - */ - - private ACComparator getSuitableACComparator() { - if (facetRequest.getSortOrder() == SortOrder.ASCENDING) { - return new AscValueACComparator(); - } else { - return new DescValueACComparator(); - } - } - - /** - * A comparator of two Aggregated Categories according to the order - * (ascending / descending) and item (ordinal or value) specified in the - * FacetRequest for the FacetResult to be generated - */ - - private static abstract class ACComparator { - ACComparator() { } - protected abstract boolean leftGoesNow (int ord1, double val1, int ord2, double val2); - } - - private static final class AscValueACComparator extends ACComparator { - - AscValueACComparator() { } - - @Override - protected boolean leftGoesNow (int ord1, double val1, int ord2, double val2) { - return (val1 == val2) ? (ord1 < ord2) : (val1 < val2); - } - } - - private static final class DescValueACComparator extends ACComparator { - - DescValueACComparator() { } - - @Override - protected boolean leftGoesNow (int ord1, double val1, int ord2, double val2) { - return (val1 == val2) ? (ord1 > ord2) : (val1 > val2); - } - } - - /** - * Intermediate result to hold counts from one or more partitions processed - * thus far. Its main field, constructor parameter mapToAACOs, is a map - * from ordinals to AACOs. The AACOs mapped to contain ordinals and values - * encountered in the count arrays of the partitions processed thus far. The - * ordinals mapped from are their parents, and they may be not contained in - * the partitions processed thus far. All nodes belong to the taxonomy subtree - * defined at the facet request, constructor parameter facetReq, by its - * root and depth. - */ - public static class IntermediateFacetResultWithHash implements IntermediateFacetResult { - protected IntToObjectMap mapToAACOs; - FacetRequest facetRequest; - boolean isRootNodeIncluded; // among the ordinals in the partitions - // processed thus far - double rootNodeValue; // the value of it, in case encountered. - int totalNumOfFacetsConsidered; // total number of facets - // which belong to facetRequest subtree and have value != 0, - // and have been encountered thus far in the partitions processed. - // root node of result tree is not included in this count. - - public IntermediateFacetResultWithHash(FacetRequest facetReq, - IntToObjectMap mapToAACOs) { - this.mapToAACOs = mapToAACOs; - this.facetRequest = facetReq; - this.isRootNodeIncluded = false; - this.rootNodeValue = 0.0; - this.totalNumOfFacetsConsidered = 0; - } - - @Override - public FacetRequest getFacetRequest() { - return this.facetRequest; - } - } // endof FacetResultWithHash - - /** - * Maintains info of one entry in the filled up count array: - * an ordinal number of a category and the value aggregated for it - * (typically, that value is the count for that ordinal). - */ - private static final class AggregatedCategory { - int ordinal; - double value; - AggregatedCategory(int ord, double val) { - this.ordinal = ord; - this.value = val; - } - } - - /** - * Maintains an array of AggregatedCategory. For space consideration, this is implemented as - * a pair of arrays, ordinals and values, rather than one array of pairs. - * Enumerated in ordinals are siblings, - * potential nodes of the {@link FacetResult} tree - * (i.e., the descendants of the root node, no deeper than the specified depth). - * No more than K ( = {@link FacetRequest#numResults}) - * siblings are enumerated. - * @lucene.internal - */ - protected static final class AACO { - int [] ordinals; // ordinals of the best K children, sorted from best to least - double [] values; // the respective values for these children - AACO (int[] ords, double[] vals) { - this.ordinals = ords; - this.values = vals; - } - } - - @Override - public void labelResult(FacetResult facetResult) throws IOException { - if (facetResult == null) { - return; // any result to label? - } - FacetResultNode rootNode = facetResult.getFacetResultNode(); - recursivelyLabel(rootNode, facetRequest.getNumLabel()); - } - - private void recursivelyLabel(FacetResultNode node, int numToLabel) throws IOException { - if (node == null) { - return; - } - node.label = taxonomyReader.getPath(node.ordinal); - - // recursively label the first numToLabel children of every node - int numLabeled = 0; - for (FacetResultNode frn : node.subResults) { - recursivelyLabel(frn, numToLabel); - if (++numLabeled >= numToLabel) { - return; - } - } - } - - @Override - // verifies that the children of each node are sorted by the order - // specified by the facetRequest. - // the values in these nodes may have changed due to a re-count, for example - // following the accumulation by Sampling. - // so now we test and re-order if necessary. - public FacetResult rearrangeFacetResult(FacetResult facetResult) { - PriorityQueue nodesHeap = - new ResultNodeHeap(this.facetRequest.numResults, this.getSuitableACComparator()); - FacetResultNode topFrn = facetResult.getFacetResultNode(); - rearrangeChilrenOfNode(topFrn, nodesHeap); - return facetResult; - } - - private void rearrangeChilrenOfNode(FacetResultNode node, PriorityQueue nodesHeap) { - nodesHeap.clear(); // just to be safe - for (FacetResultNode frn : node.subResults) { - nodesHeap.add(frn); - } - int size = nodesHeap.size(); - ArrayList subResults = new ArrayList(size); - while (nodesHeap.size() > 0) { - subResults.add(0, nodesHeap.pop()); - } - node.subResults = subResults; - for (FacetResultNode frn : node.subResults) { - rearrangeChilrenOfNode(frn, nodesHeap); - } - - } - - @Override - public FacetResult renderFacetResult(IntermediateFacetResult tmpResult) throws IOException { - IntermediateFacetResultWithHash tmp = (IntermediateFacetResultWithHash) tmpResult; - int ordinal = this.taxonomyReader.getOrdinal(this.facetRequest.categoryPath); - if ((tmp == null) || (ordinal == TaxonomyReader.INVALID_ORDINAL)) { - return null; - } - double value = Double.NaN; - if (tmp.isRootNodeIncluded) { - value = tmp.rootNodeValue; - } - FacetResultNode root = generateNode(ordinal, value, tmp.mapToAACOs); - return new FacetResult(tmp.facetRequest, root, tmp.totalNumOfFacetsConsidered); - } - - private FacetResultNode generateNode(int ordinal, double val, IntToObjectMap mapToAACOs) { - FacetResultNode node = new FacetResultNode(ordinal, val); - AACO aaco = mapToAACOs.get(ordinal); - if (null == aaco) { - return node; - } - List list = new ArrayList(); - for (int i = 0; i < aaco.ordinals.length; i++) { - list.add(generateNode(aaco.ordinals[i], aaco.values[i], mapToAACOs)); - } - node.subResults = list; - return node; - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/package.html b/lucene/facet/src/java/org/apache/lucene/facet/search/package.html deleted file mode 100644 index 94b2b36abcf..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Facets search code - - -Facets search code. - - \ No newline at end of file diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/DoubleRange.java similarity index 98% rename from lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java rename to lucene/facet/src/java/org/apache/lucene/facet/simple/DoubleRange.java index 65ede2cec40..5fbea850032 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/DoubleRange.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.range; +package org.apache.lucene.facet.simple; /* * Licensed to the Apache Software Foundation (ASF) under one or more diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/FacetField.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/FacetField.java index 211a9336296..f41a79dac12 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/FacetField.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/FacetField.java @@ -30,8 +30,8 @@ public class FacetField extends Field { TYPE.setIndexed(true); TYPE.freeze(); } - final String dim; - final String[] path; + public final String dim; + public final String[] path; public FacetField(String dim, String... path) { super("dummy", TYPE); diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/FloatRange.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/FloatRange.java similarity index 98% rename from lucene/facet/src/java/org/apache/lucene/facet/range/FloatRange.java rename to lucene/facet/src/java/org/apache/lucene/facet/simple/FloatRange.java index 1a40be66dac..4793dc7a06d 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/FloatRange.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/FloatRange.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.range; +package org.apache.lucene.facet.simple; /* * Licensed to the Apache Software Foundation (ASF) under one or more diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/LongRange.java similarity index 97% rename from lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java rename to lucene/facet/src/java/org/apache/lucene/facet/simple/LongRange.java index 3fe5824abf0..eb14dc5ddde 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/LongRange.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.range; +package org.apache.lucene.facet.simple; /* * Licensed to the Apache Software Foundation (ASF) under one or more diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/Range.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/Range.java similarity index 96% rename from lucene/facet/src/java/org/apache/lucene/facet/range/Range.java rename to lucene/facet/src/java/org/apache/lucene/facet/simple/Range.java index 99519f6e45c..c3f5d3b837b 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/Range.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/Range.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.range; +package org.apache.lucene.facet.simple; /* * Licensed to the Apache Software Foundation (ASF) under one or more diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/RangeFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/RangeFacetCounts.java index 65d32321bde..65121bc8cb5 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/RangeFacetCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/RangeFacetCounts.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.Collections; import java.util.List; -import org.apache.lucene.facet.range.Range; import org.apache.lucene.facet.simple.SimpleFacetsCollector.MatchingDocs; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.queries.function.FunctionValues; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/search/SearcherTaxonomyManager.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/SearcherTaxonomyManager.java similarity index 99% rename from lucene/facet/src/java/org/apache/lucene/facet/search/SearcherTaxonomyManager.java rename to lucene/facet/src/java/org/apache/lucene/facet/simple/SearcherTaxonomyManager.java index b91802ca000..6245c114681 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/search/SearcherTaxonomyManager.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/SearcherTaxonomyManager.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.search; +package org.apache.lucene.facet.simple; /* * Licensed to the Apache Software Foundation (ASF) under one or more diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillDownQuery.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillDownQuery.java index 6b4e64b5ca6..8ad3d1768b0 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillDownQuery.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillDownQuery.java @@ -23,7 +23,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.lucene.facet.params.CategoryListParams; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillSideways.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillSideways.java index a7a6755cb86..24b514275d4 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillSideways.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleDrillSideways.java @@ -26,9 +26,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.DrillDownQuery; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleFacetsCollector.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleFacetsCollector.java index 4479b728b5c..b17d6c0f0a2 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleFacetsCollector.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/SimpleFacetsCollector.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.lucene.facet.params.FacetSearchParams; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.index.AtomicReaderContext; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/simple/SortedSetDocValuesReaderState.java b/lucene/facet/src/java/org/apache/lucene/facet/simple/SortedSetDocValuesReaderState.java index 49aa209670e..1ebc04961bc 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/simple/SortedSetDocValuesReaderState.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/simple/SortedSetDocValuesReaderState.java @@ -23,8 +23,6 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.CompositeReader; import org.apache.lucene.index.IndexReader; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/package.html b/lucene/facet/src/java/org/apache/lucene/facet/sortedset/package.html deleted file mode 100644 index 1967a679c54..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Classes to perform faceting without a separate taxonomy index, using on SortedSetDocValuesField - - -Classes to perform faceting without a separate taxonomy index, using on SortedSetDocValuesField. - - diff --git a/lucene/facet/src/java/org/apache/lucene/facet/collections/LRUHashMap.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/LRUHashMap.java similarity index 99% rename from lucene/facet/src/java/org/apache/lucene/facet/collections/LRUHashMap.java rename to lucene/facet/src/java/org/apache/lucene/facet/taxonomy/LRUHashMap.java index 5565319c288..7b052987733 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/collections/LRUHashMap.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/LRUHashMap.java @@ -1,7 +1,4 @@ -package org.apache.lucene.facet.collections; - -import java.util.LinkedHashMap; -import java.util.Map; +package org.apache.lucene.facet.taxonomy; /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,6 +17,9 @@ import java.util.Map; * limitations under the License. */ +import java.util.LinkedHashMap; +import java.util.Map; + /** * LRUHashMap is an extension of Java's HashMap, which has a bounded size(); * When it reaches that size, each time a new element is added, the least diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/PrintTaxonomyStats.java similarity index 96% rename from lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java rename to lucene/facet/src/java/org/apache/lucene/facet/taxonomy/PrintTaxonomyStats.java index 65165d8035b..c04d67b9116 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/PrintTaxonomyStats.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/PrintTaxonomyStats.java @@ -1,4 +1,4 @@ -package org.apache.lucene.facet.util; +package org.apache.lucene.facet.taxonomy; /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,8 +21,6 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyReader.ChildrenIterator; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; import org.apache.lucene.store.Directory; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java index 9601ffdaf71..ea4b897c2e3 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java @@ -5,8 +5,8 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.lucene.facet.collections.LRUHashMap; import org.apache.lucene.facet.taxonomy.FacetLabel; +import org.apache.lucene.facet.taxonomy.LRUHashMap; import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.index.CorruptIndexException; // javadocs diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/FacetsPayloadMigrationReader.java b/lucene/facet/src/java/org/apache/lucene/facet/util/FacetsPayloadMigrationReader.java deleted file mode 100644 index e3d998d5159..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/FacetsPayloadMigrationReader.java +++ /dev/null @@ -1,265 +0,0 @@ -package org.apache.lucene.facet.util; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.DocsAndPositionsEnum; -import org.apache.lucene.index.FieldInfo.DocValuesType; -import org.apache.lucene.index.FieldInfo; -import org.apache.lucene.index.FieldInfos; -import org.apache.lucene.index.Fields; -import org.apache.lucene.index.FilterAtomicReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.Terms; -import org.apache.lucene.index.TermsEnum; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.Bits; -import org.apache.lucene.util.BytesRef; - -/** - * A {@link FilterAtomicReader} for migrating a facets index which encodes - * category ordinals in a payload to {@link BinaryDocValues}. To migrate the index, - * you should build a mapping from a field (String) to term ({@link Term}), - * which denotes under which BinaryDocValues field to put the data encoded in the - * matching term's payload. You can follow the code example below to migrate an - * existing index: - * - *

- * // Add the index and migrate payload to DocValues on the go
- * DirectoryReader reader = DirectoryReader.open(oldDir);
- * IndexWriterConfig conf = new IndexWriterConfig(VER, ANALYZER);
- * IndexWriter writer = new IndexWriter(newDir, conf);
- * List<AtomicReaderContext> leaves = reader.leaves();
- * AtomicReader wrappedLeaves[] = new AtomicReader[leaves.size()];
- * for (int i = 0; i < leaves.size(); i++) {
- *   wrappedLeaves[i] = new FacetPayloadMigrationReader(leaves.get(i).reader(),
- *       fieldTerms);
- * }
- * writer.addIndexes(new MultiReader(wrappedLeaves));
- * writer.commit();
- * 
- * - *

- * NOTE: to build the field-to-term map you can use - * {@link #buildFieldTermsMap(Directory, FacetIndexingParams)}, as long as the - * index to migrate contains the ordinals payload under - * {@link #PAYLOAD_TERM_TEXT}. - * - * @lucene.experimental - */ -public class FacetsPayloadMigrationReader extends FilterAtomicReader { - - private class PayloadMigratingBinaryDocValues extends BinaryDocValues { - - private Fields fields; - private Term term; - private DocsAndPositionsEnum dpe; - private int curDocID = -1; - private int lastRequestedDocID; - - private DocsAndPositionsEnum getDPE() { - try { - DocsAndPositionsEnum dpe = null; - if (fields != null) { - Terms terms = fields.terms(term.field()); - if (terms != null) { - TermsEnum te = terms.iterator(null); // no use for reusing - if (te.seekExact(term.bytes())) { - // we're not expected to be called for deleted documents - dpe = te.docsAndPositions(null, null, DocsAndPositionsEnum.FLAG_PAYLOADS); - } - } - } - return dpe; - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - protected PayloadMigratingBinaryDocValues(Fields fields, Term term) { - this.fields = fields; - this.term = term; - this.dpe = getDPE(); - if (dpe == null) { - curDocID = DocIdSetIterator.NO_MORE_DOCS; - } else { - try { - curDocID = dpe.nextDoc(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - @Override - public void get(int docID, BytesRef result) { - try { - // If caller is moving backwards (eg, during merge, - // the consuming DV format is free to iterate over - // our values as many times as it wants), we must - // re-init the dpe: - if (docID <= lastRequestedDocID) { - dpe = getDPE(); - if (dpe == null) { - curDocID = DocIdSetIterator.NO_MORE_DOCS; - } else{ - curDocID = dpe.nextDoc(); - } - } - lastRequestedDocID = docID; - if (curDocID > docID) { - // document does not exist - result.length = 0; - return; - } - - if (curDocID < docID) { - curDocID = dpe.advance(docID); - if (curDocID != docID) { // requested document does not have a payload - result.length = 0; - return; - } - } - - dpe.nextPosition(); - result.copyBytes(dpe.getPayload()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - /** The {@link Term} text of the ordinals payload. */ - public static final String PAYLOAD_TERM_TEXT = "$fulltree$"; - - /** - * A utility method for building the field-to-Term map, given the - * {@link FacetIndexingParams} and the directory of the index to migrate. The - * map that will be built will correspond to partitions as well as multiple - * {@link CategoryListParams}. - *

- * NOTE: since {@link CategoryListParams} no longer define a - * {@link Term}, this method assumes that the term used by the different - * {@link CategoryListParams} is {@link #PAYLOAD_TERM_TEXT}. If this is not - * the case, then you should build the map yourself, using the terms in your - * index. - */ - public static Map buildFieldTermsMap(Directory dir, FacetIndexingParams fip) throws IOException { - // only add field-Term mapping that will actually have DocValues in the end. - // therefore traverse the index terms and add what exists. this pertains to - // multiple CLPs, as well as partitions - DirectoryReader reader = DirectoryReader.open(dir); - final Map fieldTerms = new HashMap(); - for (AtomicReaderContext context : reader.leaves()) { - for (CategoryListParams clp : fip.getAllCategoryListParams()) { - Terms terms = context.reader().terms(clp.field); - if (terms != null) { - TermsEnum te = terms.iterator(null); - BytesRef termBytes = null; - while ((termBytes = te.next()) != null) { - String term = termBytes.utf8ToString(); - if (term.startsWith(PAYLOAD_TERM_TEXT )) { - if (term.equals(PAYLOAD_TERM_TEXT)) { - fieldTerms.put(clp.field, new Term(clp.field, term)); - } else { - fieldTerms.put(clp.field + term.substring(PAYLOAD_TERM_TEXT.length()), new Term(clp.field, term)); - } - } - } - } - } - } - reader.close(); - return fieldTerms; - } - - private final Map fieldTerms; - - /** - * Wraps an {@link AtomicReader} and migrates the payload to {@link BinaryDocValues} - * fields by using the given mapping. - */ - public FacetsPayloadMigrationReader(AtomicReader in, Map fieldTerms) { - super(in); - this.fieldTerms = fieldTerms; - } - - @Override - public BinaryDocValues getBinaryDocValues(String field) throws IOException { - Term term = fieldTerms.get(field); - if (term == null) { - return super.getBinaryDocValues(field); - } else { - // we shouldn't return null, even if the term does not exist or has no - // payloads, since we already marked the field as having DocValues. - return new PayloadMigratingBinaryDocValues(fields(), term); - } - } - - @Override - public Bits getDocsWithField(String field) throws IOException { - Term term = fieldTerms.get(field); - if (term == null) { - return super.getDocsWithField(field); - } else { - // we shouldn't return null, even if the term does not exist or has no - // payloads, since we already marked the field as having DocValues. - return new Bits.MatchAllBits(maxDoc()); - } - } - - @Override - public FieldInfos getFieldInfos() { - FieldInfos innerInfos = super.getFieldInfos(); - ArrayList infos = new ArrayList(innerInfos.size()); - // if there are partitions, then the source index contains one field for all their terms - // while with DocValues, we simulate that by multiple fields. - HashSet leftoverFields = new HashSet(fieldTerms.keySet()); - int number = -1; - for (FieldInfo info : innerInfos) { - if (fieldTerms.containsKey(info.name)) { - // mark this field as having a DocValues - infos.add(new FieldInfo(info.name, true, info.number, - info.hasVectors(), info.omitsNorms(), info.hasPayloads(), - info.getIndexOptions(), DocValuesType.BINARY, - info.getNormType(), info.attributes())); - leftoverFields.remove(info.name); - } else { - infos.add(info); - } - number = Math.max(number, info.number); - } - for (String field : leftoverFields) { - infos.add(new FieldInfo(field, false, ++number, false, false, false, - null, DocValuesType.BINARY, null, null)); - } - return new FieldInfos(infos.toArray(new FieldInfo[infos.size()])); - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/OrdinalMappingAtomicReader.java b/lucene/facet/src/java/org/apache/lucene/facet/util/OrdinalMappingAtomicReader.java deleted file mode 100644 index 6b2da7553b9..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/OrdinalMappingAtomicReader.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.apache.lucene.facet.util; - -/* - * 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. - */ - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.OrdinalMap; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.BinaryDocValues; -import org.apache.lucene.index.FilterAtomicReader; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/** - * A {@link FilterAtomicReader} for updating facets ordinal references, - * based on an ordinal map. You should use this code in conjunction with merging - * taxonomies - after you merge taxonomies, you receive an {@link OrdinalMap} - * which maps the 'old' ordinals to the 'new' ones. You can use that map to - * re-map the doc values which contain the facets information (ordinals) either - * before or while merging the indexes. - *

- * For re-mapping the ordinals during index merge, do the following: - * - *

- * // merge the old taxonomy with the new one.
- * OrdinalMap map = new MemoryOrdinalMap();
- * DirectoryTaxonomyWriter.addTaxonomy(srcTaxoDir, map);
- * int[] ordmap = map.getMap();
- * 
- * // Add the index and re-map ordinals on the go
- * DirectoryReader reader = DirectoryReader.open(oldDir);
- * IndexWriterConfig conf = new IndexWriterConfig(VER, ANALYZER);
- * IndexWriter writer = new IndexWriter(newDir, conf);
- * 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(), ordmap);
- *   }
- * writer.addIndexes(new MultiReader(wrappedLeaves));
- * writer.commit();
- * 
- * - * @lucene.experimental - */ -public class OrdinalMappingAtomicReader extends FilterAtomicReader { - - private final int[] ordinalMap; - - private final Map dvFieldMap = new HashMap(); - - /** - * Wraps an AtomicReader, mapping ordinals according to the ordinalMap. - * Calls {@link #OrdinalMappingAtomicReader(AtomicReader, int[], FacetIndexingParams) - * OrdinalMappingAtomicReader(in, ordinalMap, new DefaultFacetIndexingParams())} - */ - public OrdinalMappingAtomicReader(AtomicReader in, int[] ordinalMap) { - this(in, ordinalMap, FacetIndexingParams.DEFAULT); - } - - /** - * Wraps an AtomicReader, mapping ordinals according to the ordinalMap, - * using the provided indexingParams. - */ - public OrdinalMappingAtomicReader(AtomicReader in, int[] ordinalMap, FacetIndexingParams indexingParams) { - super(in); - this.ordinalMap = ordinalMap; - for (CategoryListParams params: indexingParams.getAllCategoryListParams()) { - dvFieldMap.put(params.field, params); - } - } - - @Override - public BinaryDocValues getBinaryDocValues(String field) throws IOException { - BinaryDocValues inner = super.getBinaryDocValues(field); - if (inner == null) { - return inner; - } - - CategoryListParams clp = dvFieldMap.get(field); - if (clp == null) { - return inner; - } else { - return new OrdinalMappingBinaryDocValues(clp, inner); - } - } - - private class OrdinalMappingBinaryDocValues extends BinaryDocValues { - - private final IntEncoder encoder; - private final IntDecoder decoder; - private final IntsRef ordinals = new IntsRef(32); - private final BinaryDocValues delegate; - private final BytesRef scratch = new BytesRef(); - - protected OrdinalMappingBinaryDocValues(CategoryListParams clp, BinaryDocValues delegate) { - this.delegate = delegate; - encoder = clp.createEncoder(); - decoder = encoder.createMatchingDecoder(); - } - - @SuppressWarnings("synthetic-access") - @Override - public void get(int docID, BytesRef result) { - // NOTE: this isn't quite koscher, because in general - // multiple threads can call BinaryDV.get which would - // then conflict on the single scratch instance, but - // because this impl is only used for merging, we know - // only 1 thread calls us: - delegate.get(docID, scratch); - if (scratch.length > 0) { - // We must use scratch (and not re-use result) here, - // else encoder may overwrite the DV provider's - // private byte[]: - decoder.decode(scratch, ordinals); - - // map the ordinals - for (int i = 0; i < ordinals.length; i++) { - ordinals.ints[i] = ordinalMap[ordinals.ints[i]]; - } - - encoder.encode(ordinals, result); - } - } - } -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/PartitionsUtils.java b/lucene/facet/src/java/org/apache/lucene/facet/util/PartitionsUtils.java deleted file mode 100644 index 99f66dfff22..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/PartitionsUtils.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apache.lucene.facet.util; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; - -/* - * 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. - */ - -/** - * Utilities for partitions - sizes and such - * - * @lucene.experimental - */ -public final class PartitionsUtils { - - /** The prefix that is added to the name of the partition. */ - public static final String PART_NAME_PREFIX = "$part"; - - /** - * Get the partition size in this parameter, or return the size of the taxonomy, which - * is smaller. (Guarantees usage of as little memory as possible at search time). - */ - public final static int partitionSize(FacetIndexingParams indexingParams, final TaxonomyReader taxonomyReader) { - return Math.min(indexingParams.getPartitionSize(), taxonomyReader.getSize()); - } - - /** - * Partition number of an ordinal. - *

- * This allows to locate the partition containing a certain (facet) ordinal. - * @see FacetIndexingParams#getPartitionSize() - */ - public final static int partitionNumber(FacetIndexingParams iParams, int ordinal) { - return ordinal / iParams.getPartitionSize(); - } - - /** - * Partition name by category ordinal - */ - public final static String partitionNameByOrdinal(FacetIndexingParams iParams, int ordinal) { - int partition = partitionNumber(iParams, ordinal); - return partitionName(partition); - } - - /** Partition name by its number */ - public final static String partitionName(int partition) { - // TODO would be good if this method isn't called when partitions are not enabled. - // perhaps through some specialization code. - if (partition == 0) { - // since regular faceted search code goes through this method too, - // return the same value for partition 0 and when there are no partitions - return ""; - } - return PART_NAME_PREFIX + Integer.toString(partition); - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/ResultSortUtils.java b/lucene/facet/src/java/org/apache/lucene/facet/util/ResultSortUtils.java deleted file mode 100644 index 1b11244cc53..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/ResultSortUtils.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.apache.lucene.facet.util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -import org.apache.lucene.util.PriorityQueue; - -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.Heap; -import org.apache.lucene.facet.search.FacetRequest.SortOrder; - -/* - * 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. - */ - -/** - * Utilities for generating facet results sorted as required - * - * @lucene.experimental - */ -public class ResultSortUtils { - - /** - * Create a suitable heap according to facet request being served. - * @return heap for maintaining results for specified request. - * @throws IllegalArgumentException is provided facet request is not supported - */ - public static Heap createSuitableHeap(FacetRequest facetRequest) { - int nresults = facetRequest.numResults; - boolean accending = (facetRequest.getSortOrder() == SortOrder.ASCENDING); - - if (nresults == Integer.MAX_VALUE) { - return new AllValueHeap(accending); - } - - if (accending) { - return new MaxValueHeap(nresults); - } else { - return new MinValueHeap(nresults); - } - } - - private static class MinValueHeap extends PriorityQueue implements Heap { - public MinValueHeap(int size) { - super(size); - } - - @Override - protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) { - double value0 = arg0.value; - double value1 = arg1.value; - - int valueCompare = Double.compare(value0, value1); - if (valueCompare == 0) { - return arg0.ordinal < arg1.ordinal; - } - - return valueCompare < 0; - } - - } - - private static class MaxValueHeap extends PriorityQueue implements Heap { - public MaxValueHeap(int size) { - super(size); - } - - @Override - protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) { - double value0 = arg0.value; - double value1 = arg1.value; - - int valueCompare = Double.compare(value0, value1); - if (valueCompare == 0) { - return arg0.ordinal > arg1.ordinal; - } - - return valueCompare > 0; - } - } - - /** - * Create a Heap-Look-Alike, which implements {@link Heap}, but uses a - * regular ArrayList for holding ALL the objects given, - * only sorting upon the first call to {@link #pop()}. - */ - private static class AllValueHeap implements Heap { - private ArrayList resultNodes = new ArrayList(); - final boolean accending; - private boolean isReady = false; - public AllValueHeap(boolean accending) { - this.accending = accending; - } - - @Override - public FacetResultNode insertWithOverflow(FacetResultNode node) { - resultNodes.add(node); - return null; - } - - @Override - public FacetResultNode pop() { - if (!isReady) { - Collections.sort(resultNodes, new Comparator() { - @Override - public int compare(FacetResultNode o1, FacetResultNode o2) { - int value = Double.compare(o1.value, o2.value); - if (value == 0) { - value = o1.ordinal - o2.ordinal; - } - if (accending) { - value = -value; - } - return value; - } - }); - isReady = true; - } - - return resultNodes.remove(0); - } - - @Override - public int size() { - return resultNodes.size(); - } - - @Override - public FacetResultNode top() { - if (resultNodes.size() > 0) { - return resultNodes.get(0); - } - - return null; - } - - @Override - public FacetResultNode add(FacetResultNode frn) { - resultNodes.add(frn); - return null; - } - - @Override - public void clear() { - resultNodes.clear(); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java b/lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java deleted file mode 100644 index 276317196dc..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.apache.lucene.facet.util; - -import java.io.IOException; -import java.util.List; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.OrdinalMap; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.store.Directory; - -/* - * 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. - */ - -/** - * Utility methods for merging index and taxonomy directories. - * @lucene.experimental - */ -public class TaxonomyMergeUtils { - - /** - * 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, FacetIndexingParams params) throws IOException { - // merge the taxonomies - destTaxWriter.addTaxonomy(srcTaxDir, map); - int ordinalMap[] = map.getMap(); - DirectoryReader reader = DirectoryReader.open(srcIndexDir); - List leaves = reader.leaves(); - int numReaders = leaves.size(); - AtomicReader wrappedLeaves[] = new AtomicReader[numReaders]; - for (int i = 0; i < numReaders; 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(); - } - } - -} diff --git a/lucene/facet/src/java/org/apache/lucene/facet/util/package.html b/lucene/facet/src/java/org/apache/lucene/facet/util/package.html deleted file mode 100644 index 900a5a603cb..00000000000 --- a/lucene/facet/src/java/org/apache/lucene/facet/util/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Various utilities for faceted search - - -

Various utilities for faceted search

- - \ No newline at end of file diff --git a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java b/lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java deleted file mode 100644 index 9a49b79d349..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java +++ /dev/null @@ -1,362 +0,0 @@ -package org.apache.lucene.facet; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.analysis.MockTokenizer; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.collections.IntToObjectMap; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.index.MultiFields; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.Terms; -import org.apache.lucene.index.TermsEnum; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.Bits; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util.LuceneTestCase.SuppressCodecs; -import org.apache.lucene.util._TestUtil; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -/* - * 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. - */ - -@SuppressCodecs({"SimpleText"}) -public abstract class FacetTestBase extends FacetTestCase { - - /** Holds a search and taxonomy Directories pair. */ - private static final class SearchTaxoDirPair { - Directory searchDir, taxoDir; - SearchTaxoDirPair() {} - } - - private static IntToObjectMap dirsPerPartitionSize; - private static IntToObjectMap fipPerPartitionSize; - private static File TEST_DIR; - - /** Documents text field. */ - protected static final String CONTENT_FIELD = "content"; - - /** taxonomy Reader for the test. */ - protected TaxonomyReader taxoReader; - - /** Index Reader for the test. */ - protected IndexReader indexReader; - - /** Searcher for the test. */ - protected IndexSearcher searcher; - - @BeforeClass - public static void beforeClassFacetTestBase() { - TEST_DIR = _TestUtil.getTempDir("facets"); - dirsPerPartitionSize = new IntToObjectMap(); - fipPerPartitionSize = new IntToObjectMap(); - } - - @AfterClass - public static void afterClassFacetTestBase() throws Exception { - Iterator iter = dirsPerPartitionSize.iterator(); - while (iter.hasNext()) { - SearchTaxoDirPair pair = iter.next(); - IOUtils.close(pair.searchDir, pair.taxoDir); - } - } - - /** documents text (for the text field). */ - private static final String[] DEFAULT_CONTENT = { - "the white car is the one I want.", - "the white dog does not belong to anyone.", - }; - - /** Facets: facets[D][F] == category-path no. F for document no. D. */ - private static final FacetLabel[][] DEFAULT_CATEGORIES = { - { new FacetLabel("root","a","f1"), new FacetLabel("root","a","f2") }, - { new FacetLabel("root","a","f1"), new FacetLabel("root","a","f3") }, - }; - - /** categories to be added to specified doc */ - protected List getCategories(int doc) { - return Arrays.asList(DEFAULT_CATEGORIES[doc]); - } - - /** Number of documents to index */ - protected int numDocsToIndex() { - return DEFAULT_CONTENT.length; - } - - /** content to be added to specified doc */ - protected String getContent(int doc) { - return DEFAULT_CONTENT[doc]; - } - - /** Prepare index (in RAM) with some documents and some facets. */ - protected final void initIndex(FacetIndexingParams fip) throws Exception { - initIndex(false, fip); - } - - /** Prepare index (in RAM/Disk) with some documents and some facets. */ - protected final void initIndex(boolean forceDisk, FacetIndexingParams fip) throws Exception { - int partitionSize = fip.getPartitionSize(); - if (VERBOSE) { - System.out.println("Partition Size: " + partitionSize + " forceDisk: "+forceDisk); - } - - SearchTaxoDirPair pair = dirsPerPartitionSize.get(Integer.valueOf(partitionSize)); - if (pair == null) { - pair = new SearchTaxoDirPair(); - if (forceDisk) { - pair.searchDir = newFSDirectory(new File(TEST_DIR, "index")); - pair.taxoDir = newFSDirectory(new File(TEST_DIR, "taxo")); - } else { - pair.searchDir = newDirectory(); - pair.taxoDir = newDirectory(); - } - - RandomIndexWriter iw = new RandomIndexWriter(random(), pair.searchDir, getIndexWriterConfig(getAnalyzer())); - TaxonomyWriter taxo = new DirectoryTaxonomyWriter(pair.taxoDir, OpenMode.CREATE); - - populateIndex(iw, taxo, fip); - - // commit changes (taxonomy prior to search index for consistency) - taxo.commit(); - iw.commit(); - taxo.close(); - iw.close(); - - dirsPerPartitionSize.put(Integer.valueOf(partitionSize), pair); - } - - // prepare for searching - taxoReader = new DirectoryTaxonomyReader(pair.taxoDir); - indexReader = DirectoryReader.open(pair.searchDir); - searcher = newSearcher(indexReader); - } - - /** Returns indexing params for the main index */ - protected IndexWriterConfig getIndexWriterConfig(Analyzer analyzer) { - return newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer); - } - - /** Returns a {@link FacetIndexingParams} per the given partition size. */ - protected FacetIndexingParams getFacetIndexingParams(final int partSize) { - return getFacetIndexingParams(partSize, false); - } - - /** - * Returns a {@link FacetIndexingParams} per the given partition size. If - * requested, then {@link OrdinalPolicy} will be set to - * {@link OrdinalPolicy#ALL_PARENTS}, otherwise it will randomize. - */ - protected FacetIndexingParams getFacetIndexingParams(final int partSize, final boolean forceAllParents) { - FacetIndexingParams fip = fipPerPartitionSize.get(partSize); - if (fip == null) { - // randomize OrdinalPolicy. Since not all Collectors / Accumulators - // support NO_PARENTS, don't include it. - // TODO: once all code paths support NO_PARENTS, randomize it too. - CategoryListParams randomOP = new CategoryListParams() { - final OrdinalPolicy op = random().nextBoolean() ? OrdinalPolicy.ALL_BUT_DIMENSION : OrdinalPolicy.ALL_PARENTS; - @Override - public OrdinalPolicy getOrdinalPolicy(String dimension) { - return forceAllParents ? OrdinalPolicy.ALL_PARENTS : op; - } - }; - - // several of our encoders don't support the value 0, - // which is one of the values encoded when dealing w/ partitions, - // therefore don't randomize the encoder. - fip = new FacetIndexingParams(randomOP) { - @Override - public int getPartitionSize() { - return partSize; - } - }; - fipPerPartitionSize.put(partSize, fip); - } - return fip; - } - - /** - * Faceted Search Params for the test. Sub classes should override in order to - * test with different faceted search params. - */ - protected FacetSearchParams getFacetSearchParams(FacetIndexingParams iParams, FacetRequest... facetRequests) { - return new FacetSearchParams(iParams, facetRequests); - } - - /** - * Faceted Search Params for the test. Sub classes should override in order to - * test with different faceted search params. - */ - protected FacetSearchParams getFacetSearchParams(List facetRequests, FacetIndexingParams iParams) { - return new FacetSearchParams(iParams, facetRequests); - } - - /** - * Populate the test index+taxonomy for this test. - *

Subclasses can override this to test different scenarios - */ - protected void populateIndex(RandomIndexWriter iw, TaxonomyWriter taxo, FacetIndexingParams iParams) - throws IOException { - // add test documents - int numDocsToIndex = numDocsToIndex(); - for (int doc=0; doc a = new ArrayList(); - for (FacetResultNode frn : parentRes.subResults) { - a.add(frn); - } - return a.toArray(new FacetResultNode[0]); - } - - /** utility Create a dummy document with specified categories and content */ - protected final void indexDoc(FacetIndexingParams iParams, RandomIndexWriter iw, - TaxonomyWriter tw, String content, List categories) throws IOException { - Document d = new Document(); - FacetFields facetFields = new FacetFields(tw, iParams); - facetFields.addFields(d, categories); - d.add(new TextField("content", content, Field.Store.YES)); - iw.addDocument(d); - } - - /** Build the "truth" with ALL the facets enumerating indexes content. */ - protected Map facetCountsTruth() throws IOException { - FacetIndexingParams iParams = getFacetIndexingParams(Integer.MAX_VALUE); - String delim = String.valueOf(iParams.getFacetDelimChar()); - Map res = new HashMap(); - HashSet handledTerms = new HashSet(); - for (CategoryListParams clp : iParams.getAllCategoryListParams()) { - if (!handledTerms.add(clp.field)) { - continue; // already handled this term (for another list) - } - Terms terms = MultiFields.getTerms(indexReader, clp.field); - if (terms == null) { - continue; - } - Bits liveDocs = MultiFields.getLiveDocs(indexReader); - TermsEnum te = terms.iterator(null); - DocsEnum de = null; - while (te.next() != null) { - de = _TestUtil.docs(random(), te, liveDocs, de, DocsEnum.FLAG_NONE); - int cnt = 0; - while (de.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { - cnt++; - } - res.put(new FacetLabel(te.term().utf8ToString().split(delim)), cnt); - } - } - return res; - } - - /** Validate counts for returned facets, and that there are not too many results */ - protected static void assertCountsAndCardinality(Map facetCountsTruth, List facetResults) throws Exception { - for (FacetResult fr : facetResults) { - FacetResultNode topResNode = fr.getFacetResultNode(); - FacetRequest freq = fr.getFacetRequest(); - if (VERBOSE) { - System.out.println(freq.categoryPath.toString()+ "\t\t" + topResNode); - } - assertCountsAndCardinality(facetCountsTruth, topResNode, freq.numResults); - } - } - - /** Validate counts for returned facets, and that there are not too many results */ - private static void assertCountsAndCardinality(Map facetCountsTruth, FacetResultNode resNode, int reqNumResults) throws Exception { - int actualNumResults = resNode.subResults.size(); - if (VERBOSE) { - System.out.println("NumResults: " + actualNumResults); - } - assertTrue("Too many results!", actualNumResults <= reqNumResults); - for (FacetResultNode subRes : resNode.subResults) { - assertEquals("wrong count for: "+subRes, facetCountsTruth.get(subRes.label).intValue(), (int)subRes.value); - assertCountsAndCardinality(facetCountsTruth, subRes, reqNumResults); // recurse into child results - } - } - - /** Validate results equality */ - protected static void assertSameResults(List expected, List actual) { - assertEquals("wrong number of facet results", expected.size(), actual.size()); - int size = expected.size(); - for (int i = 0; i < size; i++) { - FacetResult expectedResult = expected.get(i); - FacetResult actualResult = actual.get(i); - String expectedStr = FacetTestUtils.toSimpleString(expectedResult); - String actualStr = FacetTestUtils.toSimpleString(actualResult); - assertEquals("Results not the same!\nExpected:" + expectedStr + "\nActual:\n" + actualStr, expectedStr, actualStr); - } - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestCase.java b/lucene/facet/src/test/org/apache/lucene/facet/FacetTestCase.java index 18b2d477fe4..0a30991f4a3 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestCase.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/FacetTestCase.java @@ -1,29 +1,5 @@ package org.apache.lucene.facet; -import java.io.IOException; -import java.util.Random; - -import org.apache.lucene.facet.encoding.DGapIntEncoder; -import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder; -import org.apache.lucene.facet.encoding.EightFlagsIntEncoder; -import org.apache.lucene.facet.encoding.FourFlagsIntEncoder; -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.encoding.NOnesIntEncoder; -import org.apache.lucene.facet.encoding.SortingIntEncoder; -import org.apache.lucene.facet.encoding.UniqueValuesIntEncoder; -import org.apache.lucene.facet.encoding.VInt8IntEncoder; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.simple.CachedOrdinalsReader; -import org.apache.lucene.facet.simple.DocValuesOrdinalsReader; -import org.apache.lucene.facet.simple.Facets; -import org.apache.lucene.facet.simple.FacetsConfig; -import org.apache.lucene.facet.simple.FastTaxonomyFacetCounts; -import org.apache.lucene.facet.simple.OrdinalsReader; -import org.apache.lucene.facet.simple.SimpleFacetsCollector; -import org.apache.lucene.facet.simple.TaxonomyFacetCounts; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.util.LuceneTestCase; - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -41,36 +17,22 @@ import org.apache.lucene.util.LuceneTestCase; * limitations under the License. */ +import java.io.IOException; +import java.util.Random; + +import org.apache.lucene.facet.simple.CachedOrdinalsReader; +import org.apache.lucene.facet.simple.DocValuesOrdinalsReader; +import org.apache.lucene.facet.simple.Facets; +import org.apache.lucene.facet.simple.FacetsConfig; +import org.apache.lucene.facet.simple.FastTaxonomyFacetCounts; +import org.apache.lucene.facet.simple.OrdinalsReader; +import org.apache.lucene.facet.simple.SimpleFacetsCollector; +import org.apache.lucene.facet.simple.TaxonomyFacetCounts; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.util.LuceneTestCase; + public abstract class FacetTestCase extends LuceneTestCase { - private static final IntEncoder[] ENCODERS = new IntEncoder[] { - new SortingIntEncoder(new UniqueValuesIntEncoder(new VInt8IntEncoder())), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new VInt8IntEncoder()))), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapVInt8IntEncoder())), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new EightFlagsIntEncoder()))), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new FourFlagsIntEncoder()))), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(3)))), - new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(4)))), - }; - - /** Returns a {@link CategoryListParams} with random {@link IntEncoder} and field. */ - public static CategoryListParams randomCategoryListParams() { - final String field = CategoryListParams.DEFAULT_FIELD + "$" + random().nextInt(); - return randomCategoryListParams(field); - } - - /** Returns a {@link CategoryListParams} with random {@link IntEncoder}. */ - public static CategoryListParams randomCategoryListParams(String field) { - Random random = random(); - final IntEncoder encoder = ENCODERS[random.nextInt(ENCODERS.length)]; - return new CategoryListParams(field) { - @Override - public IntEncoder createEncoder() { - return encoder; - } - }; - } - public Facets getTaxonomyFacetCounts(TaxonomyReader taxoReader, FacetsConfig config, SimpleFacetsCollector c) throws IOException { return getTaxonomyFacetCounts(taxoReader, config, c, FacetsConfig.DEFAULT_INDEX_FIELD_NAME); } diff --git a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java b/lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java deleted file mode 100644 index 0231baa04d2..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apache.lucene.facet; - -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; - -/* - * 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. - */ - -public class FacetTestUtils { - - public static String toSimpleString(FacetResult fr) { - StringBuilder sb = new StringBuilder(); - toSimpleString(fr.getFacetRequest().categoryPath.length, 0, sb, fr.getFacetResultNode(), ""); - return sb.toString(); - } - - private static void toSimpleString(int startLength, int depth, StringBuilder sb, FacetResultNode node, String indent) { - sb.append(indent + node.label.components[startLength+depth-1] + " (" + (int) node.value + ")\n"); - for (FacetResultNode childNode : node.subResults) { - toSimpleString(startLength, depth + 1, sb, childNode, indent + " "); - } - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/ArrayHashMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/ArrayHashMapTest.java deleted file mode 100644 index ade3bc8c74d..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/ArrayHashMapTest.java +++ /dev/null @@ -1,268 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.ArrayHashMap; -import org.junit.Test; - -/* - * 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. - */ - -public class ArrayHashMapTest extends FacetTestCase { - - public static final int RANDOM_TEST_NUM_ITERATIONS = 100; // set to 100,000 for deeper test - - @Test - public void test0() { - ArrayHashMap map = new ArrayHashMap(); - - assertNull(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i).intValue()); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertNull(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i).intValue(), (100 + i)); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i).intValue(), (5 + i)); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i).intValue(), (100 + i)); - } - } - - @Test - public void test1() { - ArrayHashMap map = new ArrayHashMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - - set.clear(); - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - Integer integer = iterator.next(); - if (integer % 2 == 1) { - iterator.remove(); - continue; - } - set.add(integer); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i += 2) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - } - - @Test - public void test2() { - ArrayHashMap map = new ArrayHashMap(); - - assertTrue(map.isEmpty()); - assertNull(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i).intValue()); - } - - for (int i = 0; i < 200; i += 2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i += 2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i).intValue()); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - ArrayHashMap map = new ArrayHashMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i * 64, 100 + i); - } - HashSet keySet = new HashSet(); - for (Iterator iit = map.keyIterator(); iit.hasNext();) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (Iterator iit = map.iterator(); iit.hasNext();) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - Object[] array = map.toArray(); - assertEquals(length, array.length); - for (Object value : array) { - assertTrue(valueSet.contains(value)); - } - - Integer[] array2 = new Integer[80]; - array2 = map.toArray(array2); - for (int value : array2) { - assertTrue(valueSet.contains(value)); - } - Integer[] array3 = new Integer[120]; - array3 = map.toArray(array3); - for (int i = 0; i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - assertNull(array3[length]); - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i * 64)); - } - - for (Iterator iit = map.keyIterator(); iit.hasNext();) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - ArrayHashMap map = new ArrayHashMap(); - int length = RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i * 128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i * 128)); - assertEquals(Integer.valueOf(value), map.remove(i * 128)); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - ArrayHashMap map1 = new ArrayHashMap(100); - ArrayHashMap map2 = new ArrayHashMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, Float.valueOf(1f/i)); - map2.put(i, Float.valueOf(1f/i)); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1f); - map2.put(-1,-1.1f); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1f); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/FloatToObjectMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/FloatToObjectMapTest.java deleted file mode 100644 index c3cb26fb313..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/FloatToObjectMapTest.java +++ /dev/null @@ -1,267 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.FloatIterator; -import org.apache.lucene.facet.collections.FloatToObjectMap; -import org.junit.Test; - -/* - * 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. - */ - -public class FloatToObjectMapTest extends FacetTestCase { - - @Test - public void test0() { - FloatToObjectMap map = new FloatToObjectMap(); - - assertNull(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i * 1.1f, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i * 1.1f)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i*1.1f)); - assertEquals(100 + i, map.get(i*1.1f).intValue()); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i*1.1f); - assertNull(map.get(i*1.1f)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i*1.1f), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i*1.1f, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i*1.1f), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i*1.1f).intValue(), (100 + i)); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i*1.1f).intValue(), (5 + i)); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i*1.1f).intValue(), (100 + i)); - } - } - - @Test - public void test1() { - FloatToObjectMap map = new FloatToObjectMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i*1.1f, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - - set.clear(); - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - Integer integer = iterator.next(); - if (integer % 2 == 1) { - iterator.remove(); - continue; - } - set.add(integer); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i += 2) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - } - - @Test - public void test2() { - FloatToObjectMap map = new FloatToObjectMap(); - - assertTrue(map.isEmpty()); - assertNull(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i*1.1f, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i*1.1f)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i*1.1f)); - assertEquals(i * 4096, map.get(i*1.1f).intValue()); - } - - for (int i = 0; i < 200; i += 2) { - map.remove(i*1.1f); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i += 2) { - assertTrue(map.containsKey(i*1.1f)); - assertEquals(i * 4096, map.get(i*1.1f).intValue()); - map.remove(i*1.1f); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - FloatToObjectMap map = new FloatToObjectMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i * 64*1.1f, 100 + i); - } - HashSet keySet = new HashSet(); - for (FloatIterator iit = map.keyIterator(); iit.hasNext();) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64*1.1f)); - } - - HashSet valueSet = new HashSet(); - for (Iterator iit = map.iterator(); iit.hasNext();) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - Object[] array = map.toArray(); - assertEquals(length, array.length); - for (Object value : array) { - assertTrue(valueSet.contains(value)); - } - - Integer[] array2 = new Integer[80]; - array2 = map.toArray(array2); - for (int value : array2) { - assertTrue(valueSet.contains(value)); - } - Integer[] array3 = new Integer[120]; - array3 = map.toArray(array3); - for (int i = 0; i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - assertNull(array3[length]); - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i * 64*1.1f)); - } - - for (FloatIterator iit = map.keyIterator(); iit.hasNext();) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - FloatToObjectMap map = new FloatToObjectMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i * 128*1.1f, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i * 128*1.1f)); - assertEquals(Integer.valueOf(value), map.remove(i * 128*1.1f)); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - FloatToObjectMap map1 = new FloatToObjectMap(100); - FloatToObjectMap map2 = new FloatToObjectMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i * 1.1f, 100 + i); - map2.put(i * 1.1f, 100 + i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i * 1.1f); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i * 1.1f); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1.1f,-1); - map2.put(-1.1f,-2); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1.1f,-1); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntArrayTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntArrayTest.java deleted file mode 100644 index e15ecf7425e..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntArrayTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.apache.lucene.facet.collections; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.IntArray; -import org.junit.Test; - -/* - * 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. - */ - -public class IntArrayTest extends FacetTestCase { - - @Test - public void test0() { - IntArray array = new IntArray(); - - assertEquals(0, array.size()); - - for (int i = 0; i < 100; ++i) { - array.addToArray(i); - } - - assertEquals(100, array.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(i, array.get(i)); - } - - assertTrue(array.equals(array)); - } - - @Test - public void test1() { - IntArray array = new IntArray(); - IntArray array2 = new IntArray(); - - assertEquals(0, array.size()); - - for (int i = 0; i < 100; ++i) { - array.addToArray(99-i); - array2.addToArray(99-i); - } - - assertEquals(100, array.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(i, array.get(99-i)); - } - - array.sort(); - for (int i = 0; i < 100; ++i) { - assertEquals(i, array.get(i)); - } - - assertTrue(array.equals(array2)); - } - - @Test - public void test2() { - IntArray array = new IntArray(); - IntArray array2 = new IntArray(); - IntArray array3 = new IntArray(); - - for (int i = 0; i < 100; ++i) { - array.addToArray(i); - } - - for (int i = 0; i < 100; ++i) { - array2.addToArray(i*2); - } - - for (int i = 0; i < 50; ++i) { - array3.addToArray(i*2); - } - - assertFalse(array.equals(array2)); - - array.intersect(array2); - assertTrue(array.equals(array3)); - assertFalse(array.equals(array2)); - } - - @Test - public void testSet() { - int[] original = new int[] { 2,4,6,8,10,12,14 }; - int[] toSet = new int[] { 1,3,5,7,9,11}; - - IntArray arr = new IntArray(); - for (int val : original) { - arr.addToArray(val); - } - - for (int i = 0; i < toSet.length; i++ ) { - int val = toSet[i]; - arr.set(i, val); - } - - // Test to see if the set worked correctly - for (int i = 0; i < toSet.length; i++ ) { - assertEquals(toSet[i], arr.get(i)); - } - - // Now attempt to set something outside of the array - try { - arr.set(100, 99); - fail("IntArray.set should have thrown an exception for attempting to set outside the array"); - } catch (ArrayIndexOutOfBoundsException e) { - // We expected this to happen so let it fall through - // silently - } - - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntHashSetTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntHashSetTest.java deleted file mode 100644 index 4545bb324f3..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntHashSetTest.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.IntHashSet; -import org.junit.Test; - -/* - * 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. - */ - -public class IntHashSetTest extends FacetTestCase { - - @Test - public void test0() { - IntHashSet set0 = new IntHashSet(); - - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - set0.add(0); - assertEquals(1, set0.size()); - assertFalse(set0.isEmpty()); - set0.remove(0); - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - } - - @Test - public void test1() { - IntHashSet set0 = new IntHashSet(); - - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - for (int i = 0; i < 1000; ++i) { - set0.add(i); - } - assertEquals(1000, set0.size()); - assertFalse(set0.isEmpty()); - for (int i = 0; i < 1000; ++i) { - assertTrue(set0.contains(i)); - } - - set0.clear(); - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - - } - - @Test - public void test2() { - IntHashSet set0 = new IntHashSet(); - - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - for (int i = 0; i < 1000; ++i) { - set0.add(1); - set0.add(-382); - } - assertEquals(2, set0.size()); - assertFalse(set0.isEmpty()); - set0.remove(-382); - set0.remove(1); - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - - } - - @Test - public void test3() { - IntHashSet set0 = new IntHashSet(); - - assertEquals(0, set0.size()); - assertTrue(set0.isEmpty()); - for (int i = 0; i < 1000; ++i) { - set0.add(i); - } - - for (int i = 0; i < 1000; i += 2) { - set0.remove(i); - } - - assertEquals(500, set0.size()); - for (int i = 0; i < 1000; ++i) { - if (i % 2 == 0) { - assertFalse(set0.contains(i)); - } else { - assertTrue(set0.contains(i)); - } - } - - } - - @Test - public void test4() { - IntHashSet set1 = new IntHashSet(); - HashSet set2 = new HashSet(); - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 500; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set1.add(value); - set2.add(value); - } else { - set1.remove(value); - set2.remove(value); - } - } - assertEquals(set2.size(), set1.size()); - for (int value : set2) { - assertTrue(set1.contains(value)); - } - } - - @Test - public void testRegularJavaSet() { - HashSet set = new HashSet(); - for (int j = 0; j < 100; ++j) { - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 5000; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set.add(value); - } else { - set.remove(value); - } - } - set.clear(); - } - } - - @Test - public void testMySet() { - IntHashSet set = new IntHashSet(); - for (int j = 0; j < 100; ++j) { - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 5000; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set.add(value); - } else { - set.remove(value); - } - } - set.clear(); - } - } - - @Test - public void testToArray() { - IntHashSet set = new IntHashSet(); - for (int j = 0; j < 100; ++j) { - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 5000; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set.add(value); - } else { - set.remove(value); - } - } - int[] vals = set.toArray(); - assertEquals(set.size(), vals.length); - - int[] realValues = new int[set.size()]; - int[] unrealValues = set.toArray(realValues); - assertEquals(realValues, unrealValues); - for (int value : vals) { - assertTrue(set.remove(value)); - } - for (int i = 0; i < vals.length; ++i) { - assertEquals(vals[i], realValues[i]); - } - } - } - - @Test - public void testZZRegularJavaSet() { - HashSet set = new HashSet(); - for (int j = 0; j < 100; ++j) { - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 5000; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set.add(value); - } else { - set.remove(value); - } - } - set.clear(); - } - } - - @Test - public void testZZMySet() { - IntHashSet set = new IntHashSet(); - for (int j = 0; j < 100; ++j) { - for (int i = 0; i < ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; ++i) { - int value = random().nextInt() % 5000; - boolean shouldAdd = random().nextBoolean(); - if (shouldAdd) { - set.add(value); - } else { - set.remove(value); - } - } - set.clear(); - } - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToDoubleMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToDoubleMapTest.java deleted file mode 100644 index a75e965c924..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToDoubleMapTest.java +++ /dev/null @@ -1,272 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.DoubleIterator; -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.IntToDoubleMap; -import org.junit.Test; - -/* - * 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. - */ - -public class IntToDoubleMapTest extends FacetTestCase { - - private static void assertGround(double value) { - assertEquals(IntToDoubleMap.GROUND, value, Double.MAX_VALUE); - } - - @Test - public void test0() { - IntToDoubleMap map = new IntToDoubleMap(); - - assertGround(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i), Double.MAX_VALUE); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertGround(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i), (100 + i), Double.MAX_VALUE); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i), (5 + i), Double.MAX_VALUE); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i), (100 + i), Double.MAX_VALUE); - } - } - - @Test - public void test1() { - IntToDoubleMap map = new IntToDoubleMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (DoubleIterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Double.valueOf(100+i))); - } - - set.clear(); - for (DoubleIterator iterator = map.iterator(); iterator.hasNext();) { - double d = iterator.next(); - if (d % 2 == 1) { - iterator.remove(); - continue; - } - set.add(d); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i+=2) { - assertTrue(set.contains(Double.valueOf(100+i))); - } - } - - @Test - public void test2() { - IntToDoubleMap map = new IntToDoubleMap(); - - assertTrue(map.isEmpty()); - assertGround(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), Double.MAX_VALUE); - } - - for (int i = 0 ; i < 200; i+=2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i+=2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), Double.MAX_VALUE); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - IntToDoubleMap map = new IntToDoubleMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i*64, 100 + i); - } - HashSet keySet = new HashSet(); - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (DoubleIterator iit = map.iterator(); iit.hasNext(); ) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - double[] array = map.toArray(); - assertEquals(length, array.length); - for (double value: array) { - assertTrue(valueSet.contains(value)); - } - - double[] array2 = new double[80]; - array2 = map.toArray(array2); - assertEquals(length, array2.length); - for (double value: array2) { - assertTrue(valueSet.contains(value)); - } - - double[] array3 = new double[120]; - array3 = map.toArray(array3); - for (int i = 0 ;i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i*64)); - } - - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - IntToDoubleMap map = new IntToDoubleMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i*128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i*128)); - assertEquals(0, Double.compare(value, map.remove(i*128))); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - IntToDoubleMap map1 = new IntToDoubleMap(100); - IntToDoubleMap map2 = new IntToDoubleMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, Float.valueOf(1f/i)); - map2.put(i, Float.valueOf(1f/i)); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1f); - map2.put(-1,-1.1f); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1f); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToFloatMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToFloatMapTest.java deleted file mode 100644 index 272c8ae6093..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToFloatMapTest.java +++ /dev/null @@ -1,272 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.FloatIterator; -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.IntToFloatMap; -import org.junit.Test; - -/* - * 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. - */ - -public class IntToFloatMapTest extends FacetTestCase { - - private static void assertGround(float value) { - assertEquals(IntToFloatMap.GROUND, value, Float.MAX_VALUE); - } - - @Test - public void test0() { - IntToFloatMap map = new IntToFloatMap(); - - assertGround(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i), Float.MAX_VALUE); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertGround(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i), (100 + i), Float.MAX_VALUE); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i), (5 + i), Float.MAX_VALUE); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i), (100 + i), Float.MAX_VALUE); - } - } - - @Test - public void test1() { - IntToFloatMap map = new IntToFloatMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (FloatIterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Float.valueOf(100+i))); - } - - set.clear(); - for (FloatIterator iterator = map.iterator(); iterator.hasNext();) { - float d = iterator.next(); - if (d % 2 == 1) { - iterator.remove(); - continue; - } - set.add(d); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i+=2) { - assertTrue(set.contains(Float.valueOf(100+i))); - } - } - - @Test - public void test2() { - IntToFloatMap map = new IntToFloatMap(); - - assertTrue(map.isEmpty()); - assertGround(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), Float.MAX_VALUE); - } - - for (int i = 0 ; i < 200; i+=2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i+=2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), Float.MAX_VALUE); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - IntToFloatMap map = new IntToFloatMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i*64, 100 + i); - } - HashSet keySet = new HashSet(); - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (FloatIterator iit = map.iterator(); iit.hasNext(); ) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - float[] array = map.toArray(); - assertEquals(length, array.length); - for (float value: array) { - assertTrue(valueSet.contains(value)); - } - - float[] array2 = new float[80]; - array2 = map.toArray(array2); - assertEquals(length, array2.length); - for (float value: array2) { - assertTrue(valueSet.contains(value)); - } - - float[] array3 = new float[120]; - array3 = map.toArray(array3); - for (int i = 0 ;i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i*64)); - } - - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - IntToFloatMap map = new IntToFloatMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i*128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i*128)); - assertEquals(0, Float.compare(value, map.remove(i*128))); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - IntToFloatMap map1 = new IntToFloatMap(100); - IntToFloatMap map2 = new IntToFloatMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, Float.valueOf(1f/i)); - map2.put(i, Float.valueOf(1f/i)); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1f); - map2.put(-1,-1.1f); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1f); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToIntMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToIntMapTest.java deleted file mode 100644 index 06988b94025..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToIntMapTest.java +++ /dev/null @@ -1,272 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.IntToIntMap; -import org.junit.Test; - -/* - * 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. - */ - -public class IntToIntMapTest extends FacetTestCase { - - private static void assertGround(int value) { - assertEquals(IntToIntMap.GROUD, value); - } - - @Test - public void test0() { - IntToIntMap map = new IntToIntMap(); - - assertGround(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i)); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertGround(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i), (100 + i)); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i), (5 + i)); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i), (100 + i)); - } - } - - @Test - public void test1() { - IntToIntMap map = new IntToIntMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (IntIterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Integer.valueOf(100+i))); - } - - set.clear(); - for (IntIterator iterator = map.iterator(); iterator.hasNext();) { - Integer integer = iterator.next(); - if (integer % 2 == 1) { - iterator.remove(); - continue; - } - set.add(integer); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i+=2) { - assertTrue(set.contains(Integer.valueOf(100+i))); - } - } - - @Test - public void test2() { - IntToIntMap map = new IntToIntMap(); - - assertTrue(map.isEmpty()); - assertGround(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i)); - } - - for (int i = 0 ; i < 200; i+=2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i+=2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i)); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - IntToIntMap map = new IntToIntMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i*64, 100 + i); - } - HashSet keySet = new HashSet(); - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (IntIterator iit = map.iterator(); iit.hasNext(); ) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - int[] array = map.toArray(); - assertEquals(length, array.length); - for (int value: array) { - assertTrue(valueSet.contains(value)); - } - - int[] array2 = new int[80]; - array2 = map.toArray(array2); - assertEquals(length, array2.length); - for (int value: array2) { - assertTrue(valueSet.contains(value)); - } - - int[] array3 = new int[120]; - array3 = map.toArray(array3); - for (int i = 0 ;i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i*64)); - } - - for (IntIterator iit = map.keyIterator(); iit.hasNext(); ) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - IntToIntMap map = new IntToIntMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i*128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i*128)); - assertEquals(value, map.remove(i*128)); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - IntToIntMap map1 = new IntToIntMap(100); - IntToIntMap map2 = new IntToIntMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, 100 + i); - map2.put(i, 100 + i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1); - map2.put(-1,-2); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToObjectMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToObjectMapTest.java deleted file mode 100644 index d505155cc36..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/IntToObjectMapTest.java +++ /dev/null @@ -1,267 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.IntToObjectMap; -import org.junit.Test; - -/* - * 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. - */ - -public class IntToObjectMapTest extends FacetTestCase { - - @Test - public void test0() { - IntToObjectMap map = new IntToObjectMap(); - - assertNull(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i).intValue()); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertNull(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i).intValue(), (100 + i)); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i).intValue(), (5 + i)); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i).intValue(), (100 + i)); - } - } - - @Test - public void test1() { - IntToObjectMap map = new IntToObjectMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - - set.clear(); - for (Iterator iterator = map.iterator(); iterator.hasNext();) { - Integer integer = iterator.next(); - if (integer % 2 == 1) { - iterator.remove(); - continue; - } - set.add(integer); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i += 2) { - assertTrue(set.contains(Integer.valueOf(100 + i))); - } - } - - @Test - public void test2() { - IntToObjectMap map = new IntToObjectMap(); - - assertTrue(map.isEmpty()); - assertNull(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNull(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i).intValue()); - } - - for (int i = 0; i < 200; i += 2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i += 2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i).intValue()); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - IntToObjectMap map = new IntToObjectMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i * 64, 100 + i); - } - HashSet keySet = new HashSet(); - for (IntIterator iit = map.keyIterator(); iit.hasNext();) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (Iterator iit = map.iterator(); iit.hasNext();) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - Object[] array = map.toArray(); - assertEquals(length, array.length); - for (Object value : array) { - assertTrue(valueSet.contains(value)); - } - - Integer[] array2 = new Integer[80]; - array2 = map.toArray(array2); - for (int value : array2) { - assertTrue(valueSet.contains(value)); - } - Integer[] array3 = new Integer[120]; - array3 = map.toArray(array3); - for (int i = 0; i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - assertNull(array3[length]); - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i * 64)); - } - - for (IntIterator iit = map.keyIterator(); iit.hasNext();) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - IntToObjectMap map = new IntToObjectMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i * 128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i * 128)); - assertEquals(Integer.valueOf(value), map.remove(i * 128)); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - IntToObjectMap map1 = new IntToObjectMap(100); - IntToObjectMap map2 = new IntToObjectMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, Double.valueOf(1f/i)); - map2.put(i, Double.valueOf(1f/i)); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1d); - map2.put(-1,-1.1d); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1d); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToFloatMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToFloatMapTest.java deleted file mode 100644 index b291cc986a9..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToFloatMapTest.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.FloatIterator; -import org.apache.lucene.facet.collections.ObjectToFloatMap; -import org.junit.Test; - -/* - * 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. - */ - -public class ObjectToFloatMapTest extends FacetTestCase { - - @Test - public void test0() { - ObjectToFloatMap map = new ObjectToFloatMap(); - - assertNaN(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNaN(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i), 1E-5); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertNaN(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i), (100 + i), 1E-5); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i), (5 + i), 1E-5); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i), (100 + i), 1E-5); - } - } - - private static void assertNaN(float f) { - assertTrue(Float.isNaN(f)); - } - - private static void assertNotNaN(float f) { - assertFalse(Float.isNaN(f)); - } - - @Test - public void test1() { - ObjectToFloatMap map = new ObjectToFloatMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (FloatIterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Float.valueOf(100+i))); - } - - set.clear(); - for (FloatIterator iterator = map.iterator(); iterator.hasNext();) { - Float value = iterator.next(); - if (value % 2 == 1) { - iterator.remove(); - continue; - } - set.add(value); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i+=2) { - assertTrue(set.contains(Float.valueOf(100+i))); - } - } - - @Test - public void test2() { - ObjectToFloatMap map = new ObjectToFloatMap(); - - assertTrue(map.isEmpty()); - assertNaN(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotNaN(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), 1E-5); - } - - for (int i = 0 ; i < 200; i+=2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i+=2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), 1E-5); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - ObjectToFloatMap map = new ObjectToFloatMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i*64, 100 + i); - } - HashSet keySet = new HashSet(); - for (Iterator iit = map.keyIterator(); iit.hasNext(); ) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (FloatIterator iit = map.iterator(); iit.hasNext(); ) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - float[] array = map.toArray(); - assertEquals(length, array.length); - for (float value: array) { - assertTrue(valueSet.contains(value)); - } - - float[] array2 = new float[80]; - array2 = map.toArray(array2); - assertEquals(80, array2.length); - for (float value: array2) { - assertTrue(valueSet.contains(value)); - } - - float[] array3 = new float[120]; - array3 = map.toArray(array3); - for (int i = 0 ;i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - assertNaN(array3[length]); - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i*64)); - } - - for (Iterator iit = map.keyIterator(); iit.hasNext(); ) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - ObjectToFloatMap map = new ObjectToFloatMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i*128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i*128)); - assertEquals(0, Float.compare(value, map.remove(i*128))); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - ObjectToFloatMap map1 = new ObjectToFloatMap(100); - ObjectToFloatMap map2 = new ObjectToFloatMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i, Float.valueOf(1f/i)); - map2.put(i, Float.valueOf(1f/i)); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1,-1f); - map2.put(-1,-1.1f); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1,-1f); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToIntMapTest.java b/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToIntMapTest.java deleted file mode 100644 index 89631284d61..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/ObjectToIntMapTest.java +++ /dev/null @@ -1,277 +0,0 @@ -package org.apache.lucene.facet.collections; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Random; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.IntIterator; -import org.apache.lucene.facet.collections.ObjectToIntMap; -import org.junit.Test; - -/* - * 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. - */ - -public class ObjectToIntMapTest extends FacetTestCase { - - @Test - public void test0() { - ObjectToIntMap map = new ObjectToIntMap(); - - assertIntegerMaxValue(map.get(0)); - - for (int i = 0; i < 100; ++i) { - int value = 100 + i; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotIntegerMaxValue(map.get(i)); - } - - assertEquals(100, map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(100 + i, map.get(i), 1E-5); - - } - - for (int i = 10; i < 90; ++i) { - map.remove(i); - assertIntegerMaxValue(map.get(i)); - } - - assertEquals(20, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 10 && i < 90)); - } - - for (int i = 5; i < 85; ++i) { - map.put(i, Integer.valueOf(5 + i)); - } - assertEquals(95, map.size()); - for (int i = 0; i < 100; ++i) { - assertEquals(map.containsKey(i), !(i >= 85 && i < 90)); - } - for (int i = 0; i < 5; ++i) { - assertEquals(map.get(i), (100 + i), 1E-5); - } - for (int i = 5; i < 85; ++i) { - assertEquals(map.get(i), (5 + i), 1E-5); - } - for (int i = 90; i < 100; ++i) { - assertEquals(map.get(i), (100 + i), 1E-5); - } - } - - private static void assertIntegerMaxValue(int i) { - assertTrue(i == Integer.MAX_VALUE); - } - - private static void assertNotIntegerMaxValue(int i) { - assertFalse(i == Integer.MAX_VALUE); - } - - @Test - public void test1() { - ObjectToIntMap map = new ObjectToIntMap(); - - for (int i = 0; i < 100; ++i) { - map.put(i, Integer.valueOf(100 + i)); - } - - HashSet set = new HashSet(); - - for (IntIterator iterator = map.iterator(); iterator.hasNext();) { - set.add(iterator.next()); - } - - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; ++i) { - assertTrue(set.contains(Integer.valueOf(100+i))); - } - - set.clear(); - for (IntIterator iterator = map.iterator(); iterator.hasNext();) { - Integer value = iterator.next(); - if (value % 2 == 1) { - iterator.remove(); - continue; - } - set.add(value); - } - assertEquals(set.size(), map.size()); - for (int i = 0; i < 100; i+=2) { - assertTrue(set.contains(Integer.valueOf(100+i))); - } - } - - @Test - public void test2() { - ObjectToIntMap map = new ObjectToIntMap(); - - assertTrue(map.isEmpty()); - assertIntegerMaxValue(map.get(0)); - for (int i = 0; i < 128; ++i) { - int value = i * 4096; - assertFalse(map.containsValue(value)); - map.put(i, value); - assertTrue(map.containsValue(value)); - assertNotIntegerMaxValue(map.get(i)); - assertFalse(map.isEmpty()); - } - - assertEquals(128, map.size()); - for (int i = 0; i < 128; ++i) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), 1E-5); - } - - for (int i = 0 ; i < 200; i+=2) { - map.remove(i); - } - assertEquals(64, map.size()); - for (int i = 1; i < 128; i+=2) { - assertTrue(map.containsKey(i)); - assertEquals(i * 4096, map.get(i), 1E-5); - map.remove(i); - } - assertTrue(map.isEmpty()); - } - - @Test - public void test3() { - ObjectToIntMap map = new ObjectToIntMap(); - int length = 100; - for (int i = 0; i < length; ++i) { - map.put(i*64, 100 + i); - } - HashSet keySet = new HashSet(); - for (Iterator iit = map.keyIterator(); iit.hasNext(); ) { - keySet.add(iit.next()); - } - assertEquals(length, keySet.size()); - for (int i = 0; i < length; ++i) { - assertTrue(keySet.contains(i * 64)); - } - - HashSet valueSet = new HashSet(); - for (IntIterator iit = map.iterator(); iit.hasNext(); ) { - valueSet.add(iit.next()); - } - assertEquals(length, valueSet.size()); - int[] array = map.toArray(); - assertEquals(length, array.length); - for (int value: array) { - assertTrue(valueSet.contains(value)); - } - - int[] array2 = new int[80]; - array2 = map.toArray(array2); - assertEquals(80, array2.length); - for (int value: array2) { - assertTrue(valueSet.contains(value)); - } - - int[] array3 = new int[120]; - array3 = map.toArray(array3); - for (int i = 0 ;i < length; ++i) { - assertTrue(valueSet.contains(array3[i])); - } - assertIntegerMaxValue(array3[length]); - - for (int i = 0; i < length; ++i) { - assertTrue(map.containsValue(i + 100)); - assertTrue(map.containsKey(i*64)); - } - - for (Iterator iit = map.keyIterator(); iit.hasNext(); ) { - iit.next(); - iit.remove(); - } - assertTrue(map.isEmpty()); - assertEquals(0, map.size()); - - } - - // now with random data.. and lots of it - @Test - public void test4() { - ObjectToIntMap map = new ObjectToIntMap(); - int length = ArrayHashMapTest.RANDOM_TEST_NUM_ITERATIONS; - - // for a repeatable random sequence - long seed = random().nextLong(); - Random random = new Random(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - map.put(i*128, value); - } - - assertEquals(length, map.size()); - - // now repeat - random.setSeed(seed); - - for (int i = 0; i < length; ++i) { - int value = random.nextInt(Integer.MAX_VALUE); - assertTrue(map.containsValue(value)); - assertTrue(map.containsKey(i*128)); - assertEquals(value, map.remove(i*128)); - } - assertEquals(0, map.size()); - assertTrue(map.isEmpty()); - } - - @Test - public void testEquals() { - ObjectToIntMap map1 = new ObjectToIntMap(100); - ObjectToIntMap map2 = new ObjectToIntMap(100); - assertEquals("Empty maps should be equal", map1, map2); - assertEquals("hashCode() for empty maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 0; i < 100; ++i) { - map1.put(i * 1.1f, 100 + i); - map2.put(i * 1.1f, 100 + i); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - for (int i = 10; i < 20; i++) { - map1.remove(i * 1.1f); - } - assertFalse("Different maps should not be equal", map1.equals(map2)); - - for (int i = 19; i >=10; --i) { - map2.remove(i * 1.1f); - } - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - - map1.put(-1.1f,-1); - map2.put(-1.1f,-2); - assertFalse("Different maps should not be equal", map1.equals(map2)); - - map2.put(-1.1f,-1); - assertEquals("Identical maps should be equal", map1, map2); - assertEquals("hashCode() for identical maps should be equal", - map1.hashCode(), map2.hashCode()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestFacetsAccumulatorWithComplement.java b/lucene/facet/src/test/org/apache/lucene/facet/complements/TestFacetsAccumulatorWithComplement.java deleted file mode 100644 index d80578ba02c..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestFacetsAccumulatorWithComplement.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.apache.lucene.facet.complements; - -import java.io.IOException; -import java.util.List; - -import org.apache.lucene.facet.FacetTestBase; -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.index.ParallelAtomicReader; -import org.apache.lucene.index.SlowCompositeReaderWrapper; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/* - * 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. - */ - -public class TestFacetsAccumulatorWithComplement extends FacetTestBase { - - private FacetIndexingParams fip; - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - fip = getFacetIndexingParams(Integer.MAX_VALUE); - initIndex(fip); - } - - @Override - @After - public void tearDown() throws Exception { - closeAll(); - super.tearDown(); - } - - /** - * Test that complements does not cause a failure when using a parallel reader - */ - @Test - public void testComplementsWithParallerReader() throws Exception { - IndexReader origReader = indexReader; - ParallelAtomicReader pr = new ParallelAtomicReader(SlowCompositeReaderWrapper.wrap(origReader)); - indexReader = pr; - try { - doTestComplements(); - } finally { - indexReader = origReader; - } - } - - /** - * Test that complements works with MultiReader - */ - @Test - public void testComplementsWithMultiReader() throws Exception { - final IndexReader origReader = indexReader; - indexReader = new MultiReader(origReader); - try { - doTestComplements(); - } finally { - indexReader = origReader; - } - } - - /** - * Test that score is indeed constant when using a constant score - */ - @Test - public void testComplements() throws Exception { - doTestComplements(); - } - - private void doTestComplements() throws Exception { - // verify by facet values - List countResWithComplement = findFacets(true); - List countResNoComplement = findFacets(false); - - assertEquals("Wrong number of facet count results with complement!",1,countResWithComplement.size()); - assertEquals("Wrong number of facet count results no complement!",1,countResNoComplement.size()); - - FacetResultNode parentResWithComp = countResWithComplement.get(0).getFacetResultNode(); - FacetResultNode parentResNoComp = countResWithComplement.get(0).getFacetResultNode(); - - assertEquals("Wrong number of top count aggregated categories with complement!",3,parentResWithComp.subResults.size()); - assertEquals("Wrong number of top count aggregated categories no complement!",3,parentResNoComp.subResults.size()); - } - - /** compute facets with certain facet requests and docs */ - private List findFacets(boolean withComplement) throws IOException { - FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest(new FacetLabel("root","a"), 10)); - OldFacetsAccumulator sfa = new OldFacetsAccumulator(fsp, indexReader, taxoReader); - sfa.setComplementThreshold(withComplement ? OldFacetsAccumulator.FORCE_COMPLEMENT : OldFacetsAccumulator.DISABLE_COMPLEMENT); - FacetsCollector fc = FacetsCollector.create(sfa); - searcher.search(new MatchAllDocsQuery(), fc); - - List res = fc.getFacetResults(); - - // Results are ready, printing them... - int i = 0; - if (VERBOSE) { - for (FacetResult facetResult : res) { - System.out.println("Res "+(i++)+": "+facetResult); - } - } - - assertEquals(withComplement, sfa.isUsingComplements()); - - return res; - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCounts.java deleted file mode 100644 index f4488bd30c6..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCounts.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.apache.lucene.facet.complements; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; - -import org.apache.lucene.document.Document; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.complements.TotalFacetCounts; -import org.apache.lucene.facet.complements.TotalFacetCountsCache; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util._TestUtil; -import org.junit.Test; - -/* - * 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. - */ - -public class TestTotalFacetCounts extends FacetTestCase { - - private static void initCache() { - TotalFacetCountsCache.getSingleton().clear(); - TotalFacetCountsCache.getSingleton().setCacheSize(1); // Set to keep one in mem - } - - @Test - public void testWriteRead() throws IOException { - doTestWriteRead(14); - doTestWriteRead(100); - doTestWriteRead(7); - doTestWriteRead(3); - doTestWriteRead(1); - } - - private void doTestWriteRead(final int partitionSize) throws IOException { - initCache(); - - Directory indexDir = newDirectory(); - Directory taxoDir = newDirectory(); - IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); - - FacetIndexingParams iParams = new FacetIndexingParams() { - @Override - public int getPartitionSize() { - return partitionSize; - } - - @Override - public CategoryListParams getCategoryListParams(FacetLabel category) { - return new CategoryListParams() { - @Override - public OrdinalPolicy getOrdinalPolicy(String dimension) { - return OrdinalPolicy.ALL_PARENTS; - } - }; - } - }; - // The counts that the TotalFacetCountsArray should have after adding - // the below facets to the index. - int[] expectedCounts = new int[] { 0, 3, 1, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 }; - String[] categories = new String[] { "a/b", "c/d", "a/e", "a/d", "c/g", "c/z", "b/a", "1/2", "b/c" }; - - FacetFields facetFields = new FacetFields(taxoWriter, iParams); - for (String cat : categories) { - Document doc = new Document(); - facetFields.addFields(doc, Collections.singletonList(new FacetLabel(cat, '/'))); - indexWriter.addDocument(doc); - } - - // Commit Changes - IOUtils.close(indexWriter, taxoWriter); - - DirectoryReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); - - int[] intArray = new int[iParams.getPartitionSize()]; - - TotalFacetCountsCache tfcc = TotalFacetCountsCache.getSingleton(); - File tmpFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); - tfcc.store(tmpFile, indexReader, taxoReader, iParams); - tfcc.clear(); // not really required because TFCC overrides on load(), but in the test we need not rely on this. - tfcc.load(tmpFile, indexReader, taxoReader, iParams); - - // now retrieve the one just loaded - TotalFacetCounts totalCounts = tfcc.getTotalCounts(indexReader, taxoReader, iParams); - - int partition = 0; - for (int i = 0; i < expectedCounts.length; i += partitionSize) { - totalCounts.fillTotalCountsForPartition(intArray, partition); - int[] partitionExpectedCounts = new int[partitionSize]; - int nToCopy = Math.min(partitionSize,expectedCounts.length-i); - System.arraycopy(expectedCounts, i, partitionExpectedCounts, 0, nToCopy); - assertTrue("Wrong counts! for partition "+partition+ - "\nExpected:\n" + Arrays.toString(partitionExpectedCounts)+ - "\nActual:\n" + Arrays.toString(intArray), - Arrays.equals(partitionExpectedCounts, intArray)); - ++partition; - } - IOUtils.close(indexReader, taxoReader); - IOUtils.close(indexDir, taxoDir); - tmpFile.delete(); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCountsCache.java b/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCountsCache.java deleted file mode 100644 index cf098855dcb..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/complements/TestTotalFacetCountsCache.java +++ /dev/null @@ -1,503 +0,0 @@ -package org.apache.lucene.facet.complements; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.analysis.MockTokenizer; -import org.apache.lucene.document.Document; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.SlowRAMDirectory; -import org.apache.lucene.facet.complements.TotalFacetCounts; -import org.apache.lucene.facet.complements.TotalFacetCountsCache; -import org.apache.lucene.facet.complements.TotalFacetCounts.CreationType; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.MockDirectoryWrapper; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util._TestUtil; -import org.junit.Before; -import org.junit.Test; - -/* - * 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. - */ - -public class TestTotalFacetCountsCache extends FacetTestCase { - - static final TotalFacetCountsCache TFC = TotalFacetCountsCache.getSingleton(); - - /** - * Thread class to be used in tests for this method. This thread gets a TFC - * and records times. - */ - private static class TFCThread extends Thread { - private final IndexReader r; - private final DirectoryTaxonomyReader tr; - private final FacetIndexingParams iParams; - - TotalFacetCounts tfc; - - public TFCThread(IndexReader r, DirectoryTaxonomyReader tr, FacetIndexingParams iParams) { - this.r = r; - this.tr = tr; - this.iParams = iParams; - } - @Override - public void run() { - try { - tfc = TFC.getTotalCounts(r, tr, iParams); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - /** Utility method to add a document and facets to an index/taxonomy. */ - private static void addFacets(FacetIndexingParams iParams, IndexWriter iw, - TaxonomyWriter tw, String... strings) throws IOException { - Document doc = new Document(); - FacetFields facetFields = new FacetFields(tw, iParams); - facetFields.addFields(doc, Collections.singletonList(new FacetLabel(strings))); - iw.addDocument(doc); - } - - /** Clears the cache and sets its size to one. */ - private static void initCache() { - TFC.clear(); - TFC.setCacheSize(1); // Set to keep one in memory - } - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - initCache(); - } - - /** runs few searches in parallel */ - public void testGeneralSynchronization() throws Exception { - int numIters = atLeast(4); - Random random = random(); - for (int i = 0; i < numIters; i++) { - int numThreads = random.nextInt(3) + 2; // 2-4 - int sleepMillis = random.nextBoolean() ? -1 : random.nextInt(10) + 1 /*1-10*/; - int cacheSize = random.nextInt(4); // 0-3 - doTestGeneralSynchronization(numThreads, sleepMillis, cacheSize); - } - } - - private static final String[] CATEGORIES = new String[] { "a/b", "c/d", "a/e", "a/d", "c/g", "c/z", "b/a", "1/2", "b/c" }; - - private void index(Directory indexDir, Directory taxoDir) throws IOException { - IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); - FacetFields facetFields = new FacetFields(taxoWriter); - - for (String cat : CATEGORIES) { - Document doc = new Document(); - facetFields.addFields(doc, Collections.singletonList(new FacetLabel(cat, '/'))); - indexWriter.addDocument(doc); - } - - IOUtils.close(indexWriter, taxoWriter); - } - - private void doTestGeneralSynchronization(int numThreads, int sleepMillis, int cacheSize) throws Exception { - TFC.setCacheSize(cacheSize); - SlowRAMDirectory slowIndexDir = new SlowRAMDirectory(-1, random()); - MockDirectoryWrapper indexDir = new MockDirectoryWrapper(random(), slowIndexDir); - SlowRAMDirectory slowTaxoDir = new SlowRAMDirectory(-1, random()); - MockDirectoryWrapper taxoDir = new MockDirectoryWrapper(random(), slowTaxoDir); - - // Index documents without the "slowness" - index(indexDir, taxoDir); - - slowIndexDir.setSleepMillis(sleepMillis); - slowTaxoDir.setSleepMillis(sleepMillis); - - // Open the slow readers - IndexReader slowIndexReader = DirectoryReader.open(indexDir); - TaxonomyReader slowTaxoReader = new DirectoryTaxonomyReader(taxoDir); - - // Class to perform search and return results as threads - class Multi extends Thread { - private List results; - private FacetIndexingParams iParams; - private IndexReader indexReader; - private TaxonomyReader taxoReader; - - public Multi(IndexReader indexReader, TaxonomyReader taxoReader, FacetIndexingParams iParams) { - this.indexReader = indexReader; - this.taxoReader = taxoReader; - this.iParams = iParams; - } - - public List getResults() { - return results; - } - - @Override - public void run() { - try { - FacetSearchParams fsp = new FacetSearchParams(iParams, new CountFacetRequest(new FacetLabel("a"), 10), - new CountFacetRequest(new FacetLabel("b"), 10)); - IndexSearcher searcher = new IndexSearcher(indexReader); - FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader); - searcher.search(new MatchAllDocsQuery(), fc); - results = fc.getFacetResults(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - Multi[] multis = new Multi[numThreads]; - for (int i = 0; i < numThreads; i++) { - multis[i] = new Multi(slowIndexReader, slowTaxoReader, FacetIndexingParams.DEFAULT); - } - - for (Multi m : multis) { - m.start(); - } - - // Wait for threads and get results - String[] expLabelsA = new String[] { "a/d", "a/e", "a/b" }; - String[] expLabelsB = new String[] { "b/c", "b/a" }; - for (Multi m : multis) { - m.join(); - List facetResults = m.getResults(); - assertEquals("expected two results", 2, facetResults.size()); - - FacetResultNode nodeA = facetResults.get(0).getFacetResultNode(); - int i = 0; - for (FacetResultNode node : nodeA.subResults) { - assertEquals("wrong count", 1, (int) node.value); - assertEquals(expLabelsA[i++], node.label.toString('/')); - } - - FacetResultNode nodeB = facetResults.get(1).getFacetResultNode(); - i = 0; - for (FacetResultNode node : nodeB.subResults) { - assertEquals("wrong count", 1, (int) node.value); - assertEquals(expLabelsB[i++], node.label.toString('/')); - } - } - - IOUtils.close(slowIndexReader, slowTaxoReader, indexDir, taxoDir); - } - - /** - * Simple test to make sure the TotalFacetCountsManager updates the - * TotalFacetCounts array only when it is supposed to, and whether it - * is recomputed or read from disk. - */ - @Test - public void testGenerationalConsistency() throws Exception { - // Create temporary RAMDirectories - Directory indexDir = newDirectory(); - Directory taxoDir = newDirectory(); - - // Create our index/taxonomy writers - IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); - FacetIndexingParams iParams = FacetIndexingParams.DEFAULT; - - // Add a facet to the index - addFacets(iParams, indexWriter, taxoWriter, "a", "b"); - - // Commit Changes - indexWriter.commit(); - taxoWriter.commit(); - - // Open readers - DirectoryReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); - - // As this is the first time we have invoked the TotalFacetCountsManager, - // we should expect to compute and not read from disk. - TotalFacetCounts totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - int prevGen = assertRecomputed(totalCounts, 0, "after first attempt to get it!"); - - // Repeating same operation should pull from the cache - not recomputed. - assertTrue("Should be obtained from cache at 2nd attempt",totalCounts == - TFC.getTotalCounts(indexReader, taxoReader, iParams)); - - // Repeat the same operation as above. but clear first - now should recompute again - initCache(); - totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - prevGen = assertRecomputed(totalCounts, prevGen, "after cache clear, 3rd attempt to get it!"); - - //store to file - File outputFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); - initCache(); - TFC.store(outputFile, indexReader, taxoReader, iParams); - totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - prevGen = assertRecomputed(totalCounts, prevGen, "after cache clear, 4th attempt to get it!"); - - //clear and load - initCache(); - TFC.load(outputFile, indexReader, taxoReader, iParams); - totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - prevGen = assertReadFromDisc(totalCounts, prevGen, "after 5th attempt to get it!"); - - // Add a new facet to the index, commit and refresh readers - addFacets(iParams, indexWriter, taxoWriter, "c", "d"); - IOUtils.close(indexWriter, taxoWriter); - - TaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(taxoReader); - assertNotNull(newTaxoReader); - assertTrue("should have received more cagtegories in updated taxonomy", newTaxoReader.getSize() > taxoReader.getSize()); - taxoReader.close(); - taxoReader = newTaxoReader; - - DirectoryReader r2 = DirectoryReader.openIfChanged(indexReader); - assertNotNull(r2); - indexReader.close(); - indexReader = r2; - - // now use the new reader - should recompute - totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - prevGen = assertRecomputed(totalCounts, prevGen, "after updating the index - 7th attempt!"); - - // try again - should not recompute - assertTrue("Should be obtained from cache at 8th attempt",totalCounts == - TFC.getTotalCounts(indexReader, taxoReader, iParams)); - - IOUtils.close(indexReader, taxoReader); - outputFile.delete(); - IOUtils.close(indexDir, taxoDir); - } - - private int assertReadFromDisc(TotalFacetCounts totalCounts, int prevGen, String errMsg) { - assertEquals("should read from disk "+errMsg, CreationType.Loaded, totalCounts.createType4test); - int gen4test = totalCounts.gen4test; - assertTrue("should read from disk "+errMsg, gen4test > prevGen); - return gen4test; - } - - private int assertRecomputed(TotalFacetCounts totalCounts, int prevGen, String errMsg) { - assertEquals("should recompute "+errMsg, CreationType.Computed, totalCounts.createType4test); - int gen4test = totalCounts.gen4test; - assertTrue("should recompute "+errMsg, gen4test > prevGen); - return gen4test; - } - - /** - * This test is to address a bug in a previous version. If a TFC cache is - * written to disk, and then the taxonomy grows (but the index does not change), - * and then the TFC cache is re-read from disk, there will be an exception - * thrown, as the integers are read off of the disk according to taxonomy - * size, which has changed. - */ - @Test - public void testGrowingTaxonomy() throws Exception { - Directory indexDir = newDirectory(); - Directory taxoDir = newDirectory(); - - // Create our index/taxonomy writers - IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); - FacetIndexingParams iParams = new FacetIndexingParams() { - @Override - public int getPartitionSize() { - return 2; - } - }; - // Add a facet to the index - addFacets(iParams, indexWriter, taxoWriter, "a", "b"); - // Commit Changes - indexWriter.commit(); - taxoWriter.commit(); - - DirectoryReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); - - // Create TFC and write cache to disk - File outputFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); - TFC.store(outputFile, indexReader, taxoReader, iParams); - - // Make the taxonomy grow without touching the index - for (int i = 0; i < 10; i++) { - taxoWriter.addCategory(new FacetLabel("foo", Integer.toString(i))); - } - taxoWriter.commit(); - TaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(taxoReader); - assertNotNull(newTaxoReader); - taxoReader.close(); - taxoReader = newTaxoReader; - - initCache(); - - // With the bug, this next call should result in an exception - TFC.load(outputFile, indexReader, taxoReader, iParams); - TotalFacetCounts totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); - assertReadFromDisc(totalCounts, 0, "after reading from disk."); - - outputFile.delete(); - IOUtils.close(indexWriter, taxoWriter, indexReader, taxoReader); - IOUtils.close(indexDir, taxoDir); - } - - /** - * Test that a new TFC is only calculated and placed in memory (by two - * threads who want it at the same time) only once. - */ - @Test - public void testMemoryCacheSynchronization() throws Exception { - SlowRAMDirectory indexDir = new SlowRAMDirectory(-1, null); - SlowRAMDirectory taxoDir = new SlowRAMDirectory(-1, null); - - // Write index using 'normal' directories - IndexWriter w = new IndexWriter(indexDir, new IndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); - DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); - FacetIndexingParams iParams = FacetIndexingParams.DEFAULT; - // Add documents and facets - for (int i = 0; i < 1000; i++) { - addFacets(iParams, w, tw, "facet", Integer.toString(i)); - } - w.close(); - tw.close(); - - indexDir.setSleepMillis(1); - taxoDir.setSleepMillis(1); - - IndexReader r = DirectoryReader.open(indexDir); - DirectoryTaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); - - // Create and start threads. Thread1 should lock the cache and calculate - // the TFC array. The second thread should block until the first is - // done, then successfully retrieve from the cache without recalculating - // or reading from disk. - TFCThread tfcCalc1 = new TFCThread(r, tr, iParams); - TFCThread tfcCalc2 = new TFCThread(r, tr, iParams); - tfcCalc1.start(); - // Give thread 1 a head start to ensure correct sequencing for testing - Thread.sleep(5); - tfcCalc2.start(); - - tfcCalc1.join(); - tfcCalc2.join(); - - // Since this test ends up with references to the same TFC object, we - // can only test the times to make sure that they are the same. - assertRecomputed(tfcCalc1.tfc, 0, "thread 1 should recompute"); - assertRecomputed(tfcCalc2.tfc, 0, "thread 2 should recompute"); - assertTrue("Both results should be the same (as their inputs are the same objects)", - tfcCalc1.tfc == tfcCalc2.tfc); - - r.close(); - tr.close(); - } - - /** - * Simple test to make sure the TotalFacetCountsManager updates the - * TotalFacetCounts array only when it is supposed to, and whether it - * is recomputed or read from disk, but this time with TWO different - * TotalFacetCounts - */ - @Test - public void testMultipleIndices() throws IOException { - Directory indexDir1 = newDirectory(), indexDir2 = newDirectory(); - Directory taxoDir1 = newDirectory(), taxoDir2 = newDirectory(); - - // Create our index/taxonomy writers - IndexWriter indexWriter1 = new IndexWriter(indexDir1, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - IndexWriter indexWriter2 = new IndexWriter(indexDir2, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - TaxonomyWriter taxoWriter1 = new DirectoryTaxonomyWriter(taxoDir1); - TaxonomyWriter taxoWriter2 = new DirectoryTaxonomyWriter(taxoDir2); - FacetIndexingParams iParams = FacetIndexingParams.DEFAULT; - - // Add a facet to the index - addFacets(iParams, indexWriter1, taxoWriter1, "a", "b"); - addFacets(iParams, indexWriter1, taxoWriter1, "d", "e"); - // Commit Changes - indexWriter1.commit(); - indexWriter2.commit(); - taxoWriter1.commit(); - taxoWriter2.commit(); - - // Open two readers - DirectoryReader indexReader1 = DirectoryReader.open(indexDir1); - DirectoryReader indexReader2 = DirectoryReader.open(indexDir2); - TaxonomyReader taxoReader1 = new DirectoryTaxonomyReader(taxoDir1); - TaxonomyReader taxoReader2 = new DirectoryTaxonomyReader(taxoDir2); - - // As this is the first time we have invoked the TotalFacetCountsManager, we - // should expect to compute. - TotalFacetCounts totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); - int prevGen = -1; - prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 1"); - assertTrue("attempt 1b for same input [0] shout find it in cache", - totalCounts0 == TFC.getTotalCounts(indexReader1, taxoReader1, iParams)); - - // 2nd Reader - As this is the first time we have invoked the - // TotalFacetCountsManager, we should expect a state of NEW to be returned. - TotalFacetCounts totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); - prevGen = assertRecomputed(totalCounts1, prevGen, "after attempt 2"); - assertTrue("attempt 2b for same input [1] shout find it in cache", - totalCounts1 == TFC.getTotalCounts(indexReader2, taxoReader2, iParams)); - - // Right now cache size is one, so first TFC is gone and should be recomputed - totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); - prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 3"); - - // Similarly will recompute the second result - totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); - prevGen = assertRecomputed(totalCounts1, prevGen, "after attempt 4"); - - // Now we set the cache size to two, meaning both should exist in the - // cache simultaneously - TFC.setCacheSize(2); - - // Re-compute totalCounts0 (was evicted from the cache when the cache was smaller) - totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); - prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 5"); - - // now both are in the larger cache and should not be recomputed - totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); - assertTrue("with cache of size 2 res no. 0 should come from cache", - totalCounts0 == TFC.getTotalCounts(indexReader1, taxoReader1, iParams)); - assertTrue("with cache of size 2 res no. 1 should come from cache", - totalCounts1 == TFC.getTotalCounts(indexReader2, taxoReader2, iParams)); - - IOUtils.close(indexWriter1, indexWriter2, taxoWriter1, taxoWriter2); - IOUtils.close(indexReader1, indexReader2, taxoReader1, taxoReader2); - IOUtils.close(indexDir1, indexDir2, taxoDir1, taxoDir2); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingSpeed.java b/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingSpeed.java deleted file mode 100644 index dee37ea39fa..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingSpeed.java +++ /dev/null @@ -1,649 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import java.io.IOException; -import java.text.NumberFormat; -import java.util.Arrays; -import java.util.Locale; - -import org.apache.lucene.facet.encoding.DGapIntEncoder; -import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder; -import org.apache.lucene.facet.encoding.EightFlagsIntEncoder; -import org.apache.lucene.facet.encoding.FourFlagsIntEncoder; -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.encoding.NOnesIntEncoder; -import org.apache.lucene.facet.encoding.SortingIntEncoder; -import org.apache.lucene.facet.encoding.UniqueValuesIntEncoder; -import org.apache.lucene.facet.encoding.VInt8IntEncoder; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -public class EncodingSpeed { - - private static int[] data3630 = null; - private static int[] data9910 = null; - private static int[] data501871 = null; - private static int[] data10k = null; - private static String resultsFormat = "%-60s %10s %20d %26s %20d %26s"; - private static String headerFormat = "%-60s %10s %20s %26s %20s %26s"; - private static int integers = 100000000; - - private static NumberFormat nf; - - public static void main(String[] args) throws IOException { - testFacetIDs(data3630, 3630); - testFacetIDs(data9910, 9910); - testFacetIDs(data10k, 10000); - testFacetIDs(data501871, 501871); - } - - private static IntsRef newIntsRef(int[] data) { - IntsRef res = new IntsRef(data.length); - System.arraycopy(data, 0, res.ints, 0, data.length); - res.length = data.length; - return res; - } - - private static void testFacetIDs(int[] facetIDs, int docID) throws IOException { - int loopFactor = integers / facetIDs.length; - System.out - .println("\nEstimating ~" - + integers - + " Integers compression time by\nEncoding/decoding facets' ID payload of docID = " - + docID + " (unsorted, length of: " + facetIDs.length - + ") " + loopFactor + " times."); - - System.out.println(); - String header = String.format(Locale.ROOT, headerFormat, "Encoder", "Bits/Int", - "Encode Time", "Encode Time", "Decode Time", "Decode Time"); - - System.out.println(header); - String header2 = String.format(Locale.ROOT, headerFormat, "", "", "[milliseconds]", - "[microsecond / int]", "[milliseconds]", "[microsecond / int]"); - - System.out.println(header2); - - char[] separator = header.toCharArray(); - Arrays.fill(separator, '-'); - System.out.println(separator); - - encoderTest(new VInt8IntEncoder(), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new VInt8IntEncoder())), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new VInt8IntEncoder()))), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapVInt8IntEncoder())), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new EightFlagsIntEncoder()))), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new FourFlagsIntEncoder()))), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(3)))), facetIDs, loopFactor); - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(4)))), facetIDs, loopFactor); - - System.out.println(); - } - - private static void encoderTest(IntEncoder encoder, int[] values, int loopFactor) throws IOException { - - BytesRef bytes = new BytesRef(values.length); // at least one byte per value - - // -- Looping 100 times as a warm up -------------------------- - for (int i = 100; i != 0; --i) { - IntsRef data = newIntsRef(values); - encoder.encode(data, bytes); - } - // ----------------------------------------------------------- - - long encodeTime = 0; - for (int factor = loopFactor; factor > 0; --factor) { - IntsRef data = newIntsRef(values); - long start = System.currentTimeMillis(); - encoder.encode(data, bytes); - encodeTime += System.currentTimeMillis() - start; - } - - IntsRef decoded = new IntsRef(values.length); - int encodedSize = bytes.length; - IntDecoder decoder = encoder.createMatchingDecoder(); - - // -- Looping 100 times as a warm up -------------------------- - for (int i = 100; i != 0; --i) { - decoder.decode(bytes, decoded); - } - // ----------------------------------------------------------- - - long decodeTime = 0; - for (int i = loopFactor; i > 0; --i) { - long start = System.currentTimeMillis(); - decoder.decode(bytes, decoded); - decodeTime += System.currentTimeMillis() - start; - } - - if (decoded.length != values.length) { - throw new RuntimeException("wrong num values. expected=" + values.length + " actual=" + decoded.length + - " decoder=" + decoder); - } - - System.out.println(String.format(Locale.ROOT, resultsFormat, encoder, - nf.format(encodedSize * 8.0 / values.length), - encodeTime, - nf.format(encodeTime * 1000000.0 / (loopFactor * values.length)), - decodeTime, - nf.format(decodeTime * 1000000.0 / (loopFactor * values.length)))); - } - - static { - nf = NumberFormat.getInstance(Locale.ROOT); - nf.setMaximumFractionDigits(4); - nf.setMinimumFractionDigits(4); - - data9910 = new int[] { 2, 4, 149085, 11, 12292, 69060, 69061, 149309, - 99090, 568, 5395, 149310, 3911, 149311, 149312, 148752, 1408, - 1410, 1411, 1412, 4807, 1413, 1414, 1417, 1415, 1416, 1418, - 1420, 470, 4808, 1422, 1423, 1424, 4809, 4810, 1427, 1429, - 1430, 4811, 1432, 1433, 3752, 1435, 3753, 1437, 1439, 1440, - 4812, 1442, 1443, 4813, 1445, 1446, 1447, 4814, 4815, 1450, - 4816, 353, 1452, 89004, 1624, 1625, 2052, 1626, 1627, 63991, - 725, 726, 727, 728, 35543, 729, 730, 731, 1633, 733, 734, 735, - 37954, 737, 738, 76315, 23068, 76316, 1634, 740, 741, 742, 744, - 745, 76317, 15645, 748, 17488, 2904, 89005, 752, 753, 89006, - 754, 755, 756, 757, 41, 261, 758, 89007, 760, 762, 763, 89008, - 764, 765, 766, 85930, 165, 768, 149313, 33593, 149314, 149315, - 81589, 39456, 15467, 1296, 149316, 39457, 2235, 144, 2236, - 2309, 3050, 2237, 2311, 89692, 2240, 2241, 2243, 2244, 2245, - 2246, 2314, 12856, 2248, 2250, 2251, 2253, 2254, 12857, 7677, - 12858, 39149, 2257, 23147, 3303, 2258, 7422, 2322, 2262, 2317, - 2263, 7423, 24264, 2232, 89693, 12862, 89694, 12863, 12864, - 23201, 2329, 33019, 2255, 12865, 3517, 2492, 2277, 2280, 2267, - 2260, 25368, 12866, 2281, 2282, 2283, 12867, 2284, 9055, 2287, - 125133, 2337, 2286, 2288, 2338, 125134, 2290, 125135, 12869, - 965, 966, 1298, 17945, 1300, 970, 971, 972, 973, 974, 296, - 17946, 1303, 1391, 902, 1304, 1395, 1308, 1309, 1310, 1312, - 967, 9414, 1315, 1317, 1318, 9415, 1321, 23592, 1322, 22433, - 1323, 1324, 1326, 109241, 31225, 1330, 1331, 2540, 27196, 1332, - 1334, 1335, 11999, 414, 340, 3651, 44040, 31995, 1344, 1343, - 4618, 116770, 116771, 1474, 1349, 42122, 14199, 149317, 451, - 149318, 29, 14200, 14198, 14201, 1979, 1980, 1981, 3132, 3147, - 34090, 1987, 12770, 1329, 80818, 80819, 1988, 23522, 1986, - 15880, 1985, 32975, 1992, 1993, 7165, 3141, 3143, 86346, 1982, - 1984, 3145, 86347, 78064, 23456, 29578, 3136, 17752, 4710, - 4711, 4712, 149319, 424, 4713, 95735, 4715, 149320, 4717, 4718, - 149321, 192, 149322, 108126, 29976, 5404, 38059, 5406, 2030, - 289, 1804, 1557, 1558, 94080, 29651, 94317, 1561, 1562, 1563, - 1565, 24632, 1927, 1928, 1566, 1570, 1571, 1572, 1573, 1574, - 1575, 94318, 1576, 2674, 9351, 94319, 94320, 2677, 2678, 29654, - 2946, 2945, 2682, 2683, 2947, 3102, 3402, 3104, 4780, 3106, - 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3116, 3117, - 3118, 19610, 44805, 3119, 3407, 3121, 3122, 3124, 3126, 3127, - 41745, 41746, 3130, 459, 460, 461, 462, 463, 464, 466, 467, - 40306, 468, 471, 472, 40307, 4467, 475, 476, 477, 478, 479, - 40308, 481, 482, 20129, 483, 484, 485, 486, 4473, 488, 489, - 458, 491, 40309, 494, 495, 496, 497, 499, 500, 501, 502, 355, - 356, 1549, 358, 359, 360, 37971, 362, 2579, 2581, 24578, 2583, - 24579, 2586, 2587, 2588, 2590, 2591, 24580, 24581, 3666, 24582, - 2594, 24583, 2596, 2597, 24584, 2599, 18013, 24585, 2601, - 49361, 280, 3969, 11651, 11652, 3926, 5103, 11653, 11654, - 11655, 6896, 417, 168, 149323, 11268, 11657, 38089, 59517, - 149324, 38092, 149325, 5110, 38094, 59520, 38096, 38097, 28916, - 59703, 4992, 149326, 32383, 2478, 3985, 2479, 2480, 2481, 2482, - 2483, 2484, 2485, 2486, 24146, 22184, 2488, 2489, 2490, 2494, - 2493, 18043, 2495, 2542, 2497, 5062, 2499, 2501, 24147, 24148, - 2504, 2505, 2506, 2507, 2508, 394, 2660, 2509, 2511, 24149, - 2512, 2513, 2514, 3988, 4410, 3989, 2518, 2522, 2521, 24150, - 12082, 2524, 3990, 24151, 387, 24152, 2529, 2530, 2528, 3991, - 24153, 2534, 24154, 2536, 24155, 2538, 22510, 6332, 3554, 5309, - 7700, 6333, 6334, 6335, 6336, 6337, 5693, 117020, 6339, 149327, - 149328, 149329, 6340, 6343, 117022, 4324, 283, 284, 285, 286, - 2688, 287, 2689, 288, 8880, 290, 291, 2690, 292, 295, 294, - 24543, 13899, 297, 298, 299, 300, 303, 301, 59178, 302, 8881, - 34403, 13900, 17811, 305, 307, 306, 308, 2727, 368, 364, - 110416, 1587, 366, 367, 2692, 26624, 7233, 9082, 35684, 7250, - 13902, 304, 13903, 991, 110417, 273, 274, 275, 276, 277, 278, - 41095, 281, 282, 4419, 2768, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 1065, 239, 2745, 2746, 240, 9250, 241, 242, 244, 245, - 9251, 246, 247, 248, 249, 250, 251, 253, 254, 255, 9252, 257, - 258, 259, 9253, 9254, 2751, 265, 266, 267, 268, 9255, 9256, - 270, 271, 9257, 238, 1024, 829, 1025, 1026, 1028, 1029, 1030, - 9258, 1032, 1033, 1034, 1027, 1035, 1036, 9259, 1037, 1038, - 1039, 4594, 4429, 1041, 1042, 1043, 70332, 1045, 1046, 1047, - 1048, 21128, 1050, 122787, 72433, 1052, 2762, 1054, 1055, 1056, - 9548, 1057, 71311, 1058, 1059, 1060, 61413, 2765, 4436, 1064, - 1066, 11610, 3485, 22357, 104580, 149330, 149331, 15471, 5679, - 5680, 687, 5683, 5684, 953, 8849, 102120, 149332, 5688, 5689, - 149333, 6920, 60202, 33855, 33856, 33857, 19163, 33858, 3491, - 149334, 914, 2202, 916, 917, 919, 920, 921, 922, 3568, 924, - 925, 926, 927, 928, 929, 8752, 931, 932, 933, 934, 3570, 1876, - 9138, 1877, 1878, 2210, 1880, 1881, 3571, 1883, 1884, 2212, - 1886, 2214, 1888, 1889, 1890, 8753, 1891, 1892, 1893, 1894, - 1895, 1896, 1898, 2217, 3572, 1901, 1902, 688, 2219, 107, 1904, - 1905, 3573, 1907, 3323, 1909, 1910, 1911, 8754, 1912, 55911, - 1913, 1914, 3574, 1741, 3575, 1916, 2226, 3576, 1919, 2227, - 1920, 3577, 3578, 2229, 1923, 85396, 174, 175, 114875, 178, - 180, 181, 182, 1477, 185, 186, 172, 187, 188, 85397, 85398, - 190, 191, 891, 893, 19778, 18068, 895, 897, 896, 25985, 894, - 900, 361, 1206, 193, 194, 195, 196, 197, 198, 199, 200, 55009, - 201, 33266, 29064, 204, 205, 40129, 206, 207, 208, 2842, 209, - 210, 211, 212, 149335, 870, 871, 18005, 872, 18006, 874, 875, - 876, 1479, 1480, 1481, 879, 881, 57212, 2779, 57213, 886, 887, - 57214, 57215, 889, 890, 806, 69305, 808, 809, 86327, 812, 813, - 814, 815, 26724, 816, 69307, 43484, 818, 819, 63904, 820, 821, - 822, 86328, 13498, 824, 825, 12218, 149336, 49042, 4464, 4466, - 35536, 73245, 73246, 474, 73247, 480, 46247, 29624, 21086, - 73248, 490, 493, 73249, 73250, 401, 403, 405, 2860, 15483, - 74826, 408, 409, 74827, 410, 411, 413, 74828, 415, 2863, 68707, - 33284, 2865, 2866, 2867, 2868, 2869, 2870, 17976, 3032, 38498, - 7350, 2876, 2874, 24506, 918, 923, 64562, 64563, 32648, 930, - 1875, 32649, 1879, 32650, 1882, 1887, 32651, 64564, 32652, - 1897, 32653, 18170, 1900, 32654, 1906, 1915, 64565, 1921, 1922, - 90662, 2234, 37449, 8886, 37450, 7418, 37451, 37452, 37453, - 37454, 1609, 1610, 1611, 1612, 113456, 1212, 1616, 1617, - 113457, 1615, 1619, 113458, 1620, 8747, 113459, 8748, 42233, - 78065, 42235, 2149, 42236, 78066, 42237, 42238, 4335, 42239, - 78067, 42241, 78068, 42243, 78069, 42244, 78070, 54587, 12993, - 2040, 1130, 1131, 51172, 1133, 1134, 1135, 1136, 1137, 1138, - 1139, 1140, 1141, 149337, 1115, 5178, 149338, 452, 7784, 21522, - 1361, 103718, 149339, 15990, 79432, 149340, 4232, 149341, - 15998, 53917, 15996, 53918, 149342, 149343, 97544, 53920, - 97546, 841, 1954, 842, 41926, 844, 2589, 845, 846, 27370, 848, - 849, 41927, 25165, 852, 1956, 854, 856, 1957, 855, 1959, 35170, - 23055, 75673, 116783, 857, 116784, 851, 116785, 858, 859, 860, - 861, 57422, 1964, 864, 866, 867, 1965, 1966, 1968, 1969, 2989, - 116786, 1972, 1973, 116787, 1975, 1976, 1977, 2580, 39540, - 2585, 39541, 21755, 39542, 2592, 34859, 2593, 39543, 38540, - 2595, 39544, 149344, 35433, 81849, 35434, 40257, 873, 877, - 2778, 32040, 882, 883, 884, 885, 888, 3358, 1559, 1560, 1438, - 25387, 1569, 38135, 66925, 2673, 3095, 2679, 59053, 25443, - 34369, 1983, 17749, 9343, 1989, 13565, 31525, 61690, 18165, - 17751, 78234, 26506, 9348, 20307, 18154, 3133, 2572, 3134, - 12131, 19770, 48724, 25759, 13549, 65465, 19936, 13545, 25645, - 4786, 15756, 19547, 1581, 92226, 1362, 21524, 13059, 23717, - 149345, 20198, 27123, 149346, 149347, 26030, 27126, 27652, - 10538, 1667, 40282, 14134, 40284, 16368, 149348, 40287, 8870, - 40288, 149349, 40289, 149350, 149351, 40295, 10424, 7012, - 13178, 45608, 10423, 13181, 4201, 672, 13182, 10174, 10607, - 13183, 580, 149352, 149353, 96298, 53691, 3721, 66048, 21584, - 149354, 48206, 48207, 149355, 1405, 1406, 1407, 11162, 577, - 149356, 6941, 6942, 16583, 1284, 10511, 16584, 16585, 422, 423, - 1249, 1244, 1245, 1247, 2544, 1248, 1250, 2545, 1252, 2547, - 1253, 2549, 1259, 1257, 1258, 1260, 1261, 2551, 1262, 1263, - 1264, 1265, 2553, 1266, 17795, 2554, 17796, 1270, 1271, 1273, - 17797, 2556, 1275, 1276, 2557, 1277, 1278, 1279, 1280, 1282, - 68, 69, 5080, 5256, 6869, 10148, 6960, 10150, 149357, 10152, - 14413, 149358, 14414, 56037, 651, 56038, 131797, 555, 14415, - 14416, 149359, 149360, 56042, 14418, 149361, 149, 56043, 97512, - 34512, 797, 7396, 9395, 9396, 9397, 63417, 805, 23984, 13665, - 10452, 55147, 5656, 53, 4348, 4349, 4350, 148488, 13669, 6527, - 149362, 11374, 11376, 11377, 8092, 11378, 11380, 152, 5013, - 8093, 561, 11381, 5623, 4176, 26840, 3564, 3565, 3708, 3567, - 18783, 18784, 4039, 10540, 18786, 30100, 30101, 1528, 149363, - 19561, 19562, 19563, 19564, 1110, 134146, 10600, 149364, 10602, - 149365, 149366, 10603, 10604, 4981, 57075, 37508, 149367, - 34589, 1209, 149368, 19592, 19593, 7620, 9674, 3481, 10240, - 81835, 8001, 33872, 8907, 55155, 1585, 31731, 49694, 25760, - 31733, 903, 904, 2539, 49695, 1194, 1195, 1196, 31734, 1197, - 1198, 1199, 1593, 899, 1200, 1201, 9276, 1202, 40181, 40482, - 55718, 80833, 24596, 3669, 15699, 55720, 55721, 40481, 3672, - 39826, 80363, 2602, 2603, 2604, 62126, 2605, 2606, 2607, 8714, - 2608, 2609, 2610, 2612, 149369, 2894, 15241, 15242, 15262, - 5384, 20290, 20291, 7792, 20295, 64413, 39236, 18011, 71494, - 898, 51015, 19782, 105107, 149370, 7634, 149371, 149372, - 115458, 22821, 19894, 2213, 66926 }; - - data3630 = new int[] { 2, 4, 86133, 11, 16505, 86134, 86135, 86136, - 1290, 86137, 86138, 32473, 19346, 32474, 4922, 32475, 86139, - 16914, 86140, 86141, 86142, 86143, 32478, 86144, 86145, 32480, - 4884, 4887, 32481, 86146, 16572, 86147, 16295, 165, 86148, - 3183, 21920, 21921, 21922, 555, 4006, 32484, 21925, 21926, - 13775, 86149, 13777, 85833, 85834, 13779, 13773, 13780, 75266, - 17674, 13784, 13785, 13786, 13787, 13788, 6258, 86150, 13790, - 75267, 13793, 13794, 13795, 312, 4914, 4915, 6222, 86151, 4845, - 4883, 4918, 4894, 4919, 86152, 4921, 6223, 6224, 6225, 6226, - 67909, 6229, 18170, 6230, 5198, 25625, 6231, 6232, 6233, 1808, - 6234, 6235, 6236, 41376, 6238, 6239, 67911, 6240, 86153, 6243, - 6244, 83549, 6246, 6247, 6248, 6249, 782, 444, 6251, 6250, - 19863, 28963, 310, 2234, 144, 2236, 2309, 69437, 2311, 2325, - 2241, 69438, 69439, 2244, 2245, 2246, 23504, 2314, 69440, - 36603, 2250, 2268, 2271, 2251, 2254, 2255, 2257, 2240, 36604, - 84726, 36605, 84727, 2262, 2263, 18431, 38853, 2317, 2149, - 2326, 2327, 2329, 3980, 2275, 2277, 2258, 84728, 2260, 84729, - 84730, 13766, 36607, 2282, 2283, 84731, 2284, 2286, 2287, 2337, - 7424, 2288, 2338, 3522, 2290, 84733, 32902, 371, 37708, 2096, - 3065, 3066, 375, 377, 374, 378, 2100, 86154, 381, 382, 58795, - 379, 383, 384, 385, 4449, 387, 388, 389, 390, 9052, 391, 18358, - 2107, 394, 2111, 2108, 393, 2109, 395, 86155, 86156, 397, 2113, - 398, 399, 400, 273, 274, 275, 40980, 276, 277, 31716, 279, 280, - 31717, 281, 282, 1628, 1623, 1624, 1625, 2052, 1626, 725, 727, - 728, 729, 730, 731, 1633, 733, 734, 735, 86157, 737, 738, 739, - 1634, 3563, 3564, 3565, 1667, 12461, 76276, 3567, 5413, 77622, - 5415, 5416, 5417, 5418, 107, 86158, 7784, 15363, 153, 3723, - 2713, 7786, 3835, 7787, 86159, 7789, 7791, 7792, 7794, 86160, - 7796, 86161, 6708, 7798, 7799, 7800, 7801, 7802, 7803, 1665, - 43150, 15365, 1581, 5656, 43152, 80258, 7450, 39922, 86162, - 51587, 9059, 4606, 396, 86163, 86164, 7250, 401, 403, 2860, - 33281, 2964, 408, 9119, 409, 86165, 7669, 2861, 410, 413, - 86166, 414, 415, 33282, 405, 33283, 7498, 2865, 7230, 33284, - 2866, 86167, 2867, 47518, 2868, 86168, 2869, 2870, 4712, 7096, - 28484, 6913, 6914, 6915, 6916, 37169, 37170, 7103, 28269, 6919, - 86169, 45431, 6922, 7104, 6923, 7108, 6924, 6925, 6926, 6927, - 6928, 86170, 86171, 86172, 6930, 6931, 6932, 6934, 6935, 6936, - 451, 6937, 6938, 4756, 3554, 5309, 8145, 3586, 16417, 9767, - 14126, 25854, 6580, 10174, 86173, 5519, 21309, 8561, 20938, - 10386, 86174, 781, 2030, 16419, 30323, 16420, 16421, 16424, - 86175, 86176, 86177, 28871, 86178, 28872, 63980, 6329, 49561, - 4271, 38778, 86179, 86180, 20126, 16245, 193, 195, 196, 197, - 56973, 199, 200, 201, 202, 203, 204, 56974, 56975, 205, 206, - 4662, 207, 208, 209, 210, 211, 212, 47901, 641, 642, 643, 1380, - 1079, 47902, 1381, 1081, 1082, 1083, 47903, 1382, 47904, 1087, - 47905, 965, 966, 1298, 968, 1387, 1300, 50288, 971, 972, 973, - 974, 23974, 22183, 1390, 23313, 1389, 1391, 902, 23029, 296, - 1304, 1395, 1303, 1309, 1308, 50289, 1312, 50290, 50291, 1315, - 1317, 9270, 19796, 3605, 1320, 1321, 44946, 1322, 1323, 50292, - 967, 1587, 1326, 1331, 17482, 633, 29115, 53858, 29118, 29119, - 62624, 44494, 6965, 6966, 6959, 6967, 71562, 6969, 23459, - 23460, 17464, 4225, 23461, 23462, 23463, 5893, 23464, 17467, - 17468, 23465, 12562, 1405, 1406, 1407, 960, 961, 962, 687, 963, - 86181, 86182, 5997, 10812, 11976, 11977, 1850, 577, 13393, - 10810, 13394, 65040, 86183, 3935, 3936, 3937, 710, 86184, 5785, - 5786, 29949, 5787, 5788, 283, 284, 2687, 285, 286, 287, 2689, - 288, 289, 8880, 290, 2690, 13899, 991, 292, 295, 42007, 35616, - 63103, 298, 299, 3520, 297, 9024, 303, 301, 302, 300, 31345, - 3719, 304, 305, 306, 307, 308, 368, 364, 85002, 9026, 63105, - 367, 39596, 25835, 19746, 293, 294, 26505, 85003, 18377, 56785, - 10122, 10123, 10124, 86185, 39863, 86186, 10125, 39865, 4066, - 4067, 24257, 4068, 4070, 86187, 4073, 4074, 86188, 4076, 7538, - 4077, 86189, 4078, 4079, 7540, 7541, 4084, 4085, 7542, 86190, - 4086, 86191, 4087, 4088, 86192, 7545, 44874, 7821, 44875, - 86193, 4286, 86194, 51470, 17609, 1408, 47486, 1411, 1412, - 47487, 1413, 1414, 1417, 1415, 47488, 1416, 1418, 1420, 470, - 1422, 1423, 1424, 5001, 5002, 47489, 1427, 1429, 1430, 31811, - 1432, 1433, 47490, 1435, 3753, 1437, 1439, 1440, 47491, 1443, - 47492, 1446, 5004, 5005, 1450, 47493, 353, 1452, 42145, 3103, - 3402, 3104, 3105, 4780, 3106, 3107, 3108, 12157, 3111, 42146, - 42147, 3114, 4782, 42148, 3116, 3117, 42149, 42150, 3407, 3121, - 3122, 18154, 3126, 3127, 3128, 3410, 3130, 3411, 3412, 3415, - 24241, 3417, 3418, 3449, 42151, 3421, 3422, 7587, 42152, 3424, - 3427, 3428, 3448, 3430, 3432, 42153, 42154, 41648, 1991, 407, - 57234, 411, 2862, 57235, 2863, 18368, 57236, 2874, 7350, 4115, - 2876, 2877, 17975, 86195, 4116, 2881, 2882, 2883, 2886, 463, - 870, 872, 873, 874, 875, 8783, 8784, 877, 1480, 1481, 459, - 2778, 881, 8785, 2779, 8786, 8787, 8788, 886, 887, 8789, 889, - 8790, 86196, 6920, 86197, 5080, 5081, 7395, 7396, 9395, 9396, - 1528, 42737, 805, 86198, 1209, 13595, 4126, 9680, 34368, 9682, - 86199, 86200, 174, 175, 176, 177, 178, 179, 180, 182, 183, - 1477, 31138, 186, 172, 187, 188, 189, 190, 191, 458, 871, - 31294, 31295, 27604, 31296, 31297, 882, 883, 884, 31298, 890, - 1089, 1488, 1489, 1092, 1093, 1094, 1095, 1096, 1097, 1490, - 1098, 1495, 1502, 1099, 1100, 1101, 1493, 2997, 12223, 1103, - 2654, 1498, 1499, 1500, 80615, 80616, 80617, 33359, 86201, - 9294, 1501, 86202, 1506, 1507, 23454, 38802, 38803, 1014, - 86203, 5583, 5584, 651, 74717, 5586, 5587, 5588, 5589, 74720, - 5590, 38808, 33527, 78330, 10930, 5119, 10931, 1000, 10928, - 10932, 10933, 10934, 10935, 5863, 10936, 86204, 10938, 10939, - 86205, 192, 194, 38754, 38755, 198, 38756, 38757, 38758, 2842, - 640, 22780, 22781, 1080, 86206, 86207, 1084, 1086, 1088, 63916, - 9412, 970, 9413, 9414, 9415, 9416, 9417, 1310, 7168, 7169, - 1318, 9418, 1324, 39159, 1804, 1557, 24850, 41499, 1560, 41500, - 1562, 1563, 1565, 1927, 1928, 1566, 1569, 1570, 1571, 1572, - 1573, 1574, 1575, 1576, 2674, 2677, 2678, 2679, 2946, 2682, - 2676, 2683, 2947, 1156, 1157, 1158, 1467, 1160, 1468, 1469, - 1161, 1162, 1163, 4369, 1165, 1166, 1167, 12923, 2917, 1169, - 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 18153, 8359, - 1178, 1164, 1191, 1180, 12924, 86208, 86209, 54817, 66962, - 2476, 86210, 86211, 41820, 41821, 41822, 41824, 1130, 1131, - 1132, 32692, 1134, 34848, 1136, 1133, 1137, 1138, 1139, 1140, - 1141, 1143, 1144, 1145, 34849, 2639, 34850, 1146, 1147, 1148, - 34851, 1150, 1151, 1152, 1153, 1154, 1155, 1678, 1679, 1680, - 1681, 40870, 2059, 1685, 1686, 32686, 14970, 1688, 1689, 86212, - 1692, 1682, 1693, 1695, 1696, 1698, 12955, 8909, 41690, 1700, - 41691, 86213, 30949, 41692, 1703, 1704, 1705, 41693, 14976, - 1708, 2071, 1709, 1710, 1711, 1712, 1727, 86214, 86215, 86216, - 1715, 86217, 1714, 1717, 1690, 41697, 86218, 1720, 86219, 2073, - 41699, 1724, 2075, 1726, 1729, 1730, 1732, 2078, 2223, 1735, - 1713, 41700, 1737, 14977, 1739, 1740, 1741, 2080, 1743, 1744, - 1745, 1746, 1747, 1748, 1749, 1750, 1751, 41701, 1752, 1753, - 1909, 86220, 2085, 1754, 19548, 86221, 19551, 5733, 3856, 5190, - 4581, 25145, 86222, 86223, 4846, 86224, 4861, 86225, 86226, - 86227, 25150, 86228, 86229, 13820, 2027, 4898, 4899, 4901, - 2135, 4902, 4868, 4904, 86230, 4905, 25155, 4907, 86231, 4909, - 4910, 4911, 4912, 86232, 6220, 81357, 86233, 2589, 73877, - 29706, 6227, 6228, 86234, 6237, 86235, 6241, 6242, 1812, 13808, - 13809, 70908, 2293, 2294, 86236, 2295, 2296, 2297, 22947, - 16511, 2299, 2300, 2301, 13097, 73079, 86237, 13099, 50121, - 86238, 86239, 13101, 86240, 2424, 4725, 4726, 4727, 4728, 4729, - 4730, 86241, 26881, 10944, 4734, 4735, 4736, 26239, 26240, - 71408, 86242, 57401, 71410, 26244, 5344, 26245, 86243, 4102, - 71414, 11091, 6736, 86244, 6737, 6738, 38152, 6740, 6741, 6742, - 6298, 6743, 6745, 6746, 20867, 6749, 20616, 86245, 9801, 65297, - 20617, 65298, 20619, 5629, 65299, 20621, 20622, 8385, 20623, - 20624, 5191, 20625, 20626, 442, 443, 445, 27837, 77681, 86246, - 27839, 86247, 86248, 41435, 66511, 2478, 2479, 2480, 2481, - 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2494, - 2493, 33025, 12084, 2542, 2497, 2499, 2501, 2503, 2504, 2505, - 33026, 2506, 2507, 2508, 2509, 2511, 1787, 12080, 2513, 2514, - 3988, 3176, 3989, 2518, 2521, 9285, 2522, 2524, 2525, 3990, - 2527, 2528, 27499, 2529, 2530, 3991, 2532, 2534, 2535, 18038, - 2536, 2538, 2495, 46077, 61493, 61494, 1006, 713, 4971, 4972, - 4973, 4975, 4976, 650, 170, 7549, 7550, 7551, 7552, 7553, - 86249, 7936, 956, 11169, 11170, 1249, 1244, 1245, 1247, 2544, - 1250, 2545, 1252, 2547, 1253, 1254, 2549, 39636, 1259, 1257, - 1258, 39637, 1260, 1261, 2551, 1262, 1263, 848, 86250, 86251, - 854, 74596, 856, 1957, 86252, 855, 1959, 1961, 857, 86253, 851, - 859, 860, 862, 1964, 864, 865, 866, 867, 1965, 1966, 1967, - 1968, 1969, 86254, 1971, 1972, 1973, 1974, 1975, 1976, 1977, - 841, 1954, 842, 2978, 846, 847, 849, 850, 852, 1956, 17452, - 71941, 86255, 86256, 73665, 1471, 13690, 185, 503, 504, 2342, - 505, 506, 4378, 508, 4379, 17313, 510, 511, 512, 520, 513, - 4384, 17314, 514, 515, 46158, 17317, 518, 34269, 519, 4386, - 523, 524, 525, 46159, 528, 529, 17319, 531, 532, 533, 534, 535, - 7482, 537, 538, 5267, 536, 539, 541, 540, 19858, 17320, 17321, - 906, 907, 908, 17322, 910, 17323, 912, 15850, 913, 4398, 17324, - 86257, 278, 2948, 2949, 2950, 3007, 2951, 2952, 2953, 2954, - 2955, 3013, 35352, 3014, 3015, 2962, 3016, 33505, 39118, 3017, - 3018, 20492, 4000, 3021, 3022, 35353, 39293, 3024, 18443, 3029, - 9467, 20529, 39119, 8380, 2965, 3030, 3043, 22714, 39120, 2956, - 3035, 39121, 3037, 3038, 2688, 86258, 36675, 30894, 24505, - 8888, 13541, 49728, 27660, 9082, 27661, 365, 366, 2232, 76098, - 7233, 1494, 17391, 606, 607, 611, 610, 612, 614, 615, 613, 616, - 9117, 617, 618, 21155, 1789, 619, 620, 7636, 12019, 621, 622, - 1793, 623, 625, 624, 631, 626, 627, 21578, 21103, 628, 21579, - 629, 9122, 9123, 12189, 9289, 3168, 3169, 630, 632, 634, 21580, - 9121, 635, 636, 637, 21581, 12781, 1801, 638, 639, 1559, 24343, - 9419, 9420, 795, 796, 1611, 86259, 1612, 21551, 21552, 3741, - 1617, 3742, 1615, 1619, 1620, 6301, 3744, 1622, 67685, 8521, - 55937, 9025, 27663, 8881, 13581, 86260, 11592, 44720, 86261, - 63231, 50873, 42925, 52332, 86262, 72706, 17705, 17707, 17708, - 3401, 40217, 1248, 40218, 86263, 7098, 86264, 86265, 1264, - 86266, 1266, 1267, 1268, 1269, 86267, 1271, 1272, 1273, 1274, - 2556, 1275, 1276, 1277, 1278, 1279, 1280, 1282, 1283, 22680, - 11889, 86268, 45662, 7038, 86269, 19315, 45663, 45664, 86270, - 5855, 34002, 49245, 10447, 5663, 86271, 15429, 53877, 49249, - 86272, 86273, 86274, 60128, 60453, 60129, 5552, 31923, 43407, - 4287, 17980, 64977, 86275, 86276, 8234, 86277, 3649, 8240, - 1330, 11999, 1332, 27618, 1334, 1335, 340, 3651, 25640, 18165, - 1343, 4618, 1474, 3653, 75921, 1349, 53519, 1779, 45454, 22778, - 40153, 67677, 63826, 45455, 15128, 67678, 67679, 1792, 67680, - 3171, 47816, 45457, 9288, 59891, 67681, 25703, 35731, 35732, - 369, 35713, 35714, 35715, 34652, 35716, 31681, 35717, 12779, - 35718, 35719, 11992, 806, 807, 808, 43499, 43500, 810, 776, - 812, 813, 814, 241, 43501, 43502, 816, 755, 43503, 818, 819, - 820, 43504, 821, 822, 823, 824, 825, 826, 43505, 43506, 43507, - 828, 829, 20083, 43508, 43509, 832, 833, 834, 835, 86278, - 19984, 19985, 86279, 24125, 19986, 86280, 19988, 86281, 5414, - 86282, 85808, 5479, 5420, 5421, 5422, 5423, 63800, 86283, - 86284, 30965, 86285, 416, 1510, 5740, 5741, 81991, 86286, - 28938, 50149, 1003, 55512, 14306, 6960, 688, 86287, 14307, - 5399, 5400, 17783, 24118, 720, 86288, 44913, 24557, 667, 24876, - 6529, 24877, 24878, 24879, 24880, 31847, 20671, 4011, 171, 580, - 86289, 3863, 914, 2202, 916, 917, 918, 919, 921, 922, 923, - 7585, 925, 7586, 926, 927, 928, 7588, 929, 930, 931, 932, 933, - 934, 1875, 1876, 7589, 7590, 1878, 1879, 7591, 7592, 1882, - 1883, 1884, 2212, 7593, 1887, 1888, 1889, 1890, 1891, 1892, - 1893, 1894, 1895, 1896, 1897, 1898, 2217, 1900, 7594, 1902, - 2219, 7595, 1905, 1906, 1907, 3323, 7596, 1911, 1912, 7597, - 1914, 1915, 1916, 2226, 1919, 7598, 2227, 1920, 1921, 7599, - 7600, 4708, 1923, 355, 356, 1549, 358, 32077, 360, 32078, - 21117, 362, 19043, 71677, 5716, 86290, 49790, 86291, 86292, - 86293, 49792, 86294, 86295, 49794, 86296, 86297, 86298, 86299, - 11882, 86300, 49798, 86301, 49800, 49801, 49802, 49803, 453, - 49804, 8591, 6794, 49806, 18989, 49807, 49808, 16308, 49809, - 86302, 86303, 10105, 86304, 5285, 10106, 10107, 6557, 86305, - 23571, 10109, 38883, 10110, 5401, 86306, 67557, 16430, 67558, - 40171, 16433, 25878, 86307, 21762, 23, 86308, 86309, 21766, - 86310, 86311, 5149, 3926, 21768, 21769, 47826, 942, 46985, - 6588, 58867, 6589, 6590, 86312, 6592, 6006, 53855, 9565, 359, - 86313, 2845, 876, 879, 27556, 27557, 885, 27558, 888, 2847, - 27559, 2115, 2116, 2117, 53962, 57839, 315, 316, 317, 318, 319, - 86314, 321, 322, 2122, 323, 2123, 324, 325, 328, 326, 327, - 40542, 329, 330, 18079, 18080, 331, 1790, 7382, 332, 7380, - 7236, 23413, 23414, 18924, 18925, 333, 335, 336, 39750, 337, - 86315, 339, 341, 342, 343, 16264, 16265, 6615, 86316, 86317, - 86318, 86319, 16269, 10538, 33226, 86320, 16272, 5824, 16273, - 16274, 16276, 16277, 16278, 16279, 16280, 14517, 1547, 6463, - 3394, 49677, 659, 10380, 30013, 10382, 10378, 10379, 10383, - 10384, 10385, 86321, 4139, 13370, 13371, 86322, 86323, 11878, - 64509, 15141, 15142, 15143, 32737, 14183, 15144, 39101, 42768, - 5645, 32738, 801, 803, 804, 86324, 14707, 86325, 6601, 12402, - 712, 12403, 2936, 1447, 15477, 1410, 44872, 1550, 8614, 15478, - 15479, 15480, 15481, 4811, 3752, 1442, 15482, 8818, 1445, 5006, - 16304, 32277, 16305, 16306, 86326, 16307, 53691, 69305, 809, - 86327, 815, 26724, 69307, 43484, 63904, 86328, 13498, 827, - 86329, 831, 2857, 836, 86330, 86331, 837, 838, 839, 840, 228, - 229, 43722, 230, 231, 43723, 234, 235, 236, 237, 238, 239, - 2745, 2746, 240, 242, 243, 244, 43724, 19788, 246, 247, 21134, - 248, 250, 251, 252, 253, 254, 255, 256, 257, 258, 43725, 43726, - 41, 43727, 262, 43728, 2751, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 43729, 1035, 43730, 1037, 21821, 2926, 14388, - 10432, 14389, 14390, 14391, 14392, 86332, 14394, 14395, 2035, - 2169, 86333, 14397, 14398, 14399, 14400, 52, 14401, 14402, - 7077, 21822, 14405, 14406, 14396, 86334, 17356, 17357, 84679, - 84680, 76383, 17360, 17361, 86335, 38801, 2060, 30850, 12963, - 1684, 1687, 2061, 14978, 1694, 43387, 1697, 1699, 2067, 1701, - 1702, 1706, 43388, 43389, 76325, 1716, 1718, 26832, 1719, 1723, - 2081, 2063, 1728, 39059, 76326, 1731, 86336, 1736, 76327, 1738, - 19657, 6579, 6581, 6582, 6583, 6584, 6585, 29979, 1818, 28239, - 68, 69, 3391, 86337, 10266, 63528, 86338, 10269, 10270, 10271, - 10272, 86339, 86340, 63530, 63531, 63532, 63533, 10273, 63534, - 86341, 10681, 10682, 86342, 9673, 86343, 10683, 460, 461, 462, - 467, 4464, 4466, 3729, 471, 472, 468, 81634, 474, 81635, 475, - 476, 477, 479, 480, 81636, 81637, 482, 17442, 81638, 81639, - 484, 485, 486, 4473, 488, 489, 490, 493, 466, 494, 495, 496, - 497, 499, 500, 501, 502, 34376, 86344, 63836, 56281, 1707, - 20416, 61452, 56282, 1755, 56283, 56284, 18508, 53650, 63444, - 86345, 3579, 63445, 3677, 1979, 1980, 1981, 3132, 3147, 34090, - 1987, 12770, 1329, 80818, 80819, 1988, 23522, 1986, 15880, - 1985, 32975, 1992, 1993, 7165, 3141, 3143, 86346, 1982, 1984, - 3145, 86347, 78064, 55453, 2656, 2657, 35634, 35635, 2167, - 43479 }; - - data10k = new int[] { 2, 4, 149900, 11, 70236, 149901, 149902, 6721, - 149929, 29212, 34600, 149930, 149931, 149932, 141696, 149908, - 149909, 149910 }; - - data501871 = new int[] { 1368366, 1368367, 1817408, 11, 2513, 1817409, - 1817410, 1817411, 1382349, 126700, 1817412, 5539, 21862, 21863, - 21864, 1233, 1127, 121, 15254, 15255, 357, 449, 15256, 8817, - 15257, 15258, 1406, 1096, 281, 4826, 4827, 223, 166, 2372, 168, - 169, 2219, 170, 171, 1176, 172, 173, 2222, 3035, 177, 178, 179, - 180, 181, 183, 3036, 2378, 1157, 1158, 2380, 1160, 1161, 1162, - 2384, 1164, 1165, 1166, 1167, 1168, 2385, 3037, 1171, 1172, - 1173, 2238, 1175, 1177, 1178, 1179, 1180, 1181, 2243, 3038, - 1182, 2244, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, - 59766, 471, 7349, 3599, 2847, 59767, 59768, 59769, 59770, - 59771, 59772, 59773, 59774, 59775, 2625, 852, 853, 2632, 854, - 855, 856, 2284, 857, 862, 1031, 859, 860, 861, 866, 1033, 867, - 1035, 868, 870, 2294, 871, 2295, 873, 874, 875, 876, 877, 878, - 879, 66632, 66633, 66634, 66635, 14823, 66636, 66637, 3763, - 77345, 1370, 3764, 3765, 3766, 5666, 3768, 3770, 16892, 3771, - 3772, 3773, 3244, 3246, 3247, 1504, 266, 29250, 24764, 29251, - 689, 12844, 8068, 29252, 38918, 750, 751, 770, 3704, 753, 754, - 765, 755, 3708, 757, 758, 759, 760, 3710, 761, 762, 763, 3712, - 766, 767, 768, 769, 771, 3719, 4380, 3722, 3723, 3725, 4381, - 3727, 3728, 3731, 3732, 764, 4382, 2316, 334, 1637, 4383, 4384, - 4385, 4386, 4387, 184, 185, 1134, 186, 1135, 187, 188, 1138, - 197, 191, 3517, 193, 194, 195, 196, 208, 3519, 198, 9210, 937, - 9211, 9212, 916, 917, 117, 118, 919, 122, 921, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 924, 137, - 138, 139, 140, 141, 588, 928, 142, 143, 144, 929, 146, 147, - 148, 149, 150, 151, 3775, 3776, 3777, 3778, 3780, 3781, 3783, - 3784, 3785, 3796, 4169, 3788, 4170, 3790, 3791, 3793, 3803, - 3794, 3797, 4171, 3799, 3800, 3801, 3802, 3804, 4172, 3806, - 4173, 4174, 3811, 4175, 3813, 3829, 3815, 3816, 3817, 4176, - 4177, 3820, 3821, 3822, 2168, 3039, 2460, 2170, 2459, 2174, - 2175, 2176, 2461, 2462, 2463, 3040, 2466, 2467, 2469, 2468, - 2470, 3041, 2472, 3042, 3043, 3044, 3045, 231, 881, 882, 1219, - 884, 2038, 886, 887, 888, 891, 892, 1221, 894, 895, 1222, 2039, - 899, 1225, 900, 901, 902, 2492, 2494, 2495, 2496, 4052, 2498, - 2502, 2500, 2501, 2503, 2504, 4653, 5514, 18671, 10350, 1122, - 44317, 44318, 44319, 44320, 44321, 44322, 44323, 44324, 7923, - 1422, 10284, 10285, 6146, 9803, 10286, 466, 5998, 696, 3257, - 6043, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 7029, 4405, - 4864, 450, 349, 11214, 3548, 1092, 5728, 7395, 6533, 1123, - 5736, 1115, 6535, 6536, 2739, 2832, 2833, 2834, 2835, 2836, - 23972, 2837, 23973, 2839, 2840, 2691, 1339, 20116, 3219, 8210, - 3170, 3171, 3172, 3173, 2094, 2095, 2096, 2097, 2099, 2100, - 2102, 3174, 2104, 1372, 2105, 2107, 2108, 2109, 2110, 2113, - 2114, 2115, 2117, 2118, 3221, 3222, 2122, 2123, 2124, 4611, - 2125, 2126, 2127, 2128, 2129, 2130, 2131, 575, 576, 2132, 4612, - 2134, 2135, 2136, 4368, 5931, 5932, 5933, 5934, 5935, 5936, - 5937, 5938, 5939, 2902, 4057, 4058, 4059, 4060, 4062, 4063, - 4064, 4654, 4655, 4067, 4068, 4069, 4656, 4657, 4073, 4658, - 4074, 4075, 4659, 4660, 4661, 4076, 4662, 4663, 4664, 4078, - 4079, 4080, 4665, 4082, 4083, 4084, 4666, 4086, 4087, 4088, - 544, 545, 546, 547, 548, 549, 550, 559, 1227, 552, 553, 5035, - 555, 554, 1228, 556, 1229, 557, 558, 560, 561, 562, 563, 564, - 565, 1230, 566, 567, 568, 569, 570, 572, 573, 222, 7461, 2059, - 2060, 2061, 5664, 2062, 7463, 16997, 2065, 2066, 2067, 2068, - 2069, 2070, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 7464, - 2079, 2080, 2081, 7465, 2082, 2083, 2084, 2085, 2086, 2087, - 199, 206, 200, 203, 205, 211, 1140, 3699, 209, 214, 215, 216, - 217, 218, 777, 778, 779, 780, 2298, 781, 782, 783, 784, 785, - 787, 788, 384, 789, 790, 791, 2677, 793, 794, 795, 796, 797, - 2307, 798, 799, 801, 802, 3645, 803, 4337, 805, 3648, 3649, - 807, 808, 3651, 810, 812, 813, 814, 815, 816, 3654, 818, 819, - 13780, 930, 932, 4221, 935, 936, 938, 2197, 939, 940, 941, - 2200, 943, 1591, 1952, 2630, 1592, 2631, 1602, 1607, 1595, - 1596, 1597, 1598, 1599, 1955, 1601, 1603, 1956, 1605, 1606, - 1608, 1610, 1638, 20608, 968, 969, 970, 971, 972, 973, 974, - 975, 2729, 2730, 977, 2731, 979, 980, 981, 982, 983, 984, 3506, - 987, 989, 990, 991, 2732, 2733, 6051, 6053, 6055, 910, 6056, - 4339, 4340, 577, 4341, 579, 580, 581, 616, 584, 585, 586, 4342, - 4343, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 5046, - 599, 600, 5047, 601, 602, 603, 604, 605, 5053, 608, 609, 610, - 5055, 612, 613, 5056, 615, 617, 618, 619, 620, 621, 622, 623, - 624, 6882, 627, 628, 629, 630, 631, 5330, 633, 634, 635, 636, - 637, 639, 640, 7870, 632, 34480, 13118, 903, 904, 905, 907, - 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2643, - 1685, 1686, 1687, 1688, 1690, 1691, 2644, 2645, 1695, 2646, - 1699, 2647, 2648, 1702, 2649, 2650, 1706, 22082, 5516, 4307, - 2203, 1995, 1996, 1998, 1999, 2206, 2002, 2003, 4407, 2005, - 4408, 2007, 2008, 2009, 2010, 2011, 4409, 2013, 2014, 2015, - 2017, 3227, 3149, 6025, 22913, 22914, 3228, 7925, 10123, 10124, - 10125, 10127, 16978, 14094, 1593, 4869, 4870, 3477, 3844, 3845, - 9923, 3846, 3847, 39767, 39768, 39769, 3541, 39770, 39771, - 14179, 39772, 39773, 39774, 42558, 1043, 4203, 42559, 42560, - 42561, 42562, 42563, 42564, 11018, 42565, 42566, 4589, 4590, - 4591, 4312, 18283, 4317, 4318, 4319, 12659, 11706, 11707, - 53395, 53396, 29410, 8040, 8041, 915, 20105, 22952, 22953, - 20596, 4161, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, - 3055, 1474, 3056, 3057, 3058, 3059, 3060, 3061, 2549, 2551, - 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 515, 3070, - 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, - 3081, 3082, 506, 3083, 3084, 3085, 3086, 3087, 3088, 3089, - 3090, 3091, 527, 528, 2995, 530, 531, 533, 534, 535, 537, 538 }; - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingTest.java b/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingTest.java deleted file mode 100644 index 77521f83561..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/encoding/EncodingTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.apache.lucene.facet.encoding; - -import java.io.IOException; -import java.util.Arrays; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.encoding.DGapIntEncoder; -import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder; -import org.apache.lucene.facet.encoding.EightFlagsIntEncoder; -import org.apache.lucene.facet.encoding.FourFlagsIntEncoder; -import org.apache.lucene.facet.encoding.IntDecoder; -import org.apache.lucene.facet.encoding.IntEncoder; -import org.apache.lucene.facet.encoding.NOnesIntEncoder; -import org.apache.lucene.facet.encoding.SimpleIntEncoder; -import org.apache.lucene.facet.encoding.SortingIntEncoder; -import org.apache.lucene.facet.encoding.UniqueValuesIntEncoder; -import org.apache.lucene.facet.encoding.VInt8IntEncoder; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IntsRef; -import org.junit.BeforeClass; -import org.junit.Test; - -/* - * 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. - */ - -public class EncodingTest extends FacetTestCase { - - private static IntsRef uniqueSortedData, data; - - @BeforeClass - public static void beforeClassEncodingTest() throws Exception { - int capacity = atLeast(10000); - data = new IntsRef(capacity); - for (int i = 0; i < 10; i++) { - data.ints[i] = i + 1; // small values - } - for (int i = 10; i < data.ints.length; i++) { - data.ints[i] = random().nextInt(Integer.MAX_VALUE - 1) + 1; // some encoders don't allow 0 - } - data.length = data.ints.length; - - uniqueSortedData = IntsRef.deepCopyOf(data); - Arrays.sort(uniqueSortedData.ints); - uniqueSortedData.length = 0; - int prev = -1; - for (int i = 0; i < uniqueSortedData.ints.length; i++) { - if (uniqueSortedData.ints[i] != prev) { - uniqueSortedData.ints[uniqueSortedData.length++] = uniqueSortedData.ints[i]; - prev = uniqueSortedData.ints[i]; - } - } - } - - private static void encoderTest(IntEncoder encoder, IntsRef data, IntsRef expected) throws IOException { - // ensure toString is implemented - String toString = encoder.toString(); - assertFalse(toString.startsWith(encoder.getClass().getName() + "@")); - IntDecoder decoder = encoder.createMatchingDecoder(); - toString = decoder.toString(); - assertFalse(toString.startsWith(decoder.getClass().getName() + "@")); - - BytesRef bytes = new BytesRef(100); // some initial capacity - encoders should grow the byte[] - IntsRef values = new IntsRef(100); // some initial capacity - decoders should grow the int[] - for (int i = 0; i < 2; i++) { - // run 2 iterations to catch encoders/decoders which don't reset properly - encoding(encoder, data, bytes); - decoding(bytes, values, encoder.createMatchingDecoder()); - assertTrue(expected.intsEquals(values)); - } - } - - private static void encoding(IntEncoder encoder, IntsRef data, BytesRef bytes) throws IOException { - final IntsRef values; - if (random().nextBoolean()) { // randomly set the offset - values = new IntsRef(data.length + 1); - System.arraycopy(data.ints, 0, values.ints, 1, data.length); - values.offset = 1; // ints start at index 1 - values.length = data.length; - } else { - // need to copy the array because it may be modified by encoders (e.g. sorting) - values = IntsRef.deepCopyOf(data); - } - encoder.encode(values, bytes); - } - - private static void decoding(BytesRef bytes, IntsRef values, IntDecoder decoder) throws IOException { - int offset = 0; - if (random().nextBoolean()) { // randomly set the offset and length to other than 0,0 - bytes.grow(bytes.length + 1); // ensure that we have enough capacity to shift values by 1 - bytes.offset = 1; // bytes start at index 1 (must do that after grow) - System.arraycopy(bytes.bytes, 0, bytes.bytes, 1, bytes.length); - offset = 1; - } - decoder.decode(bytes, values); - assertEquals(offset, bytes.offset); // decoders should not mess with offsets - } - - @Test - public void testVInt8() throws Exception { - encoderTest(new VInt8IntEncoder(), data, data); - - // cover negative numbers; - BytesRef bytes = new BytesRef(5); - IntEncoder enc = new VInt8IntEncoder(); - IntsRef values = new IntsRef(1); - values.ints[values.length++] = -1; - enc.encode(values, bytes); - - IntDecoder dec = enc.createMatchingDecoder(); - values.length = 0; - dec.decode(bytes, values); - assertEquals(1, values.length); - assertEquals(-1, values.ints[0]); - } - - @Test - public void testSimpleInt() throws Exception { - encoderTest(new SimpleIntEncoder(), data, data); - } - - @Test - public void testSortingUniqueValues() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new VInt8IntEncoder())), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGap() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new VInt8IntEncoder()))), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGapEightFlags() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new EightFlagsIntEncoder()))), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGapFourFlags() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new FourFlagsIntEncoder()))), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGapNOnes4() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(4)))), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGapNOnes3() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapIntEncoder(new NOnesIntEncoder(3)))), data, uniqueSortedData); - } - - @Test - public void testSortingUniqueDGapVInt() throws Exception { - encoderTest(new SortingIntEncoder(new UniqueValuesIntEncoder(new DGapVInt8IntEncoder())), data, uniqueSortedData); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/old/AdaptiveAccumulatorTest.java b/lucene/facet/src/test/org/apache/lucene/facet/old/AdaptiveAccumulatorTest.java deleted file mode 100644 index 299191bce6a..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/old/AdaptiveAccumulatorTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apache.lucene.facet.old; - -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.sampling.BaseSampleTestTopK; -import org.apache.lucene.facet.sampling.Sampler; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.util.LuceneTestCase.Slow; - -/* - * 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. - */ - -@Slow -public class AdaptiveAccumulatorTest extends BaseSampleTestTopK { - - @Override - protected OldFacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader, - IndexReader indexReader, FacetSearchParams searchParams) { - AdaptiveFacetsAccumulator res = new AdaptiveFacetsAccumulator(searchParams, indexReader, taxoReader); - res.setSampler(sampler); - return res; - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/old/TestScoredDocIDsUtils.java b/lucene/facet/src/test/org/apache/lucene/facet/old/TestScoredDocIDsUtils.java deleted file mode 100644 index 52cecade24c..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/old/TestScoredDocIDsUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.apache.lucene.facet.old; - -import java.io.IOException; -import java.util.Random; - -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.analysis.MockTokenizer; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.FieldType; -import org.apache.lucene.document.StringField; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.DocIdSet; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.FixedBitSet; -import org.junit.Test; - -/* - * 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. - */ - -public class TestScoredDocIDsUtils extends FacetTestCase { - - @Test - public void testComplementIterator() throws Exception { - final int n = atLeast(10000); - final FixedBitSet bits = new FixedBitSet(n); - Random random = random(); - for (int i = 0; i < n; i++) { - int idx = random.nextInt(n); - bits.flip(idx, idx + 1); - } - - FixedBitSet verify = bits.clone(); - - ScoredDocIDs scoredDocIDs = ScoredDocIdsUtils.createScoredDocIds(bits, n); - - Directory dir = newDirectory(); - IndexReader reader = createReaderWithNDocs(random, n, dir); - try { - assertEquals(n - verify.cardinality(), ScoredDocIdsUtils.getComplementSet(scoredDocIDs, reader).size()); - } finally { - reader.close(); - dir.close(); - } - } - - @Test - public void testAllDocs() throws Exception { - int maxDoc = 3; - Directory dir = newDirectory(); - IndexReader reader = createReaderWithNDocs(random(), maxDoc, dir); - try { - ScoredDocIDs all = ScoredDocIdsUtils.createAllDocsScoredDocIDs(reader); - assertEquals("invalid size", maxDoc, all.size()); - ScoredDocIDsIterator iter = all.iterator(); - int doc = 0; - while (iter.next()) { - assertEquals("invalid doc ID: " + iter.getDocID(), doc++, iter.getDocID()); - assertEquals("invalid score: " + iter.getScore(), ScoredDocIDsIterator.DEFAULT_SCORE, iter.getScore(), 0.0f); - } - assertEquals("invalid maxDoc: " + doc, maxDoc, doc); - - DocIdSet docIDs = all.getDocIDs(); - assertTrue("should be cacheable", docIDs.isCacheable()); - DocIdSetIterator docIDsIter = docIDs.iterator(); - assertEquals("nextDoc() hasn't been called yet", -1, docIDsIter.docID()); - assertEquals(0, docIDsIter.nextDoc()); - assertEquals(1, docIDsIter.advance(1)); - // if advance is smaller than current doc, advance to cur+1. - assertEquals(2, docIDsIter.advance(0)); - } finally { - reader.close(); - dir.close(); - } - } - - /** - * Creates an index with n documents, this method is meant for testing purposes ONLY - */ - static IndexReader createReaderWithNDocs(Random random, int nDocs, Directory directory) throws IOException { - return createReaderWithNDocs(random, nDocs, new DocumentFactory(nDocs), directory); - } - - private static class DocumentFactory { - protected final static String field = "content"; - protected final static String delTxt = "delete"; - protected final static String alphaTxt = "alpha"; - - private final static Field deletionMark = new StringField(field, delTxt, Field.Store.NO); - private final static Field alphaContent = new StringField(field, alphaTxt, Field.Store.NO); - - public DocumentFactory(int totalNumDocs) { - } - - public boolean markedDeleted(int docNum) { - return false; - } - - public Document getDoc(int docNum) { - Document doc = new Document(); - if (markedDeleted(docNum)) { - doc.add(deletionMark); - // Add a special field for docs that are marked for deletion. Later we - // assert that those docs are not returned by all-scored-doc-IDs. - FieldType ft = new FieldType(); - ft.setStored(true); - doc.add(new Field("del", Integer.toString(docNum), ft)); - } - - if (haveAlpha(docNum)) { - doc.add(alphaContent); - } - return doc; - } - - public boolean haveAlpha(int docNum) { - return false; - } - } - - static IndexReader createReaderWithNDocs(Random random, int nDocs, DocumentFactory docFactory, Directory dir) throws IOException { - RandomIndexWriter writer = new RandomIndexWriter(random, dir, - newIndexWriterConfig(random, TEST_VERSION_CURRENT, - new MockAnalyzer(random, MockTokenizer.KEYWORD, false))); - for (int docNum = 0; docNum < nDocs; docNum++) { - writer.addDocument(docFactory.getDoc(docNum)); - } - // Delete documents marked for deletion - writer.deleteDocuments(new Term(DocumentFactory.field, DocumentFactory.delTxt)); - writer.close(); - - // Open a fresh read-only reader with the deletions in place - return DirectoryReader.open(dir); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sampling/BaseSampleTestTopK.java b/lucene/facet/src/test/org/apache/lucene/facet/sampling/BaseSampleTestTopK.java deleted file mode 100644 index 85d45489fec..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/sampling/BaseSampleTestTopK.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.util.List; -import java.util.Random; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.BaseTestTopK; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; - -/* - * 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. - */ - -public abstract class BaseSampleTestTopK extends BaseTestTopK { - - /** Number of top results */ - protected static final int K = 2; - - /** since there is a chance that this test would fail even if the code is correct, retry the sampling */ - protected static final int RETRIES = 10; - - @Override - protected FacetSearchParams searchParamsWithRequests(int numResults, FacetIndexingParams fip) { - FacetSearchParams res = super.searchParamsWithRequests(numResults, fip); - for (FacetRequest req : res.facetRequests) { - // randomize the way we aggregate results - if (random().nextBoolean()) { - req.setResultMode(ResultMode.GLOBAL_FLAT); - } else { - req.setResultMode(ResultMode.PER_NODE_IN_TREE); - } - } - return res; - } - - protected abstract OldFacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader, - IndexReader indexReader, FacetSearchParams searchParams); - - /** - * Try out faceted search with sampling enabled and complements either disabled or enforced - * Lots of randomly generated data is being indexed, and later on a "90% docs" faceted search - * is performed. The results are compared to non-sampled ones. - */ - public void testCountUsingSampling() throws Exception { - boolean useRandomSampler = random().nextBoolean(); - for (int partitionSize : partitionSizes) { - try { - // complements return counts for all ordinals, so force ALL_PARENTS indexing - // so that it's easier to compare - FacetIndexingParams fip = getFacetIndexingParams(partitionSize, true); - initIndex(fip); - // Get all of the documents and run the query, then do different - // facet counts and compare to control - Query q = new TermQuery(new Term(CONTENT_FIELD, BETA)); // 90% of the docs - - FacetSearchParams expectedSearchParams = searchParamsWithRequests(K, fip); - FacetsCollector fc = FacetsCollector.create(expectedSearchParams, indexReader, taxoReader); - - searcher.search(q, fc); - - List expectedResults = fc.getFacetResults(); - - FacetSearchParams samplingSearchParams = searchParamsWithRequests(K, fip); - - // try several times in case of failure, because the test has a chance to fail - // if the top K facets are not sufficiently common with the sample set - for (int nTrial = 0; nTrial < RETRIES; nTrial++) { - try { - // complement with sampling! - final Sampler sampler = createSampler(nTrial, useRandomSampler, samplingSearchParams); - - assertSampling(expectedResults, q, sampler, samplingSearchParams, false); - assertSampling(expectedResults, q, sampler, samplingSearchParams, true); - - break; // succeeded - } catch (AssertionError e) { - if (nTrial >= RETRIES - 1) { - throw e; // no more retries allowed, must fail - } - } - } - } finally { - closeAll(); - } - } - } - - private void assertSampling(List expected, Query q, Sampler sampler, FacetSearchParams params, boolean complement) throws Exception { - FacetsCollector samplingFC = samplingCollector(complement, sampler, params); - - searcher.search(q, samplingFC); - List sampledResults = samplingFC.getFacetResults(); - - assertSameResults(expected, sampledResults); - } - - private FacetsCollector samplingCollector(final boolean complement, final Sampler sampler, - FacetSearchParams samplingSearchParams) { - OldFacetsAccumulator sfa = getSamplingAccumulator(sampler, taxoReader, indexReader, samplingSearchParams); - sfa.setComplementThreshold(complement ? OldFacetsAccumulator.FORCE_COMPLEMENT : OldFacetsAccumulator.DISABLE_COMPLEMENT); - return FacetsCollector.create(sfa); - } - - private Sampler createSampler(int nTrial, boolean useRandomSampler, FacetSearchParams sParams) { - SamplingParams samplingParams = new SamplingParams(); - - /* - * Set sampling to Exact fixing with TakmiSampleFixer as it is not easy to - * validate results with amortized results. - */ - samplingParams.setSampleFixer(new TakmiSampleFixer(indexReader, taxoReader, sParams)); - - final double retryFactor = Math.pow(1.01, nTrial); - samplingParams.setOversampleFactor(5.0 * retryFactor); // Oversampling - samplingParams.setSampleRatio(0.8 * retryFactor); - samplingParams.setMinSampleSize((int) (100 * retryFactor)); - samplingParams.setMaxSampleSize((int) (10000 * retryFactor)); - samplingParams.setSamplingThreshold(11000); //force sampling - - Sampler sampler = useRandomSampler ? - new RandomSampler(samplingParams, new Random(random().nextLong())) : - new RepeatableSampler(samplingParams); - return sampler; - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sampling/OversampleWithDepthTest.java b/lucene/facet/src/test/org/apache/lucene/facet/sampling/OversampleWithDepthTest.java deleted file mode 100644 index cd0098d11cf..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/sampling/OversampleWithDepthTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.io.IOException; -import java.util.Collections; - -import org.apache.lucene.document.Document; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.IOUtils; -import org.junit.Test; - -/* - * 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. - */ - -public class OversampleWithDepthTest extends FacetTestCase { - - @Test - public void testCountWithdepthUsingSampling() throws Exception, IOException { - Directory indexDir = newDirectory(); - Directory taxoDir = newDirectory(); - - FacetIndexingParams fip = new FacetIndexingParams(randomCategoryListParams()); - - // index 100 docs, each with one category: ["root", docnum/10, docnum] - // e.g. root/8/87 - index100Docs(indexDir, taxoDir, fip); - - DirectoryReader r = DirectoryReader.open(indexDir); - TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); - - CountFacetRequest facetRequest = new CountFacetRequest(new FacetLabel("root"), 10); - // Setting the depth to '2', should potentially get all categories - facetRequest.setDepth(2); - facetRequest.setResultMode(ResultMode.PER_NODE_IN_TREE); - - FacetSearchParams fsp = new FacetSearchParams(fip, facetRequest); - - // Craft sampling params to enforce sampling - final SamplingParams params = new SamplingParams(); - params.setMinSampleSize(2); - params.setMaxSampleSize(50); - params.setOversampleFactor(5); - params.setSamplingThreshold(60); - params.setSampleRatio(0.1); - - FacetResult res = searchWithFacets(r, tr, fsp, params); - FacetRequest req = res.getFacetRequest(); - assertEquals(facetRequest, req); - - FacetResultNode rootNode = res.getFacetResultNode(); - - // Each node below root should also have sub-results as the requested depth was '2' - for (FacetResultNode node : rootNode.subResults) { - assertTrue("node " + node.label + " should have had children as the requested depth was '2'", node.subResults.size() > 0); - } - - IOUtils.close(r, tr, indexDir, taxoDir); - } - - private void index100Docs(Directory indexDir, Directory taxoDir, FacetIndexingParams fip) throws IOException { - IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, null); - IndexWriter w = new IndexWriter(indexDir, iwc); - TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); - - FacetFields facetFields = new FacetFields(tw, fip); - for (int i = 0; i < 100; i++) { - Document doc = new Document(); - FacetLabel cp = new FacetLabel("root",Integer.toString(i / 10), Integer.toString(i)); - facetFields.addFields(doc, Collections.singletonList(cp)); - w.addDocument(doc); - } - IOUtils.close(tw, w); - } - - /** search reader r*/ - private FacetResult searchWithFacets(IndexReader r, TaxonomyReader tr, FacetSearchParams fsp, - final SamplingParams params) throws IOException { - // a FacetsCollector with a sampling accumulator - Sampler sampler = new RandomSampler(params, random()); - OldFacetsAccumulator sfa = new SamplingAccumulator(sampler, fsp, r, tr); - FacetsCollector fcWithSampling = FacetsCollector.create(sfa); - - IndexSearcher s = newSearcher(r); - s.search(new MatchAllDocsQuery(), fcWithSampling); - - // there's only one expected result, return just it. - return fcWithSampling.getFacetResults().get(0); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplerTest.java b/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplerTest.java deleted file mode 100644 index b0c7f29b1c9..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplerTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.facet.FacetTestBase; -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.junit.After; -import org.junit.Before; - -/* - * 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. - */ - -public class SamplerTest extends FacetTestBase { - - private FacetIndexingParams fip; - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - fip = getFacetIndexingParams(Integer.MAX_VALUE); - initIndex(fip); - } - - @Override - protected int numDocsToIndex() { - return 100; - } - - @Override - protected List getCategories(final int doc) { - return new ArrayList() { - { - add(new FacetLabel("root", "a", Integer.toString(doc % 10))); - } - }; - } - - @Override - protected String getContent(int doc) { - return ""; - } - - @Override - @After - public void tearDown() throws Exception { - closeAll(); - super.tearDown(); - } - - public void testDefaultFixer() throws Exception { - RandomSampler randomSampler = new RandomSampler(); - SampleFixer fixer = randomSampler.samplingParams.getSampleFixer(); - assertEquals(null, fixer); - } - - public void testCustomFixer() throws Exception { - SamplingParams sp = new SamplingParams(); - sp.setSampleFixer(new TakmiSampleFixer(null, null, null)); - assertEquals(TakmiSampleFixer.class, sp.getSampleFixer().getClass()); - } - - public void testNoFixing() throws Exception { - SamplingParams sp = new SamplingParams(); - sp.setMaxSampleSize(10); - sp.setMinSampleSize(5); - sp.setSampleRatio(0.01d); - sp.setSamplingThreshold(50); - sp.setOversampleFactor(5d); - - assertNull("Fixer should be null as the test is for no-fixing", - sp.getSampleFixer()); - FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest( - new FacetLabel("root", "a"), 1)); - SamplingAccumulator accumulator = new SamplingAccumulator( - new RandomSampler(sp, random()), fsp, indexReader, taxoReader); - - // Make sure no complements are in action - accumulator - .setComplementThreshold(OldFacetsAccumulator.DISABLE_COMPLEMENT); - - FacetsCollector fc = FacetsCollector.create(accumulator); - - searcher.search(new MatchAllDocsQuery(), fc); - FacetResultNode node = fc.getFacetResults().get(0).getFacetResultNode(); - - assertTrue(node.value < numDocsToIndex()); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingAccumulatorTest.java b/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingAccumulatorTest.java deleted file mode 100644 index 2cbfd1dfa87..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingAccumulatorTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.util.LuceneTestCase.Slow; - -/* - * 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. - */ - -@Slow -public class SamplingAccumulatorTest extends BaseSampleTestTopK { - - @Override - protected OldFacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader, - IndexReader indexReader, FacetSearchParams searchParams) { - return new SamplingAccumulator(sampler, searchParams, indexReader, taxoReader); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingWrapperTest.java b/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingWrapperTest.java deleted file mode 100644 index a6074faed6b..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/sampling/SamplingWrapperTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.apache.lucene.facet.sampling; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.util.LuceneTestCase.Slow; - -/* - * 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. - */ - -@Slow -public class SamplingWrapperTest extends BaseSampleTestTopK { - - @Override - protected OldFacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader, - IndexReader indexReader, FacetSearchParams searchParams) { - return new SamplingWrapper(new OldFacetsAccumulator(searchParams, indexReader, taxoReader), sampler); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java b/lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java deleted file mode 100644 index 2ad44b08a44..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.search; - -/* - * 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. - */ - -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.Scorer.ChildScorer; -import org.apache.lucene.search.Scorer; - -/** Verifies in collect() that all child subScorers are on - * the collected doc. */ -public class AssertingSubDocsAtOnceCollector extends Collector { - - // TODO: allow wrapping another Collector - - List allScorers; - - @Override - public void setScorer(Scorer s) { - // Gathers all scorers, including s and "under": - allScorers = new ArrayList(); - allScorers.add(s); - int upto = 0; - while(upto < allScorers.size()) { - s = allScorers.get(upto++); - for (ChildScorer sub : s.getChildren()) { - allScorers.add(sub.child); - } - } - } - - @Override - public void collect(int docID) { - for(Scorer s : allScorers) { - if (docID != s.docID()) { - throw new IllegalStateException("subScorer=" + s + " has docID=" + s.docID() + " != collected docID=" + docID); - } - } - } - - @Override - public void setNextReader(AtomicReaderContext context) { - } - - @Override - public boolean acceptsDocsOutOfOrder() { - return false; - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java b/lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java deleted file mode 100644 index 66f0cb9ea8e..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.util._TestUtil; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.facet.FacetTestBase; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; - -/* - * 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. - */ - -public abstract class BaseTestTopK extends FacetTestBase { - - protected static final String ALPHA = "alpha"; - protected static final String BETA = "beta"; - - /** partition sizes on which the tests are run */ - protected static int[] partitionSizes = new int[] { 2, 3, 100, Integer.MAX_VALUE }; - - /** Categories are generated from range [0,maxCategory) */ - protected static int maxCategory = 5000; - private static final int categoriesPow2 = maxCategory * maxCategory; - - private int currDoc; - private int nextInt; - - @Override - protected void populateIndex(RandomIndexWriter iw, TaxonomyWriter taxo, FacetIndexingParams fip) throws IOException { - currDoc = -1; - super.populateIndex(iw, taxo, fip); - } - - /** prepare the next random int */ - private void nextInt(int doc) { - if (currDoc == doc ) { - return; - } - currDoc = doc; - // the code below tries to achieve non-uniform distribution of - // categories. Perhaps we can use random.nextGaussian() instead, - // something like nextGaussian() * stdev + maxCategory/2. Or - // try to generate a Zipf distribution. - nextInt = random().nextInt(categoriesPow2); - nextInt = (int)Math.sqrt(nextInt); - } - - @Override - protected String getContent(int doc) { - nextInt(doc); - if (random().nextDouble() > 0.1) { - return ALPHA + ' ' + BETA; - } - return ALPHA; - } - - @Override - protected List getCategories(int doc) { - nextInt(doc); - FacetLabel cp = new FacetLabel( - "a", - Integer.toString(nextInt / 1000), - Integer.toString(nextInt / 100), - Integer.toString(nextInt / 10)); - if (VERBOSE) { - System.out.println("Adding CP: " + cp.toString()); - } - return Arrays.asList(cp); - } - - protected FacetSearchParams searchParamsWithRequests(int numResults, FacetIndexingParams fip) { - List facetRequests = new ArrayList(); - facetRequests.add(new CountFacetRequest(new FacetLabel("a"), numResults)); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "1"), numResults)); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "1", "10"), numResults)); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "2", "26", "267"), numResults)); - return getFacetSearchParams(facetRequests, fip); - } - - @Override - protected int numDocsToIndex() { - return 20000; - } - - @Override - protected IndexWriterConfig getIndexWriterConfig(Analyzer analyzer) { - return super.getIndexWriterConfig(analyzer).setMaxBufferedDocs(_TestUtil.nextInt(random(), 500, 10000)); - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java b/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java deleted file mode 100644 index 8b9036f8ca3..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java +++ /dev/null @@ -1,304 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.util.PartitionsUtils; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.store.Directory; -import org.junit.Test; - -/* - * 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. - */ - -public class TestTopKInEachNodeResultHandler extends FacetTestCase { - - //TODO (Facet): Move to extend BaseTestTopK and separate to several smaller test cases (methods) - see TestTopKResultsHandler - - @Test - public void testSimple() throws Exception { - - int[] partitionSizes = new int[] { - 2,3,4, 5, 6, 7, 10, 1000, - Integer.MAX_VALUE }; - - for (int partitionSize : partitionSizes) { - Directory iDir = newDirectory(); - Directory tDir = newDirectory(); - - if (VERBOSE) { - System.out.println("Partition Size: " + partitionSize); - } - - final int pSize = partitionSize; - FacetIndexingParams iParams = new FacetIndexingParams() { - @Override - public int getPartitionSize() { - return pSize; - } - }; - - RandomIndexWriter iw = new RandomIndexWriter(random(), iDir, - newIndexWriterConfig(TEST_VERSION_CURRENT, - new MockAnalyzer(random())).setOpenMode(OpenMode.CREATE)); - TaxonomyWriter tw = new DirectoryTaxonomyWriter(tDir); - prvt_add(iParams, iw, tw, "a", "b"); - prvt_add(iParams, iw, tw, "a", "b", "1"); - prvt_add(iParams, iw, tw, "a", "b", "1"); - prvt_add(iParams, iw, tw, "a", "b", "2"); - prvt_add(iParams, iw, tw, "a", "b", "2"); - prvt_add(iParams, iw, tw, "a", "b", "2"); - prvt_add(iParams, iw, tw, "a", "b", "3"); - prvt_add(iParams, iw, tw, "a", "b", "4"); - prvt_add(iParams, iw, tw, "a", "c"); - prvt_add(iParams, iw, tw, "a", "c"); - prvt_add(iParams, iw, tw, "a", "c"); - prvt_add(iParams, iw, tw, "a", "c"); - prvt_add(iParams, iw, tw, "a", "c"); - prvt_add(iParams, iw, tw, "a", "c", "1"); - prvt_add(iParams, iw, tw, "a", "d"); - prvt_add(iParams, iw, tw, "a", "e"); - - IndexReader ir = iw.getReader(); - iw.close(); - tw.commit(); - tw.close(); - - IndexSearcher is = newSearcher(ir); - DirectoryTaxonomyReader tr = new DirectoryTaxonomyReader(tDir); - - // Get all of the documents and run the query, then do different - // facet counts and compare to control - Query q = new TermQuery(new Term("content", "alpha")); - - CountFacetRequest cfra23 = new CountFacetRequest(new FacetLabel("a"), 2); - cfra23.setDepth(3); - cfra23.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfra22 = new CountFacetRequest(new FacetLabel("a"), 2); - cfra22.setDepth(2); - cfra22.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfra21 = new CountFacetRequest(new FacetLabel("a"), 2); - cfra21.setDepth(1); - cfra21.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfrb22 = new CountFacetRequest(new FacetLabel("a", "b"), 2); - cfrb22.setDepth(2); - cfrb22.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfrb23 = new CountFacetRequest(new FacetLabel("a", "b"), 2); - cfrb23.setDepth(3); - cfrb23.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfrb21 = new CountFacetRequest(new FacetLabel("a", "b"), 2); - cfrb21.setDepth(1); - cfrb21.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest doctor = new CountFacetRequest(new FacetLabel("Doctor"), 2); - doctor.setDepth(1); - doctor.setResultMode(ResultMode.PER_NODE_IN_TREE); - - CountFacetRequest cfrb20 = new CountFacetRequest(new FacetLabel("a", "b"), 2); - cfrb20.setDepth(0); - cfrb20.setResultMode(ResultMode.PER_NODE_IN_TREE); - - List facetRequests = new ArrayList(); - facetRequests.add(cfra23); - facetRequests.add(cfra22); - facetRequests.add(cfra21); - facetRequests.add(cfrb23); - facetRequests.add(cfrb22); - facetRequests.add(cfrb21); - facetRequests.add(doctor); - facetRequests.add(cfrb20); - FacetSearchParams facetSearchParams = new FacetSearchParams(iParams, facetRequests); - - FacetArrays facetArrays = new FacetArrays(PartitionsUtils.partitionSize(facetSearchParams.indexingParams, tr)); - OldFacetsAccumulator sfa = new OldFacetsAccumulator(facetSearchParams, is.getIndexReader(), tr, facetArrays); - sfa.setComplementThreshold(OldFacetsAccumulator.DISABLE_COMPLEMENT); - FacetsCollector fc = FacetsCollector.create(sfa); - - is.search(q, fc); - List facetResults = fc.getFacetResults(); - - FacetResult fr = facetResults.get(0); // a, depth=3, K=2 - boolean hasDoctor = "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(9, fr.getNumValidDescendants()); - FacetResultNode parentRes = fr.getFacetResultNode(); - assertEquals(2, parentRes.subResults.size()); - // two nodes sorted by descending values: a/b with 8 and a/c with 6 - // a/b has two children a/b/2 with value 3, and a/b/1 with value 2. - // a/c has one child a/c/1 with value 1. - double [] expectedValues0 = { 8.0, 3.0, 2.0, 6.0, 1.0 }; - int i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues0[i++], node.value, Double.MIN_VALUE); - for (FacetResultNode node2 : node.subResults) { - assertEquals(expectedValues0[i++], node2.value, Double.MIN_VALUE); - } - } - - // now just change the value of the first child of the root to 5, and then rearrange - // expected are: first a/c of value 6, and one child a/c/1 with value 1 - // then a/b with value 5, and both children: a/b/2 with value 3, and a/b/1 with value 2. - for (FacetResultNode node : parentRes.subResults) { - node.value = 5.0; - break; - } - // now rearrange - double [] expectedValues00 = { 6.0, 1.0, 5.0, 3.0, 2.0 }; - fr = sfa.createFacetResultsHandler(cfra23, sfa.createOrdinalValueResolver(cfra23)).rearrangeFacetResult(fr); - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues00[i++], node.value, Double.MIN_VALUE); - for (FacetResultNode node2 : node.subResults) { - assertEquals(expectedValues00[i++], node2.value, Double.MIN_VALUE); - } - } - - fr = facetResults.get(1); // a, depth=2, K=2. same result as before - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(9, fr.getNumValidDescendants()); - parentRes = fr.getFacetResultNode(); - assertEquals(2, parentRes.subResults.size()); - // two nodes sorted by descending values: a/b with 8 and a/c with 6 - // a/b has two children a/b/2 with value 3, and a/b/1 with value 2. - // a/c has one child a/c/1 with value 1. - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues0[i++], node.value, Double.MIN_VALUE); - for (FacetResultNode node2 : node.subResults) { - assertEquals(expectedValues0[i++], node2.value, Double.MIN_VALUE); - } - } - - fr = facetResults.get(2); // a, depth=1, K=2 - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(4, fr.getNumValidDescendants(), 4); - parentRes = fr.getFacetResultNode(); - assertEquals(2, parentRes.subResults.size()); - // two nodes sorted by descending values: - // a/b with value 8 and a/c with value 6 - double [] expectedValues2 = { 8.0, 6.0, 0.0}; - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues2[i++], node.value, Double.MIN_VALUE); - assertEquals(node.subResults.size(), 0); - } - - fr = facetResults.get(3); // a/b, depth=3, K=2 - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(4, fr.getNumValidDescendants()); - parentRes = fr.getFacetResultNode(); - assertEquals(8.0, parentRes.value, Double.MIN_VALUE); - assertEquals(2, parentRes.subResults.size()); - double [] expectedValues3 = { 3.0, 2.0 }; - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues3[i++], node.value, Double.MIN_VALUE); - assertEquals(0, node.subResults.size()); - } - - fr = facetResults.get(4); // a/b, depth=2, K=2 - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(4, fr.getNumValidDescendants()); - parentRes = fr.getFacetResultNode(); - assertEquals(8.0, parentRes.value, Double.MIN_VALUE); - assertEquals(2, parentRes.subResults.size()); - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues3[i++], node.value, Double.MIN_VALUE); - assertEquals(0, node.subResults.size()); - } - - fr = facetResults.get(5); // a/b, depth=1, K=2 - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(4, fr.getNumValidDescendants()); - parentRes = fr.getFacetResultNode(); - assertEquals(8.0, parentRes.value, Double.MIN_VALUE); - assertEquals(2, parentRes.subResults.size()); - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues3[i++], node.value, Double.MIN_VALUE); - assertEquals(0, node.subResults.size()); - } - - fr = facetResults.get(6); // Doctor, depth=0, K=2 - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - assertEquals(0, fr.getNumValidDescendants()); // 0 descendants but rootnode - parentRes = fr.getFacetResultNode(); - assertEquals(0.0, parentRes.value, Double.MIN_VALUE); - assertEquals(0, parentRes.subResults.size()); - hasDoctor |= "Doctor".equals(fr.getFacetRequest().categoryPath.components[0]); - - // doctor, depth=1, K=2 - assertTrue("Should have found an empty FacetResult " + - "for a facet that doesn't exist in the index.", hasDoctor); - assertEquals("Shouldn't have found more than 8 request.", 8, facetResults.size()); - - fr = facetResults.get(7); // a/b, depth=0, K=2 - assertEquals(0, fr.getNumValidDescendants()); - parentRes = fr.getFacetResultNode(); - assertEquals(8.0, parentRes.value, Double.MIN_VALUE); - assertEquals(0, parentRes.subResults.size()); - i = 0; - for (FacetResultNode node : parentRes.subResults) { - assertEquals(expectedValues3[i++], node.value, Double.MIN_VALUE); - assertEquals(0, node.subResults.size()); - } - - ir.close(); - tr.close(); - iDir.close(); - tDir.close(); - } - - } - - private void prvt_add(FacetIndexingParams iParams, RandomIndexWriter iw, - TaxonomyWriter tw, String... strings) throws IOException { - Document d = new Document(); - FacetFields facetFields = new FacetFields(tw, iParams); - facetFields.addFields(d, Collections.singletonList(new FacetLabel(strings))); - d.add(new TextField("content", "alpha", Field.Store.YES)); - iw.addDocument(d); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java b/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java deleted file mode 100644 index 426206bb91d..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java +++ /dev/null @@ -1,211 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.junit.Test; - -/* - * 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. - */ - -public class TestTopKResultsHandler extends BaseTestTopK { - - private static final FacetLabel[] CATEGORIES = { - new FacetLabel( "a", "b"), - new FacetLabel( "a", "b", "1"), - new FacetLabel( "a", "b", "1"), - new FacetLabel( "a", "b", "2"), - new FacetLabel( "a", "b", "2"), - new FacetLabel( "a", "b", "3"), - new FacetLabel( "a", "b", "4"), - new FacetLabel( "a", "c"), - new FacetLabel( "a", "c"), - new FacetLabel( "a", "c"), - new FacetLabel( "a", "c"), - new FacetLabel( "a", "c"), - new FacetLabel( "a", "c", "1"), - }; - - @Override - protected String getContent(int doc) { - return ALPHA; - } - - @Override - protected int numDocsToIndex() { - return CATEGORIES.length; - } - - @Override - protected List getCategories(int doc) { - return Arrays.asList(CATEGORIES[doc]); - } - - /** - * Straightforward test: Adding specific documents with specific facets and - * counting them in the most basic form. - */ - @Test - public void testSimple() throws Exception { - for (int partitionSize : partitionSizes) { - FacetIndexingParams fip = getFacetIndexingParams(partitionSize); - OrdinalPolicy op = fip.getCategoryListParams(null).getOrdinalPolicy(null); - initIndex(fip); - - List facetRequests = new ArrayList(); - facetRequests.add(new CountFacetRequest(new FacetLabel("a"), 100)); - CountFacetRequest cfra = new CountFacetRequest(new FacetLabel("a"), 100); - cfra.setDepth(3); - // makes it easier to check the results in the test. - cfra.setResultMode(ResultMode.GLOBAL_FLAT); - facetRequests.add(cfra); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "b"), 100)); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "b", "1"), 100)); - facetRequests.add(new CountFacetRequest(new FacetLabel("a", "c"), 100)); - - // do different facet counts and compare to control - FacetSearchParams sParams = getFacetSearchParams(facetRequests, fip); - FacetsCollector fc = FacetsCollector.create(sParams, indexReader, taxoReader); - - searcher.search(new MatchAllDocsQuery(), fc); - List facetResults = fc.getFacetResults(); - - FacetResult fr = facetResults.get(0); - FacetResultNode parentRes = fr.getFacetResultNode(); - if (op == OrdinalPolicy.ALL_PARENTS) { - assertEquals(13.0, parentRes.value, Double.MIN_VALUE); - } - FacetResultNode[] frn = resultNodesAsArray(parentRes); - assertEquals(7.0, frn[0].value, Double.MIN_VALUE); - assertEquals(6.0, frn[1].value, Double.MIN_VALUE); - - fr = facetResults.get(1); - parentRes = fr.getFacetResultNode(); - if (op == OrdinalPolicy.ALL_PARENTS) { - assertEquals(13.0, parentRes.value, Double.MIN_VALUE); - } - frn = resultNodesAsArray(parentRes); - assertEquals(7.0, frn[0].value, Double.MIN_VALUE); - assertEquals(6.0, frn[1].value, Double.MIN_VALUE); - assertEquals(2.0, frn[2].value, Double.MIN_VALUE); - assertEquals(2.0, frn[3].value, Double.MIN_VALUE); - assertEquals(1.0, frn[4].value, Double.MIN_VALUE); - assertEquals(1.0, frn[5].value, Double.MIN_VALUE); - - fr = facetResults.get(2); - parentRes = fr.getFacetResultNode(); - if (op == OrdinalPolicy.ALL_PARENTS) { - assertEquals(7.0, parentRes.value, Double.MIN_VALUE); - } - frn = resultNodesAsArray(parentRes); - assertEquals(2.0, frn[0].value, Double.MIN_VALUE); - assertEquals(2.0, frn[1].value, Double.MIN_VALUE); - assertEquals(1.0, frn[2].value, Double.MIN_VALUE); - assertEquals(1.0, frn[3].value, Double.MIN_VALUE); - - fr = facetResults.get(3); - parentRes = fr.getFacetResultNode(); - if (op == OrdinalPolicy.ALL_PARENTS) { - assertEquals(2.0, parentRes.value, Double.MIN_VALUE); - } - frn = resultNodesAsArray(parentRes); - assertEquals(0, frn.length); - - fr = facetResults.get(4); - parentRes = fr.getFacetResultNode(); - if (op == OrdinalPolicy.ALL_PARENTS) { - assertEquals(6.0, parentRes.value, Double.MIN_VALUE); - } - frn = resultNodesAsArray(parentRes); - assertEquals(1.0, frn[0].value, Double.MIN_VALUE); - closeAll(); - } - } - - /** - * Creating an index, matching the results of an top K = Integer.MAX_VALUE and top-1000 requests - */ - @Test - public void testGetMaxIntFacets() throws Exception { - for (int partitionSize : partitionSizes) { - FacetIndexingParams fip = getFacetIndexingParams(partitionSize); - initIndex(fip); - - // do different facet counts and compare to control - FacetLabel path = new FacetLabel("a", "b"); - FacetSearchParams sParams = getFacetSearchParams(fip, new CountFacetRequest(path, Integer.MAX_VALUE)); - FacetsCollector fc = FacetsCollector.create(sParams, indexReader, taxoReader); - - searcher.search(new MatchAllDocsQuery(), fc); - List results = fc.getFacetResults(); - - assertEquals("Should only be one result as there's only one request", 1, results.size()); - FacetResult res = results.get(0); - assertEquals(path + " should only have 4 desendants", 4, res.getNumValidDescendants()); - - // As a control base results, ask for top-1000 results - FacetSearchParams sParams2 = getFacetSearchParams(fip, new CountFacetRequest(path, Integer.MAX_VALUE)); - FacetsCollector fc2 = FacetsCollector.create(sParams2, indexReader, taxoReader); - - searcher.search(new MatchAllDocsQuery(), fc2); - List baseResults = fc2.getFacetResults(); - FacetResult baseRes = baseResults.get(0); - - // Removing the first line which holds the REQUEST and this is surly different between the two - String baseResultString = baseRes.toString(); - baseResultString = baseResultString.substring(baseResultString.indexOf('\n')); - - // Removing the first line - String resultString = res.toString(); - resultString = resultString.substring(resultString.indexOf('\n')); - - assertTrue("Results for k=MAX_VALUE do not match the regular results for k=1000!!", - baseResultString.equals(resultString)); - - closeAll(); - } - } - - @Test - public void testSimpleSearchForNonexistentFacet() throws Exception { - for (int partitionSize : partitionSizes) { - FacetIndexingParams fip = getFacetIndexingParams(partitionSize); - initIndex(fip); - - FacetLabel path = new FacetLabel("Miau Hattulla"); - FacetSearchParams sParams = getFacetSearchParams(fip, new CountFacetRequest(path, 10)); - - FacetsCollector fc = FacetsCollector.create(sParams, indexReader, taxoReader); - - searcher.search(new MatchAllDocsQuery(), fc); - - List facetResults = fc.getFacetResults(); - - assertEquals("Shouldn't have found anything for a FacetRequest " - + "of a facet that doesn't exist in the index.", 1, facetResults.size()); - assertEquals("Miau Hattulla", facetResults.get(0).getFacetResultNode().label.components[0]); - closeAll(); - } - } -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java b/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java deleted file mode 100644 index cd9a3caeeb6..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.apache.lucene.facet.search; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; - -import org.apache.lucene.facet.old.OldFacetsAccumulator; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.Query; -import org.junit.Test; - -/* - * 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. - */ - -public class TestTopKResultsHandlerRandom extends BaseTestTopK { - - private List countFacets(FacetIndexingParams fip, int numResults, final boolean doComplement) - throws IOException { - Query q = new MatchAllDocsQuery(); - FacetSearchParams facetSearchParams = searchParamsWithRequests(numResults, fip); - OldFacetsAccumulator sfa = new OldFacetsAccumulator(facetSearchParams, indexReader, taxoReader); - sfa.setComplementThreshold(doComplement ? OldFacetsAccumulator.FORCE_COMPLEMENT : OldFacetsAccumulator.DISABLE_COMPLEMENT); - FacetsCollector fc = FacetsCollector.create(sfa); - searcher.search(q, fc); - List facetResults = fc.getFacetResults(); - return facetResults; - } - - /** - * Test that indeed top results are returned, ordered same as all results - * also when some facets have the same counts. - */ - @Test - public void testTopCountsOrder() throws Exception { - for (int partitionSize : partitionSizes) { - FacetIndexingParams fip = getFacetIndexingParams(partitionSize); - initIndex(fip); - - /* - * Try out faceted search in it's most basic form (no sampling nor complement - * that is). In this test lots (and lots..) of randomly generated data is - * being indexed, and later on an "over-all" faceted search is performed. The - * results are checked against the DF of each facet by itself - */ - List facetResults = countFacets(fip, 100000, false); - assertCountsAndCardinality(facetCountsTruth(), facetResults); - - /* - * Try out faceted search with complements. In this test lots (and lots..) of - * randomly generated data is being indexed, and later on, a "beta" faceted - * search is performed - retrieving ~90% of the documents so complements takes - * place in here. The results are checked against the a regular (a.k.a - * no-complement, no-sampling) faceted search with the same parameters. - */ - facetResults = countFacets(fip, 100000, true); - assertCountsAndCardinality(facetCountsTruth(), facetResults); - - List allFacetResults = countFacets(fip, 100000, false); - - HashMap all = new HashMap(); - int maxNumNodes = 0; - int k = 0; - for (FacetResult fr : allFacetResults) { - FacetResultNode topResNode = fr.getFacetResultNode(); - maxNumNodes = Math.max(maxNumNodes, topResNode.subResults.size()); - int prevCount = Integer.MAX_VALUE; - int pos = 0; - for (FacetResultNode frn: topResNode.subResults) { - assertTrue("wrong counts order: prev="+prevCount+" curr="+frn.value, prevCount>=frn.value); - prevCount = (int) frn.value; - String key = k+"--"+frn.label+"=="+frn.value; - if (VERBOSE) { - System.out.println(frn.label + " - " + frn.value + " "+key+" "+pos); - } - all.put(key, pos++); // will use this later to verify order of sub-results - } - k++; - } - - // verify that when asking for less results, they are always of highest counts - // also verify that the order is stable - for (int n=1; n someResults = countFacets(fip, n, false); - k = 0; - for (FacetResult fr : someResults) { - FacetResultNode topResNode = fr.getFacetResultNode(); - assertTrue("too many results: n="+n+" but got "+topResNode.subResults.size(), n>=topResNode.subResults.size()); - int pos = 0; - for (FacetResultNode frn: topResNode.subResults) { - String key = k+"--"+frn.label+"=="+frn.value; - if (VERBOSE) { - System.out.println(frn.label + " - " + frn.value + " "+key+" "+pos); - } - Integer origPos = all.get(key); - assertNotNull("missing in all results: "+frn,origPos); - assertEquals("wrong order of sub-results!",pos++, origPos.intValue()); // verify order of sub-results - } - k++; - } - } - - closeAll(); // done with this partition - } - } - - @Override - protected int numDocsToIndex() { - return TEST_NIGHTLY ? 20000 : 1000; - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestCachedOrdinalsReader.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestCachedOrdinalsReader.java index e368f5d5b41..4dce38bba2d 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestCachedOrdinalsReader.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestCachedOrdinalsReader.java @@ -23,8 +23,6 @@ import java.util.Arrays; import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; import org.apache.lucene.index.AtomicReaderContext; diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestDrillDownQuery.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestDrillDownQuery.java index afeca0a658f..febf1f25b18 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestDrillDownQuery.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestDrillDownQuery.java @@ -29,10 +29,6 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.PerDimensionIndexingParams; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestMultipleIndexFields.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestMultipleIndexFields.java index 8d6d16edc52..33096578434 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestMultipleIndexFields.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestMultipleIndexFields.java @@ -31,12 +31,6 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.params.PerDimensionIndexingParams; -import org.apache.lucene.facet.search.FacetRequest.ResultMode; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestRangeFacets.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestRangeFacets.java index f69d480b3da..96ab014e1fb 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestRangeFacets.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestRangeFacets.java @@ -34,20 +34,6 @@ import org.apache.lucene.document.FloatField; import org.apache.lucene.document.LongField; import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.FacetTestUtils; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.range.DoubleRange; -import org.apache.lucene.facet.range.FloatRange; -import org.apache.lucene.facet.range.LongRange; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.DrillDownQuery; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsAccumulator; -import org.apache.lucene.facet.search.FacetsCollector; import org.apache.lucene.facet.simple.SimpleDrillSideways.SimpleDrillSidewaysResult; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.TaxonomyReader; diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestSearcherTaxonomyManager.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestSearcherTaxonomyManager.java index 76e8856350a..3acba86247d 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestSearcherTaxonomyManager.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestSearcherTaxonomyManager.java @@ -27,11 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.SearcherTaxonomyManager.SearcherAndTaxonomy; -import org.apache.lucene.facet.search.SearcherTaxonomyManager; +import org.apache.lucene.facet.simple.SearcherTaxonomyManager.SearcherAndTaxonomy; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; import org.apache.lucene.index.IndexWriter; @@ -61,7 +57,6 @@ public class TestSearcherTaxonomyManager extends FacetTestCase { List paths = new ArrayList(); while (true) { Document doc = new Document(); - List docPaths = new ArrayList(); int numPaths = _TestUtil.nextInt(random(), 1, 5); for(int i=0;i allExpectedCounts, termExpectedCounts; + private static Map allExpectedCounts, termExpectedCounts; @AfterClass public static void afterClassCountingFacetsAggregatorTest() throws Exception { @@ -172,7 +165,7 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { } private static void indexDocsWithFacetsNoTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, - ObjectToIntMap expectedCounts) throws IOException { + Map expectedCounts) throws IOException { Random random = random(); int numDocs = atLeast(random, 2); FacetsConfig config = getConfig(taxoWriter); @@ -185,7 +178,7 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { } private static void indexDocsWithFacetsAndTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, - ObjectToIntMap expectedCounts) throws IOException { + Map expectedCounts) throws IOException { Random random = random(); int numDocs = atLeast(random, 2); FacetsConfig config = getConfig(taxoWriter); @@ -199,7 +192,7 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { } private static void indexDocsWithFacetsAndSomeTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, - ObjectToIntMap expectedCounts) throws IOException { + Map expectedCounts) throws IOException { Random random = random(); int numDocs = atLeast(random, 2); FacetsConfig config = getConfig(taxoWriter); @@ -216,8 +209,8 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { } // initialize expectedCounts w/ 0 for all categories - private static ObjectToIntMap newCounts() { - ObjectToIntMap counts = new ObjectToIntMap(); + private static Map newCounts() { + Map counts = new HashMap(); counts.put(CP_A, 0); counts.put(CP_B, 0); counts.put(CP_C, 0); @@ -285,12 +278,12 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { SimpleFacetResult result = facets.getTopChildren(NUM_CHILDREN_CP_A, CP_A); assertEquals(-1, result.value.intValue()); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(termExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(termExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value); } result = facets.getTopChildren(NUM_CHILDREN_CP_B, CP_B); - assertEquals(termExpectedCounts.get(CP_B), result.value.intValue()); + assertEquals(termExpectedCounts.get(CP_B), result.value); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(termExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(termExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value); } IOUtils.close(indexReader, taxoReader); @@ -311,16 +304,16 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { assertEquals(-1, result.value.intValue()); int prevValue = Integer.MAX_VALUE; for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value); assertTrue("wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue, labelValue.value.intValue() <= prevValue); prevValue = labelValue.value.intValue(); } result = facets.getTopChildren(NUM_CHILDREN_CP_B, CP_B); - assertEquals(allExpectedCounts.get(CP_B), result.value.intValue()); + assertEquals(allExpectedCounts.get(CP_B), result.value); prevValue = Integer.MAX_VALUE; for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value); assertTrue("wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue, labelValue.value.intValue() <= prevValue); prevValue = labelValue.value.intValue(); } @@ -342,12 +335,12 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { SimpleFacetResult result = facets.getTopChildren(Integer.MAX_VALUE, CP_A); assertEquals(-1, result.value.intValue()); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_A + "/" + labelValue.label), labelValue.value); } result = facets.getTopChildren(Integer.MAX_VALUE, CP_B); - assertEquals(allExpectedCounts.get(CP_B), result.value.intValue()); + assertEquals(allExpectedCounts.get(CP_B), result.value); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_B + "/" + labelValue.label), labelValue.value); } IOUtils.close(indexReader, taxoReader); @@ -365,14 +358,14 @@ public class TestTaxonomyFacetCounts2 extends FacetTestCase { Facets facets = getTaxonomyFacetCounts(taxoReader, getConfig(), sfc); SimpleFacetResult result = facets.getTopChildren(NUM_CHILDREN_CP_C, CP_C); - assertEquals(allExpectedCounts.get(CP_C), result.value.intValue()); + assertEquals(allExpectedCounts.get(CP_C), result.value); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_C + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_C + "/" + labelValue.label), labelValue.value); } result = facets.getTopChildren(NUM_CHILDREN_CP_D, CP_D); - assertEquals(allExpectedCounts.get(CP_C), result.value.intValue()); + assertEquals(allExpectedCounts.get(CP_C), result.value); for(LabelAndValue labelValue : result.labelValues) { - assertEquals(allExpectedCounts.get(CP_D + "/" + labelValue.label), labelValue.value.intValue()); + assertEquals(allExpectedCounts.get(CP_D + "/" + labelValue.label), labelValue.value); } IOUtils.close(indexReader, taxoReader); diff --git a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestTaxonomyFacetSumValueSource.java b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestTaxonomyFacetSumValueSource.java index 446a4d53219..709d0a42c5d 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/simple/TestTaxonomyFacetSumValueSource.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/simple/TestTaxonomyFacetSumValueSource.java @@ -35,11 +35,11 @@ import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.document.StringField; import org.apache.lucene.facet.FacetTestCase; import org.apache.lucene.facet.taxonomy.FacetLabel; +import org.apache.lucene.facet.taxonomy.PrintTaxonomyStats; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.util.PrintTaxonomyStats; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexWriter; diff --git a/lucene/facet/src/test/org/apache/lucene/facet/collections/TestLRUHashMap.java b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestLRUHashMap.java similarity index 95% rename from lucene/facet/src/test/org/apache/lucene/facet/collections/TestLRUHashMap.java rename to lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestLRUHashMap.java index d61bf710af8..2607a1e19b0 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/collections/TestLRUHashMap.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestLRUHashMap.java @@ -1,8 +1,4 @@ -package org.apache.lucene.facet.collections; - -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.collections.LRUHashMap; -import org.junit.Test; +package org.apache.lucene.facet.taxonomy; /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,6 +17,10 @@ import org.junit.Test; * limitations under the License. */ +import org.apache.lucene.facet.FacetTestCase; +import org.apache.lucene.facet.taxonomy.LRUHashMap; +import org.junit.Test; + public class TestLRUHashMap extends FacetTestCase { // testLRU() tests that the specified size limit is indeed honored, and // the remaining objects in the map are indeed those that have been most diff --git a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java index ea78aeaa751..4d1865c656f 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java @@ -9,7 +9,8 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; +import org.apache.lucene.facet.simple.FacetField; +import org.apache.lucene.facet.simple.FacetsConfig; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.writercache.TaxonomyWriterCache; import org.apache.lucene.facet.taxonomy.writercache.cl2o.Cl2oTaxonomyWriterCache; @@ -56,12 +57,12 @@ public class TestConcurrentFacetedIndexing extends FacetTestCase { }; - static FacetLabel newCategory() { + static FacetField newCategory() { Random r = random(); String l1 = "l1." + r.nextInt(10); // l1.0-l1.9 (10 categories) String l2 = "l2." + r.nextInt(30); // l2.0-l2.29 (30 categories) String l3 = "l3." + r.nextInt(100); // l3.0-l3.99 (100 categories) - return new FacetLabel(l1, l2, l3); + return new FacetField(l1, l2, l3); } static TaxonomyWriterCache newTaxoWriterCache(int ndocs) { @@ -87,10 +88,14 @@ public class TestConcurrentFacetedIndexing extends FacetTestCase { final IndexWriter iw = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); final DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, newTaxoWriterCache(numDocs.get())); final Thread[] indexThreads = new Thread[atLeast(4)]; + final FacetsConfig config = new FacetsConfig(tw); + for(int i=0;i<10;i++) { + config.setHierarchical("l1." + i, true); + config.setMultiValued("l1." + i, true); + } for (int i = 0; i < indexThreads.length; i++) { indexThreads[i] = new Thread() { - private final FacetFields facetFields = new FacetFields(tw); @Override public void run() { @@ -99,20 +104,20 @@ public class TestConcurrentFacetedIndexing extends FacetTestCase { try { Document doc = new Document(); int numCats = random.nextInt(3) + 1; // 1-3 - List cats = new ArrayList(numCats); while (numCats-- > 0) { - FacetLabel cp = newCategory(); - cats.add(cp); + FacetField ff = newCategory(); + doc.add(ff); + + FacetLabel label = FacetLabel.create(ff.dim, ff.path); // add all prefixes to values - int level = cp.length; + int level = label.length; while (level > 0) { - String s = cp.subpath(level).toString('/'); + String s = label.subpath(level).toString('/'); values.put(s, s); --level; } } - facetFields.addFields(doc, cats); - iw.addDocument(doc); + iw.addDocument(config.build(doc)); } catch (IOException e) { throw new RuntimeException(e); } @@ -140,9 +145,8 @@ public class TestConcurrentFacetedIndexing extends FacetTestCase { parentOrd = ord; // next level should have this parent } } - tr.close(); - IOUtils.close(tw, iw, taxoDir, indexDir); + IOUtils.close(tw, iw, tr, taxoDir, indexDir); } } diff --git a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java index 24ee75b065e..80b176e8fef 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java @@ -11,9 +11,9 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.search.DrillDownQuery; +import org.apache.lucene.facet.simple.FacetField; +import org.apache.lucene.facet.simple.FacetsConfig; +import org.apache.lucene.facet.simple.SimpleDrillDownQuery; import org.apache.lucene.facet.taxonomy.FacetLabel; import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap; @@ -23,8 +23,8 @@ import org.apache.lucene.facet.taxonomy.writercache.lru.LruTaxonomyWriterCache; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.IndexWriterConfig.OpenMode; +import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.SegmentInfos; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.store.AlreadyClosedException; @@ -427,30 +427,28 @@ public class TestDirectoryTaxonomyWriter extends FacetTestCase { Directory indexDir = newDirectory(), taxoDir = newDirectory(); IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, new Cl2oTaxonomyWriterCache(2, 1f, 1)); - FacetFields facetFields = new FacetFields(taxoWriter); + FacetsConfig config = new FacetsConfig(taxoWriter); // Add one huge label: String bigs = null; int ordinal = -1; - FacetLabel cp = null; - while (true) { - int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH - 4; // for the dimension and separator - bigs = _TestUtil.randomSimpleString(random(), len, len); - cp = new FacetLabel("dim", bigs); - ordinal = taxoWriter.addCategory(cp); - Document doc = new Document(); - facetFields.addFields(doc, Collections.singletonList(cp)); - indexWriter.addDocument(doc); - break; - } + + int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH - 4; // for the dimension and separator + bigs = _TestUtil.randomSimpleString(random(), len, len); + FacetField ff = new FacetField("dim", bigs); + FacetLabel cp = FacetLabel.create("dim", bigs); + ordinal = taxoWriter.addCategory(cp); + Document doc = new Document(); + doc.add(ff); + indexWriter.addDocument(config.build(doc)); // Add tiny ones to cause a re-hash for (int i = 0; i < 3; i++) { String s = _TestUtil.randomSimpleString(random(), 1, 10); taxoWriter.addCategory(new FacetLabel("dim", s)); - Document doc = new Document(); - facetFields.addFields(doc, Collections.singletonList(new FacetLabel("dim", s))); - indexWriter.addDocument(doc); + doc = new Document(); + doc.add(new FacetField("dim", s)); + indexWriter.addDocument(config.build(doc)); } // when too large components were allowed to be added, this resulted in a new added category @@ -461,13 +459,11 @@ public class TestDirectoryTaxonomyWriter extends FacetTestCase { DirectoryReader indexReader = DirectoryReader.open(indexDir); TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); IndexSearcher searcher = new IndexSearcher(indexReader); - DrillDownQuery ddq = new DrillDownQuery(FacetIndexingParams.DEFAULT); - ddq.add(cp); + SimpleDrillDownQuery ddq = new SimpleDrillDownQuery(new FacetsConfig()); + ddq.add("dim", bigs); assertEquals(1, searcher.search(ddq, 10).totalHits); - IOUtils.close(indexReader, taxoReader); - - IOUtils.close(indexDir, taxoDir); + IOUtils.close(indexReader, taxoReader, indexDir, taxoDir); } @Test diff --git a/lucene/facet/src/test/org/apache/lucene/facet/util/AssertingCategoryListIterator.java b/lucene/facet/src/test/org/apache/lucene/facet/util/AssertingCategoryListIterator.java deleted file mode 100644 index 27139f3123f..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/util/AssertingCategoryListIterator.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.apache.lucene.facet.util; - -import java.io.IOException; - -import org.apache.lucene.facet.search.CategoryListIterator; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.util.IntsRef; - -/* - * 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. - */ - -/** - * A {@link CategoryListIterator} which asserts that - * {@link #getOrdinals(int, IntsRef)} is not called before - * {@link #setNextReader(AtomicReaderContext)} and that if - * {@link #setNextReader(AtomicReaderContext)} returns false, - * {@link #getOrdinals(int, IntsRef)} isn't called. - */ -public class AssertingCategoryListIterator implements CategoryListIterator { - - private final CategoryListIterator delegate; - private boolean setNextReaderCalled = false; - private boolean validSegment = false; - private int maxDoc; - - public AssertingCategoryListIterator(CategoryListIterator delegate) { - this.delegate = delegate; - } - - @Override - public boolean setNextReader(AtomicReaderContext context) throws IOException { - setNextReaderCalled = true; - maxDoc = context.reader().maxDoc(); - return validSegment = delegate.setNextReader(context); - } - - @Override - public void getOrdinals(int docID, IntsRef ints) throws IOException { - if (!setNextReaderCalled) { - throw new RuntimeException("should not call getOrdinals without setNextReader first"); - } - if (!validSegment) { - throw new RuntimeException("should not call getOrdinals if setNextReader returned false"); - } - if (docID >= maxDoc) { - throw new RuntimeException("docID is larger than current maxDoc; forgot to call setNextReader?"); - } - delegate.getOrdinals(docID, ints); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/util/OrdinalMappingReaderTest.java b/lucene/facet/src/test/org/apache/lucene/facet/util/OrdinalMappingReaderTest.java deleted file mode 100644 index 1989e11b753..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/util/OrdinalMappingReaderTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.apache.lucene.facet.util; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.analysis.MockTokenizer; -import org.apache.lucene.document.Document; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap; -import org.apache.lucene.facet.util.TaxonomyMergeUtils; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.IOUtils; -import org.junit.Test; - -/* - * 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. - */ - -public class OrdinalMappingReaderTest extends FacetTestCase { - - private static final int NUM_DOCS = 100; - - @Test - public void testTaxonomyMergeUtils() throws Exception { - Directory dir = newDirectory(); - Directory taxDir = newDirectory(); - FacetIndexingParams fip = new FacetIndexingParams(randomCategoryListParams()); - buildIndexWithFacets(dir, taxDir, true, fip); - - Directory dir1 = newDirectory(); - Directory taxDir1 = newDirectory(); - buildIndexWithFacets(dir1, taxDir1, false, fip); - - IndexWriter destIndexWriter = new IndexWriter(dir1, new IndexWriterConfig(TEST_VERSION_CURRENT, null)); - DirectoryTaxonomyWriter destTaxWriter = new DirectoryTaxonomyWriter(taxDir1); - try { - TaxonomyMergeUtils.merge(dir, taxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter, fip); - } finally { - IOUtils.close(destIndexWriter, destTaxWriter); - } - - verifyResults(dir1, taxDir1, fip); - dir1.close(); - taxDir1.close(); - dir.close(); - taxDir.close(); - } - - private void verifyResults(Directory dir, Directory taxDir, FacetIndexingParams fip) throws IOException { - DirectoryReader reader1 = DirectoryReader.open(dir); - DirectoryTaxonomyReader taxReader = new DirectoryTaxonomyReader(taxDir); - IndexSearcher searcher = newSearcher(reader1); - FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest(new FacetLabel("tag"), NUM_DOCS)); - FacetsCollector collector = FacetsCollector.create(fsp, reader1, taxReader); - searcher.search(new MatchAllDocsQuery(), collector); - FacetResult result = collector.getFacetResults().get(0); - FacetResultNode node = result.getFacetResultNode(); - for (FacetResultNode facet: node.subResults) { - int weight = (int)facet.value; - int label = Integer.parseInt(facet.label.components[1]); - //System.out.println(label + ": " + weight); - if (VERBOSE) { - System.out.println(label + ": " + weight); - } - assertEquals(NUM_DOCS ,weight); - } - reader1.close(); - taxReader.close(); - } - - private void buildIndexWithFacets(Directory dir, Directory taxDir, boolean asc, FacetIndexingParams fip) throws IOException { - IndexWriterConfig config = newIndexWriterConfig(TEST_VERSION_CURRENT, - new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false)); - RandomIndexWriter writer = new RandomIndexWriter(random(), dir, config); - - DirectoryTaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(taxDir); - for (int i = 1; i <= NUM_DOCS; i++) { - Document doc = new Document(); - List categoryPaths = new ArrayList(i + 1); - for (int j = i; j <= NUM_DOCS; j++) { - int facetValue = asc? j: NUM_DOCS - j; - categoryPaths.add(new FacetLabel("tag", Integer.toString(facetValue))); - } - FacetFields facetFields = new FacetFields(taxonomyWriter, fip); - facetFields.addFields(doc, categoryPaths); - writer.addDocument(doc); - } - taxonomyWriter.close(); - writer.close(); - } - -} diff --git a/lucene/facet/src/test/org/apache/lucene/facet/util/TestFacetsPayloadMigrationReader.java b/lucene/facet/src/test/org/apache/lucene/facet/util/TestFacetsPayloadMigrationReader.java deleted file mode 100644 index c7bb284fff5..00000000000 --- a/lucene/facet/src/test/org/apache/lucene/facet/util/TestFacetsPayloadMigrationReader.java +++ /dev/null @@ -1,412 +0,0 @@ -package org.apache.lucene.facet.util; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; - -import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; -import org.apache.lucene.analysis.tokenattributes.PayloadAttribute; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.Field.Store; -import org.apache.lucene.document.FieldType; -import org.apache.lucene.document.StringField; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.params.CategoryListParams; -import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy; -import org.apache.lucene.facet.params.FacetIndexingParams; -import org.apache.lucene.facet.params.FacetSearchParams; -import org.apache.lucene.facet.params.PerDimensionIndexingParams; -import org.apache.lucene.facet.params.PerDimensionOrdinalPolicy; -import org.apache.lucene.facet.search.CategoryListIterator; -import org.apache.lucene.facet.search.CountFacetRequest; -import org.apache.lucene.facet.search.DrillDownQuery; -import org.apache.lucene.facet.search.FacetRequest; -import org.apache.lucene.facet.search.FacetResult; -import org.apache.lucene.facet.search.FacetResultNode; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.taxonomy.FacetLabel; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.FieldInfo; -import org.apache.lucene.index.FieldInfo.IndexOptions; -import org.apache.lucene.index.FieldInfos; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.index.NoMergePolicy; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.Terms; -import org.apache.lucene.index.TermsEnum; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.MultiCollector; -import org.apache.lucene.search.PrefixQuery; -import org.apache.lucene.search.TotalHitCountCollector; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util.IntsRef; -import org.junit.Test; - -/* - * 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. - */ - -/** Tests facets index migration from payload to DocValues.*/ -public class TestFacetsPayloadMigrationReader extends FacetTestCase { - - private static class PayloadFacetFields extends FacetFields { - - private static final class CountingListStream extends TokenStream { - private final PayloadAttribute payloadAtt = addAttribute(PayloadAttribute.class); - private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class); - private final Iterator> categoriesData; - - CountingListStream(Map categoriesData) { - this.categoriesData = categoriesData.entrySet().iterator(); - } - - @Override - public boolean incrementToken() throws IOException { - if (!categoriesData.hasNext()) { - return false; - } - - Entry entry = categoriesData.next(); - termAtt.setEmpty().append(FacetsPayloadMigrationReader.PAYLOAD_TERM_TEXT + entry.getKey()); - payloadAtt.setPayload(entry.getValue()); - return true; - } - - } - - private static final FieldType COUNTING_LIST_PAYLOAD_TYPE = new FieldType(); - static { - COUNTING_LIST_PAYLOAD_TYPE.setIndexed(true); - COUNTING_LIST_PAYLOAD_TYPE.setTokenized(true); - COUNTING_LIST_PAYLOAD_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); - COUNTING_LIST_PAYLOAD_TYPE.setStored(false); - COUNTING_LIST_PAYLOAD_TYPE.setOmitNorms(true); - COUNTING_LIST_PAYLOAD_TYPE.freeze(); - } - - public PayloadFacetFields(TaxonomyWriter taxonomyWriter, FacetIndexingParams params) { - super(taxonomyWriter, params); - } - - @Override - protected FieldType drillDownFieldType() { - // Since the payload is indexed in the same field as the drill-down terms, - // we must set IndexOptions to DOCS_AND_FREQS_AND_POSITIONS - final FieldType type = new FieldType(TextField.TYPE_NOT_STORED); - type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); - type.freeze(); - return type; - } - - @Override - protected void addCountingListData(Document doc, Map categoriesData, String field) { - CountingListStream ts = new CountingListStream(categoriesData); - doc.add(new Field(field, ts, COUNTING_LIST_PAYLOAD_TYPE)); - } - } - - private static final String[] DIMENSIONS = new String[] { "dim1", "dim2", "dim3.1", "dim3.2" }; - - private HashMap createIndex(Directory indexDir, Directory taxoDir, FacetIndexingParams fip) - throws Exception { - Random random = random(); - IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)); - conf.setMaxBufferedDocs(2); // force few segments - conf.setMergePolicy(NoMergePolicy.COMPOUND_FILES); // avoid merges so that we're left with few segments - IndexWriter indexWriter = new IndexWriter(indexDir, conf); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); - - FacetFields facetFields = new PayloadFacetFields(taxoWriter, fip); - - HashMap expectedCounts = new HashMap(DIMENSIONS.length); - int numDocs = atLeast(10); - for (int i = 0; i < numDocs; i++) { - Document doc = new Document(); - int numCategories = random.nextInt(3) + 1; - ArrayList categories = new ArrayList(numCategories); - HashSet docDimensions = new HashSet(); - while (numCategories-- > 0) { - String dim = DIMENSIONS[random.nextInt(DIMENSIONS.length)]; - // we should only increment the expected count by 1 per document - docDimensions.add(dim); - categories.add(new FacetLabel(dim, Integer.toString(i), Integer.toString(numCategories))); - } - facetFields.addFields(doc, categories); - doc.add(new StringField("docid", Integer.toString(i), Store.YES)); - doc.add(new TextField("foo", "content" + i, Store.YES)); - indexWriter.addDocument(doc); - - // update expected count per dimension - for (String dim : docDimensions) { - Integer val = expectedCounts.get(dim); - if (val == null) { - expectedCounts.put(dim, Integer.valueOf(1)); - } else { - expectedCounts.put(dim, Integer.valueOf(val.intValue() + 1)); - } - } - - if (random.nextDouble() < 0.2) { // add some documents that will be deleted - doc = new Document(); - doc.add(new StringField("del", "key", Store.NO)); - facetFields.addFields(doc, Collections.singletonList(new FacetLabel("dummy"))); - indexWriter.addDocument(doc); - } - } - - indexWriter.commit(); - taxoWriter.commit(); - - // delete the docs that were marked for deletion. note that the 'dummy' - // category is not removed from the taxonomy, so must account for it when we - // verify the migrated index. - indexWriter.deleteDocuments(new Term("del", "key")); - indexWriter.commit(); - - IOUtils.close(indexWriter, taxoWriter); - - return expectedCounts; - } - - private void migrateIndex(Directory indexDir, FacetIndexingParams fip) throws Exception { - final Map fieldTerms = FacetsPayloadMigrationReader.buildFieldTermsMap(indexDir, fip); - DirectoryReader reader = DirectoryReader.open(indexDir); - List leaves = reader.leaves(); - int numReaders = leaves.size(); - AtomicReader wrappedLeaves[] = new AtomicReader[numReaders]; - for (int i = 0; i < numReaders; i++) { - wrappedLeaves[i] = new FacetsPayloadMigrationReader(leaves.get(i).reader(), fieldTerms); - } - - IndexWriter writer = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); - writer.deleteAll(); - try { - writer.addIndexes(new MultiReader(wrappedLeaves)); - writer.commit(); - } finally { - reader.close(); - writer.close(); - } - } - - private void verifyMigratedIndex(Directory indexDir, Directory taxoDir, HashMap expectedCounts, - FacetIndexingParams fip) throws Exception { - DirectoryReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); - IndexSearcher searcher = newSearcher(indexReader); - - assertFalse("index should not have deletions", indexReader.hasDeletions()); - - verifyNotFacetsData(indexReader, searcher); - verifyFacetedSearch(expectedCounts, fip, indexReader, taxoReader, searcher); - verifyDrillDown(expectedCounts, fip, indexReader, taxoReader, searcher); - verifyIndexOrdinals(indexReader, taxoReader, fip); - - IOUtils.close(indexReader, taxoReader); - } - - private void verifyNotFacetsData(DirectoryReader indexReader, IndexSearcher searcher) throws IOException { - // verify that non facets data was not damaged - TotalHitCountCollector total = new TotalHitCountCollector(); - searcher.search(new PrefixQuery(new Term("foo", "content")), total); - assertEquals("invalid number of results for content query", total.getTotalHits(), indexReader.maxDoc()); - - int numDocIDs = 0; - for (AtomicReaderContext context : indexReader.leaves()) { - Terms docIDs = context.reader().terms("docid"); - assertNotNull(docIDs); - TermsEnum te = docIDs.iterator(null); - while (te.next() != null) { - ++numDocIDs; - } - } - assertEquals("invalid number of docid terms", indexReader.maxDoc(), numDocIDs); - } - - private void verifyFacetedSearch(Map expectedCounts, FacetIndexingParams fip, - DirectoryReader indexReader, TaxonomyReader taxoReader, IndexSearcher searcher) throws IOException { - // run faceted search and assert expected counts - ArrayList requests = new ArrayList(expectedCounts.size()); - for (String dim : expectedCounts.keySet()) { - requests.add(new CountFacetRequest(new FacetLabel(dim), 5)); - } - FacetSearchParams fsp = new FacetSearchParams(fip, requests); - FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader); - MatchAllDocsQuery base = new MatchAllDocsQuery(); - searcher.search(base, fc); - List facetResults = fc.getFacetResults(); - assertEquals(requests.size(), facetResults.size()); - for (FacetResult res : facetResults) { - FacetResultNode node = res.getFacetResultNode(); - String dim = node.label.components[0]; - assertEquals("wrong count for " + dim, expectedCounts.get(dim).intValue(), (int) node.value); - } - } - - private void verifyDrillDown(Map expectedCounts, FacetIndexingParams fip, DirectoryReader indexReader, - TaxonomyReader taxoReader, IndexSearcher searcher) throws IOException { - // verify drill-down - for (String dim : expectedCounts.keySet()) { - FacetLabel drillDownCP = new FacetLabel(dim); - FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest(drillDownCP, 10)); - DrillDownQuery drillDown = new DrillDownQuery(fip, new MatchAllDocsQuery()); - drillDown.add(drillDownCP); - TotalHitCountCollector total = new TotalHitCountCollector(); - FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader); - searcher.search(drillDown, MultiCollector.wrap(fc, total)); - assertTrue("no results for drill-down query " + drillDown, total.getTotalHits() > 0); - List facetResults = fc.getFacetResults(); - assertEquals(1, facetResults.size()); - FacetResultNode rootNode = facetResults.get(0).getFacetResultNode(); - assertEquals("wrong count for " + dim, expectedCounts.get(dim).intValue(), (int) rootNode.value); - } - } - - private void verifyIndexOrdinals(DirectoryReader indexReader, TaxonomyReader taxoReader, FacetIndexingParams fip) - throws IOException { - // verify that the ordinals in the index match the ones in the taxonomy, and vice versa - - // collect all fields which have DocValues, to assert later that all were - // visited i.e. that during migration we didn't add FieldInfos with no - // DocValues - HashSet docValuesFields = new HashSet(); - for (AtomicReaderContext context : indexReader.leaves()) { - FieldInfos infos = context.reader().getFieldInfos(); - for (FieldInfo info : infos) { - if (info.hasDocValues()) { - docValuesFields.add(info.name); - } - } - } - - // check that all visited ordinals are found in the taxonomy and vice versa - boolean[] foundOrdinals = new boolean[taxoReader.getSize()]; - for (int i = 0; i < foundOrdinals.length; i++) { - foundOrdinals[i] = false; // init to be on the safe side - } - foundOrdinals[0] = true; // ROOT ordinals isn't indexed - // mark 'dummy' category ordinal as seen - int dummyOrdinal = taxoReader.getOrdinal(new FacetLabel("dummy")); - if (dummyOrdinal > 0) { - foundOrdinals[dummyOrdinal] = true; - } - - int partitionSize = fip.getPartitionSize(); - int numPartitions = (int) Math.ceil(taxoReader.getSize() / (double) partitionSize); - final IntsRef ordinals = new IntsRef(32); - for (String dim : DIMENSIONS) { - CategoryListParams clp = fip.getCategoryListParams(new FacetLabel(dim)); - int partitionOffset = 0; - for (int partition = 0; partition < numPartitions; partition++, partitionOffset += partitionSize) { - final CategoryListIterator cli = clp.createCategoryListIterator(partition); - for (AtomicReaderContext context : indexReader.leaves()) { - if (cli.setNextReader(context)) { // not all fields may exist in all segments - // remove that field from the list of DocValues fields - docValuesFields.remove(clp.field + PartitionsUtils.partitionName(partition)); - int maxDoc = context.reader().maxDoc(); - for (int doc = 0; doc < maxDoc; doc++) { - cli.getOrdinals(doc, ordinals); - for (int j = 0; j < ordinals.length; j++) { - // verify that the ordinal is recognized by the taxonomy - int ordinal = ordinals.ints[j] + partitionOffset; - assertTrue("should not have received dummy ordinal (" + dummyOrdinal + ")", dummyOrdinal != ordinal); - assertNotNull("missing category for ordinal " + ordinal, taxoReader.getPath(ordinal)); - foundOrdinals[ordinal] = true; - } - } - } - } - } - } - - assertTrue("some fields which have docValues were not visited: " + docValuesFields, docValuesFields.isEmpty()); - - for (int i = 0; i < foundOrdinals.length; i++) { - assertTrue("ordinal " + i + " not visited", foundOrdinals[i]); - } - } - - private void doTestMigration(final int partitionSize) throws Exception { - // create a facets index with PayloadFacetFields and check it after migration - Directory indexDir = newDirectory(); - Directory taxoDir = newDirectory(); - - // set custom CLP fields for two dimensions and use the default ($facets) for the other two - HashMap params = new HashMap(); - params.put(new FacetLabel(DIMENSIONS[0]), new CategoryListParams(DIMENSIONS[0]) { - @Override - public OrdinalPolicy getOrdinalPolicy(String dimension) { - return OrdinalPolicy.ALL_PARENTS; - } - }); - params.put(new FacetLabel(DIMENSIONS[1]), new CategoryListParams(DIMENSIONS[1]) { - @Override - public OrdinalPolicy getOrdinalPolicy(String dimension) { - return OrdinalPolicy.ALL_PARENTS; - } - }); - - HashMap policies = new HashMap(); - policies.put(DIMENSIONS[2], OrdinalPolicy.ALL_PARENTS); - policies.put(DIMENSIONS[3], OrdinalPolicy.ALL_PARENTS); - FacetIndexingParams fip = new PerDimensionIndexingParams(params, new PerDimensionOrdinalPolicy(policies)) { - @Override - public int getPartitionSize() { - return partitionSize; - } - }; - - HashMap expectedCounts = createIndex(indexDir, taxoDir, fip); - migrateIndex(indexDir, fip); - verifyMigratedIndex(indexDir, taxoDir, expectedCounts, fip); - - IOUtils.close(indexDir, taxoDir); - } - - @Test - public void testMigration() throws Exception { - doTestMigration(Integer.MAX_VALUE); - } - - @Test - public void testMigrationWithPartitions() throws Exception { - doTestMigration(2); - } - -}