// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/DistinctDateFacet.java
// public abstract class DistinctDateFacet<P extends ToXContent> extends DateFacet<P> implements HasDistinct {
// 
//     /**
//      * Create a new distinct date facet.
//      * 
//      * @param name the facet name
//      */
//     public DistinctDateFacet(final String name) {
//         super(name);
//     }
// 
//     @Override
//     protected void injectHeaderXContent(final XContentBuilder builder) throws IOException {
//         builder.field(Constants.DISTINCT_COUNT, getDistinctCount());
//     }
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/DistinctTimePeriod.java
// public class DistinctTimePeriod<E extends ToXContent> extends TimePeriod<E> {
// 
//     private final long _distinctCount;
// 
//     /**
//      * Create a new DistinctTimePeriod.
//      * 
//      * @param time the timestamp of this period
//      * @param count the count of values in this period
//      * @param distinctCount the count of distinct values in this period
//      * @param entry the actual facet entry for this time period
//      */
//     public DistinctTimePeriod(final long time, final long count,
//             final long distinctCount, final E entry) {
//         super(time, count, entry);
//         _distinctCount = distinctCount;
//     }
// 
//     /**
//      * Get the distinct count for this time period.
//      * 
//      * @return the distinct count
//      */
//     public long getDistinctCount() {
//         return _distinctCount;
//     }
// 
//     @Override
//     protected void injectEntryHeaderXContent(final XContentBuilder builder) throws IOException {
//         builder.field(Constants.DISTINCT_COUNT, getDistinctCount());
//     }
// 
//     @Override
//     protected void injectEntryFooterXContent(final XContentBuilder builder) throws IOException {}
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/HasDistinct.java
// public interface HasDistinct {
// 
//     /**
//      * Get the distinct count.
//      * 
//      * @return the distinct count
//      */
//     long getDistinctCount();
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/NullEntry.java
// public enum NullEntry implements ToXContent {
// 
//     /**
//      * The only instance of NullEntry you'll ever need.
//      */
//     INSTANCE;
// 
//     @Override
//     public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
//         return builder;
//     }
// 
// }


import static com.google.common.collect.Lists.newArrayListWithCapacity;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.elasticsearch.common.CacheRecycler;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.bytes.HashedBytesArray;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.trove.ExtTLongObjectHashMap;
import org.elasticsearch.common.trove.procedure.TLongObjectProcedure;
import org.elasticsearch.search.facet.Facet;
import com.clearspring.analytics.stream.cardinality.CardinalityMergeException;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.DistinctDateFacet;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.DistinctTimePeriod;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.HasDistinct;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.NullEntry;
        _distinctCount = _materializePeriod.getOverallDistinct();
        _materializePeriod.clear();
        releaseCache();
    }

    @Override
    protected void releaseCache() {
        CacheRecycler.pushLongObjectMap(_counts);
    }

    private final PeriodMerger _mergePeriods = new PeriodMerger();

    private static class PeriodMerger implements TLongObjectProcedure<DistinctCountPayload> {

        InternalDistinctFacet target;

        // Called once per period
        @Override
        public boolean execute(final long time, final DistinctCountPayload payload) {
            // These objects already know how to merge themselves
            payload.mergeInto(target._counts, time);
            return true;
        }

    }

    private final PeriodMaterializer _materializePeriod = new PeriodMaterializer();

    private static final class PeriodMaterializer implements TLongObjectProcedure<DistinctCountPayload> {

// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/DistinctDateFacet.java
// public abstract class DistinctDateFacet<P extends ToXContent> extends DateFacet<P> implements HasDistinct {
// 
//     /**
//      * Create a new distinct date facet.
//      * 
//      * @param name the facet name
//      */
//     public DistinctDateFacet(final String name) {
//         super(name);
//     }
// 
//     @Override
//     protected void injectHeaderXContent(final XContentBuilder builder) throws IOException {
//         builder.field(Constants.DISTINCT_COUNT, getDistinctCount());
//     }
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/DistinctTimePeriod.java
// public class DistinctTimePeriod<E extends ToXContent> extends TimePeriod<E> {
// 
//     private final long _distinctCount;
// 
//     /**
//      * Create a new DistinctTimePeriod.
//      * 
//      * @param time the timestamp of this period
//      * @param count the count of values in this period
//      * @param distinctCount the count of distinct values in this period
//      * @param entry the actual facet entry for this time period
//      */
//     public DistinctTimePeriod(final long time, final long count,
//             final long distinctCount, final E entry) {
//         super(time, count, entry);
//         _distinctCount = distinctCount;
//     }
// 
//     /**
//      * Get the distinct count for this time period.
//      * 
//      * @return the distinct count
//      */
//     public long getDistinctCount() {
//         return _distinctCount;
//     }
// 
//     @Override
//     protected void injectEntryHeaderXContent(final XContentBuilder builder) throws IOException {
//         builder.field(Constants.DISTINCT_COUNT, getDistinctCount());
//     }
// 
//     @Override
//     protected void injectEntryFooterXContent(final XContentBuilder builder) throws IOException {}
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/HasDistinct.java
// public interface HasDistinct {
// 
//     /**
//      * Get the distinct count.
//      * 
//      * @return the distinct count
//      */
//     long getDistinctCount();
// 
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/external/NullEntry.java
// public enum NullEntry implements ToXContent {
// 
//     /**
//      * The only instance of NullEntry you'll ever need.
//      */
//     INSTANCE;
// 
//     @Override
//     public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
//         return builder;
//     }
// 
// }


// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/internal/InternalDistinctFacet.java
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.elasticsearch.common.CacheRecycler;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.bytes.HashedBytesArray;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.trove.ExtTLongObjectHashMap;
import org.elasticsearch.common.trove.procedure.TLongObjectProcedure;
import org.elasticsearch.search.facet.Facet;
import com.clearspring.analytics.stream.cardinality.CardinalityMergeException;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.DistinctDateFacet;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.DistinctTimePeriod;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.HasDistinct;
import com.pearson.entech.elasticsearch.search.facet.approx.date.external.NullEntry;

        _distinctCount = _materializePeriod.getOverallDistinct();
        _materializePeriod.clear();
        releaseCache();
    }

    @Override
    protected void releaseCache() {
        CacheRecycler.pushLongObjectMap(_counts);
    }

    private final PeriodMerger _mergePeriods = new PeriodMerger();

    private static class PeriodMerger implements TLongObjectProcedure<DistinctCountPayload> {

        InternalDistinctFacet target;

        // Called once per period
        @Override
        public boolean execute(final long time, final DistinctCountPayload payload) {
            // These objects already know how to merge themselves
            payload.mergeInto(target._counts, time);
            return true;
        }

    }

    private final PeriodMaterializer _materializePeriod = new PeriodMaterializer();

    private static final class PeriodMaterializer implements TLongObjectProcedure<DistinctCountPayload> {

        private List<DistinctTimePeriod<NullEntry>> _target;