--- /dev/null
+package org.apache.lucene.facet.search;
+
+import java.io.IOException;
+
+import org.apache.lucene.facet.search.params.FacetRequest;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.search.results.FacetResultNode;
+import org.apache.lucene.facet.search.results.IntermediateFacetResult;
+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.
+ */
+
+/**
+ * Handler for facet results.
+ * <p>
+ * The facet results handler provided by the {@link FacetRequest} to
+ * a {@link FacetsAccumulator}.
+ * <p>
+ * First it is used by {@link FacetsAccumulator} to obtain a temporary
+ * facet result for each partition and to merge results of several partitions.
+ * <p>
+ * Later the accumulator invokes the handler to render the results, creating
+ * {@link FacetResult} objects.
+ * <p>
+ * Last the accumulator invokes the handler to label final results.
+ *
+ * @lucene.experimental
+ */
+public abstract class FacetResultsHandler {
+
+ /** Taxonomy for which facets are handled */
+ protected final TaxonomyReader taxonomyReader;
+
+ /**
+ * Facet request served by this handler.
+ */
+ protected final FacetRequest facetRequest;
+
+ /**
+ * Create a faceted search handler.
+ * @param taxonomyReader See {@link #getTaxonomyReader()}.
+ * @param facetRequest See {@link #getFacetRequest()}.
+ */
+ public FacetResultsHandler(TaxonomyReader taxonomyReader,
+ FacetRequest facetRequest) {
+ this.taxonomyReader = taxonomyReader;
+ this.facetRequest = facetRequest;
+ }
+
+ /**
+ * Fetch results of a single partition, given facet arrays for that partition,
+ * and based on the matching documents and faceted search parameters.
+ *
+ * @param arrays
+ * facet arrays for the certain partition
+ * @param offset
+ * offset in input arrays where partition starts
+ * @return temporary facet result, potentially, to be passed back to
+ * <b>this</b> result handler for merging, or <b>null</b> in case that
+ * constructor parameter, <code>facetRequest</code>, requests an
+ * illegal FacetResult, like, e.g., a root node category path that
+ * does not exist in constructor parameter <code>taxonomyReader</code>
+ * .
+ * @throws IOException
+ * on error
+ */
+ public abstract IntermediateFacetResult fetchPartitionResult(FacetArrays arrays, 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 <b>this</b>
+ * handler.
+ * @return temporary facet result that represents to union, as specified by
+ * <b>this</b> 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 <code>facetResults</code> do not
+ * have the same {@link FacetRequest}
+ * @see IntermediateFacetResult#getFacetRequest()
+ */
+ public abstract IntermediateFacetResult mergeResults(IntermediateFacetResult... tmpResults)
+ throws IOException, ClassCastException, IllegalArgumentException;
+
+ /**
+ * 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.
+ * <P>
+ * 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#setValue(double)
+ */
+ public abstract FacetResult rearrangeFacetResult(FacetResult facetResult);
+
+ /**
+ * Label results according to settings in {@link FacetRequest},
+ * such as {@link FacetRequest#getNumLabel()}.
+ * Usually invoked by {@link FacetsAccumulator#accumulate(ScoredDocIDs)}
+ * @param facetResult facet result to be labeled.
+ * @throws IOException on error
+ */
+ public abstract void labelResult (FacetResult facetResult) throws IOException;
+
+ /** Return taxonomy reader used for current facets accumulation operation. */
+ public final TaxonomyReader getTaxonomyReader() {
+ return this.taxonomyReader;
+ }
+
+ /** Return the facet request served by this handler. */
+ public final FacetRequest getFacetRequest() {
+ return this.facetRequest;
+ }
+
+ /**
+ * 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.getArraysLength();
+ return ordinal / partitionSize == offset / partitionSize;
+ }
+
+}