net.sf.jasperreports.data.cache.LongArrayStore.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jasperreports.data.cache.LongArrayStore.java

Source

/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
 */
package net.sf.jasperreports.data.cache;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Lucian Chirita (lucianc@users.sourceforge.net)
 */
public class LongArrayStore implements BufferColumnStore, ArrayStore {

    private static final Log log = LogFactory.getLog(LongArrayStore.class);

    private final boolean useGCD;
    private final ValueTransformer valueTransformer;

    private final long[] values;

    private int count;

    private long min;
    private long max;

    private RunLengthStore runLengthStore;

    public LongArrayStore(int size) {
        this(size, null, false);
    }

    public LongArrayStore(int size, ValueTransformer valueTransformer) {
        this(size, valueTransformer, false);
    }

    public LongArrayStore(int size, boolean useGCD) {
        this(size, null, useGCD);
    }

    @Override
    public Class<?> getBaseValuesType() {
        return valueTransformer == null ? Number.class : valueTransformer.getResultType();
    }

    public LongArrayStore(int size, ValueTransformer valueTransformer, boolean useGCD) {
        this.useGCD = useGCD;
        this.valueTransformer = valueTransformer;

        this.values = new long[size];
        this.runLengthStore = new RunLengthStore(this);
        reset();
    }

    private void reset() {
        this.count = 0;

        this.min = Long.MAX_VALUE;
        this.max = Long.MIN_VALUE;

        this.runLengthStore.reset();
    }

    @Override
    public int count() {
        return count;
    }

    @Override
    public boolean valuesEqual(int idx1, int idx2) {
        return values[idx1] == values[idx2];
    }

    @Override
    public void copyValue(int destIdx, int sourceIdx) {
        values[destIdx] = values[sourceIdx];
    }

    @Override
    public void updateCount(int count) {
        this.count = count;
    }

    public void add(long value) {
        values[count] = value;
        ++count;

        if (value < min) {
            min = value;
        }
        if (value > max) {
            max = value;
        }

        runLengthStore.valueAdded();
    }

    @Override
    public void addValue(Object value) {
        if (value instanceof Integer || value instanceof Long || value instanceof Byte || value instanceof Short) {
            add(((Number) value).longValue());
        } else if (value instanceof Character) {
            add(((Character) value).charValue());
        } else {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public boolean full() {
        return count >= values.length;
    }

    @Override
    public void resetValues() {
        reset();
    }

    @Override
    public ColumnValues createValues() {
        if (count == 0) {
            // no values
            if (log.isDebugEnabled()) {
                log.debug(this + ": no values");
            }

            return EmptyColumnValues.instance();
        }

        if (min == max) {
            // constant value
            if (log.isDebugEnabled()) {
                log.debug(this + ": constant value of size " + count);
            }

            //FIXME keep value as primitive?
            // transform the value so that we don't need to store the transformer
            Object value = valueTransformer == null ? min : valueTransformer.get(min);
            return new ConstantColumnValue(count, value);
        }

        long linearOffset = 0;
        long linearFactor = 1;

        if (min != 0) {
            linearOffset = min;

            if (log.isDebugEnabled()) {
                log.debug(this + ": using offset " + linearOffset);
            }

            // apply min
            for (int i = 0; i < count; i++) {
                values[i] -= linearOffset;
            }

            min = 0;
            max -= linearOffset;
        }

        if (useGCD) {
            long gcd = computeGCD();
            if (gcd > 1) {
                if (log.isDebugEnabled()) {
                    log.debug(this + ": using factor " + gcd);
                }

                for (int i = 0; i < count; i++) {
                    values[i] /= gcd;
                }

                max /= gcd;
                linearFactor = gcd;
            }
        }

        int originalCount = count;
        ValueLength valueLength = ValueLength.getNumberLength(max);
        ColumnValues runLengthValues = runLengthStore.applyRunLengths(valueLength);

        if (log.isDebugEnabled()) {
            log.debug(this + ": creating values of count " + count + ", value length " + valueLength);
        }

        ColumnValues colValues = NumberValuesUtils.instance().toValues(count, values, valueLength, linearFactor,
                linearOffset);
        if (valueTransformer != null) {
            colValues = new TransformedColumnValues(colValues, valueTransformer);
        }

        ColumnValues finalValues;
        if (runLengthValues == null) {
            finalValues = colValues;
        } else {
            finalValues = new RunLengthColumnValues(originalCount, colValues, runLengthValues);
        }
        return finalValues;
    }

    protected long computeGCD() {
        long gcd = values[0] - min;
        for (int i = 1; i < count; i++) {
            gcd = gcd(gcd, values[i] - min);
            if (gcd == 1) {
                return gcd;
            }
        }
        return gcd;
    }

    private static long gcd(long a, long b) {
        if (b == 0) {
            return a;
        }

        while (a > 0) {
            long t = a;
            a = b % a;
            b = t;
        }
        return b;
    }

    @Override
    public String toString() {
        return "LongArrayStore@" + hashCode();
    }

}