io.druid.query.aggregation.histogram.ApproximateHistogramAggregatorFactory.java Source code

Java tutorial

Introduction

Here is the source code for io.druid.query.aggregation.histogram.ApproximateHistogramAggregatorFactory.java

Source

/*
 * Druid - a distributed column store.
 * Copyright 2012 - 2015 Metamarkets Group Inc.
 *
 * Licensed 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.
 */

package io.druid.query.aggregation.histogram;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Floats;
import com.google.common.primitives.Ints;
import com.metamx.common.StringUtils;
import io.druid.query.aggregation.Aggregator;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.aggregation.BufferAggregator;
import io.druid.segment.ColumnSelectorFactory;
import org.apache.commons.codec.binary.Base64;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

@JsonTypeName("approxHistogram")
public class ApproximateHistogramAggregatorFactory implements AggregatorFactory {
    private static final byte CACHE_TYPE_ID = 0x8;

    protected final String name;
    protected final String fieldName;

    protected final int resolution;
    protected final int numBuckets;

    protected final float lowerLimit;
    protected final float upperLimit;

    @JsonCreator
    public ApproximateHistogramAggregatorFactory(@JsonProperty("name") String name,
            @JsonProperty("fieldName") String fieldName, @JsonProperty("resolution") Integer resolution,
            @JsonProperty("numBuckets") Integer numBuckets, @JsonProperty("lowerLimit") Float lowerLimit,
            @JsonProperty("upperLimit") Float upperLimit

    ) {
        this.name = name;
        this.fieldName = fieldName;
        this.resolution = resolution == null ? ApproximateHistogram.DEFAULT_HISTOGRAM_SIZE : resolution;
        this.numBuckets = numBuckets == null ? ApproximateHistogram.DEFAULT_BUCKET_SIZE : numBuckets;
        this.lowerLimit = lowerLimit == null ? Float.NEGATIVE_INFINITY : lowerLimit;
        this.upperLimit = upperLimit == null ? Float.POSITIVE_INFINITY : upperLimit;

        Preconditions.checkArgument(this.resolution > 0, "resolution must be greater than 1");
        Preconditions.checkArgument(this.numBuckets > 0, "numBuckets must be greater than 1");
        Preconditions.checkArgument(this.upperLimit > this.lowerLimit,
                "upperLimit must be greater than lowerLimit");
    }

    @Override
    public Aggregator factorize(ColumnSelectorFactory metricFactory) {
        return new ApproximateHistogramAggregator(name, metricFactory.makeFloatColumnSelector(fieldName),
                resolution, lowerLimit, upperLimit);
    }

    @Override
    public BufferAggregator factorizeBuffered(ColumnSelectorFactory metricFactory) {
        return new ApproximateHistogramBufferAggregator(metricFactory.makeFloatColumnSelector(fieldName),
                resolution, lowerLimit, upperLimit);
    }

    @Override
    public Comparator getComparator() {
        return ApproximateHistogramAggregator.COMPARATOR;
    }

    @Override
    public Object combine(Object lhs, Object rhs) {
        return ApproximateHistogramAggregator.combineHistograms(lhs, rhs);
    }

    @Override
    public AggregatorFactory getCombiningFactory() {
        return new ApproximateHistogramFoldingAggregatorFactory(name, name, resolution, numBuckets, lowerLimit,
                upperLimit);
    }

    @Override
    public List<AggregatorFactory> getRequiredColumns() {
        return Arrays.<AggregatorFactory>asList(new ApproximateHistogramAggregatorFactory(fieldName, fieldName,
                resolution, numBuckets, lowerLimit, upperLimit));
    }

    @Override
    public Object deserialize(Object object) {
        if (object instanceof byte[]) {
            final ApproximateHistogram ah = ApproximateHistogram.fromBytes((byte[]) object);
            ah.setLowerLimit(lowerLimit);
            ah.setUpperLimit(upperLimit);

            return ah;
        } else if (object instanceof ByteBuffer) {
            final ApproximateHistogram ah = ApproximateHistogram.fromBytes((ByteBuffer) object);
            ah.setLowerLimit(lowerLimit);
            ah.setUpperLimit(upperLimit);

            return ah;
        } else if (object instanceof String) {
            byte[] bytes = Base64.decodeBase64(StringUtils.toUtf8((String) object));
            final ApproximateHistogram ah = ApproximateHistogram.fromBytes(bytes);
            ah.setLowerLimit(lowerLimit);
            ah.setUpperLimit(upperLimit);

            return ah;
        } else {
            return object;
        }
    }

    @Override
    public Object finalizeComputation(Object object) {
        return ((ApproximateHistogram) object).toHistogram(numBuckets);
    }

    @JsonProperty
    @Override
    public String getName() {
        return name;
    }

    @JsonProperty
    public String getFieldName() {
        return fieldName;
    }

    @JsonProperty
    public int getResolution() {
        return resolution;
    }

    @JsonProperty
    public float getLowerLimit() {
        return lowerLimit;
    }

    @JsonProperty
    public float getUpperLimit() {
        return upperLimit;
    }

    @JsonProperty
    public int getNumBuckets() {
        return numBuckets;
    }

    @Override
    public List<String> requiredFields() {
        return Arrays.asList(fieldName);
    }

    @Override
    public byte[] getCacheKey() {
        byte[] fieldNameBytes = StringUtils.toUtf8(fieldName);
        return ByteBuffer.allocate(1 + fieldNameBytes.length + Ints.BYTES * 2 + Floats.BYTES * 2).put(CACHE_TYPE_ID)
                .put(fieldNameBytes).putInt(resolution).putInt(numBuckets).putFloat(lowerLimit).putFloat(upperLimit)
                .array();
    }

    @Override
    public String getTypeName() {
        return "approximateHistogram";
    }

    @Override
    public int getMaxIntermediateSize() {
        return new ApproximateHistogram(resolution).getMaxStorageSize();
    }

    @Override
    public Object getAggregatorStartValue() {
        return new ApproximateHistogram(resolution);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        ApproximateHistogramAggregatorFactory that = (ApproximateHistogramAggregatorFactory) o;

        if (Float.compare(that.lowerLimit, lowerLimit) != 0) {
            return false;
        }
        if (numBuckets != that.numBuckets) {
            return false;
        }
        if (resolution != that.resolution) {
            return false;
        }
        if (Float.compare(that.upperLimit, upperLimit) != 0) {
            return false;
        }
        if (fieldName != null ? !fieldName.equals(that.fieldName) : that.fieldName != null) {
            return false;
        }
        if (name != null ? !name.equals(that.name) : that.name != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (fieldName != null ? fieldName.hashCode() : 0);
        result = 31 * result + resolution;
        result = 31 * result + numBuckets;
        result = 31 * result + (lowerLimit != +0.0f ? Float.floatToIntBits(lowerLimit) : 0);
        result = 31 * result + (upperLimit != +0.0f ? Float.floatToIntBits(upperLimit) : 0);
        return result;
    }

    @Override
    public String toString() {
        return "ApproximateHistogramAggregatorFactory{" + "name='" + name + '\'' + ", fieldName='" + fieldName
                + '\'' + ", resolution=" + resolution + ", numBuckets=" + numBuckets + ", lowerLimit=" + lowerLimit
                + ", upperLimit=" + upperLimit + '}';
    }
}