// Path: src/main/java/com/pearson/entech/elasticsearch/plugin/approx/BytesRefUtils.java
// public static void process(final BytesRefHash hash, final Procedure proc) {
//     int[] ids;
//     try {
//         ids = (int[]) getCompactMethod().invoke(hash, __emptyParams);
//     } catch(final IllegalAccessException e) {
//         throw new RuntimeException(e);
//     } catch(final InvocationTargetException e) {
//         throw new RuntimeException(e);
//     }
//     final BytesRef scratch = new BytesRef();
//     for(int i = 0; i < ids.length; i++) {
//         final int id = ids[i];
//         if(id < 0)
//             break;
//         hash.get(id, scratch);
//         try {
//             proc.consume(scratch);
//         } catch(final Exception e) {
//             throw new IllegalStateException(e);
//         }
//     }
//     hash.clear();
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/plugin/approx/BytesRefUtils.java
// public static interface Procedure {
// 
//     /**
//      * Called once for each BytesRef.
//      * 
//      * @param ref the BytesRef
//      * @throws Exception
//      */
//     void consume(BytesRef ref) throws Exception;
// 
// }


import static com.pearson.entech.elasticsearch.plugin.approx.BytesRefUtils.process;
import java.io.ByteArrayInputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.lucene.codecs.bloom.MurmurHash2;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefHash;
import com.clearspring.analytics.stream.cardinality.AdaptiveCounting;
import com.clearspring.analytics.stream.cardinality.CardinalityMergeException;
import com.clearspring.analytics.stream.cardinality.HyperLogLog;
import com.clearspring.analytics.stream.cardinality.HyperLogLogPlus;
import com.clearspring.analytics.stream.cardinality.ICardinality;
import com.clearspring.analytics.stream.cardinality.LinearCounting;
import com.clearspring.analytics.stream.cardinality.LogLog;
import com.clearspring.analytics.util.ExternalizableUtil;
import com.clearspring.analytics.util.IBuilder;
import com.pearson.entech.elasticsearch.plugin.approx.BytesRefUtils.Procedure;

    @Override
    public void writeExternal(final ObjectOutput out) throws IOException {
        out.writeBoolean(_tipped);
        if(_tipped) {

            if(_estimator instanceof LinearCounting)
                out.writeByte(LC);
            else if(_estimator instanceof AdaptiveCounting)
                out.writeByte(AC);
            else if(_estimator instanceof HyperLogLog)
                out.writeByte(HLC);
            else if(_estimator instanceof HyperLogLogPlus)
                out.writeByte(HLPC);
            else if(_estimator instanceof LogLog)
                out.writeByte(LLC);
            else
                throw new IOException("Estimator unsupported for serialization: " + _estimator.getClass().getName());

            final byte[] bytes = _estimator.getBytes();
            out.writeInt(bytes.length);
            out.write(bytes);

        } else {

            out.writeInt(_tippingPoint);
            out.writeObject(_builder);
            out.writeInt(_counter.size());
            out.writeInt(_longestBytesRefSize);

// Path: src/main/java/com/pearson/entech/elasticsearch/plugin/approx/BytesRefUtils.java
// public static void process(final BytesRefHash hash, final Procedure proc) {
//     int[] ids;
//     try {
//         ids = (int[]) getCompactMethod().invoke(hash, __emptyParams);
//     } catch(final IllegalAccessException e) {
//         throw new RuntimeException(e);
//     } catch(final InvocationTargetException e) {
//         throw new RuntimeException(e);
//     }
//     final BytesRef scratch = new BytesRef();
//     for(int i = 0; i < ids.length; i++) {
//         final int id = ids[i];
//         if(id < 0)
//             break;
//         hash.get(id, scratch);
//         try {
//             proc.consume(scratch);
//         } catch(final Exception e) {
//             throw new IllegalStateException(e);
//         }
//     }
//     hash.clear();
// }
// 
// Path: src/main/java/com/pearson/entech/elasticsearch/plugin/approx/BytesRefUtils.java
// public static interface Procedure {
// 
//     /**
//      * Called once for each BytesRef.
//      * 
//      * @param ref the BytesRef
//      * @throws Exception
//      */
//     void consume(BytesRef ref) throws Exception;
// 
// }


// Path: src/main/java/com/pearson/entech/elasticsearch/search/facet/approx/date/internal/CountThenEstimateBytes.java
import static com.pearson.entech.elasticsearch.plugin.approx.BytesRefUtils.process;
import java.io.ByteArrayInputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.lucene.codecs.bloom.MurmurHash2;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefHash;
import com.clearspring.analytics.stream.cardinality.AdaptiveCounting;
import com.clearspring.analytics.stream.cardinality.CardinalityMergeException;
import com.clearspring.analytics.stream.cardinality.HyperLogLog;
import com.clearspring.analytics.stream.cardinality.HyperLogLogPlus;
import com.clearspring.analytics.stream.cardinality.ICardinality;
import com.clearspring.analytics.stream.cardinality.LinearCounting;
import com.clearspring.analytics.stream.cardinality.LogLog;
import com.clearspring.analytics.util.ExternalizableUtil;
import com.clearspring.analytics.util.IBuilder;
import com.pearson.entech.elasticsearch.plugin.approx.BytesRefUtils.Procedure;


    @Override
    public void writeExternal(final ObjectOutput out) throws IOException {
        out.writeBoolean(_tipped);
        if(_tipped) {

            if(_estimator instanceof LinearCounting)
                out.writeByte(LC);
            else if(_estimator instanceof AdaptiveCounting)
                out.writeByte(AC);
            else if(_estimator instanceof HyperLogLog)
                out.writeByte(HLC);
            else if(_estimator instanceof HyperLogLogPlus)
                out.writeByte(HLPC);
            else if(_estimator instanceof LogLog)
                out.writeByte(LLC);
            else
                throw new IOException("Estimator unsupported for serialization: " + _estimator.getClass().getName());

            final byte[] bytes = _estimator.getBytes();
            out.writeInt(bytes.length);
            out.write(bytes);

        } else {

            out.writeInt(_tippingPoint);
            out.writeObject(_builder);
            out.writeInt(_counter.size());
            out.writeInt(_longestBytesRefSize);

            process(_counter, new Procedure() {