com.asoroka.sidora.tabularmetadata.heuristics.ranges.RunningMinMaxHeuristic.java Source code

Java tutorial

Introduction

Here is the source code for com.asoroka.sidora.tabularmetadata.heuristics.ranges.RunningMinMaxHeuristic.java

Source

/**
 * TEMPORARY LICENSE HEADER STANDIN
 * REPLACE WITH APPROPRIATE SIDORA LICENSE
 */

package com.asoroka.sidora.tabularmetadata.heuristics.ranges;

import static com.asoroka.sidora.tabularmetadata.datatype.DataType.parseableAs;
import static com.google.common.collect.Maps.asMap;
import static com.google.common.collect.Ordering.natural;
import static com.google.common.collect.Range.atLeast;
import static com.google.common.collect.Range.atMost;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.EnumMap;
import java.util.Map;

import org.slf4j.Logger;

import com.asoroka.sidora.tabularmetadata.datatype.DataType;
import com.asoroka.sidora.tabularmetadata.datatype.ParsingException;
import com.asoroka.sidora.tabularmetadata.heuristics.AbstractHeuristic;
import com.google.common.base.Function;
import com.google.common.collect.Range;

/**
 * Calculates the ranges of values supplied for each possible parseable type, without caching the values supplied.
 * 
 * @author A. Soroka
 */
public class RunningMinMaxHeuristic extends AbstractHeuristic<RunningMinMaxHeuristic, Map<DataType, Range<?>>>
        implements RangeDeterminingHeuristic<RunningMinMaxHeuristic> {

    /**
     * A {@link Map} from data types to the minimum value from all presented values that were parseable in that type.
     */
    protected Map<DataType, Comparable<?>> minimums;

    /**
     * A {@link Map} from data types to the maximum value from all presented values that were parseable in that type.
     */
    protected Map<DataType, Comparable<?>> maximums;

    private static final Logger log = getLogger(RunningMinMaxHeuristic.class);

    /**
     * Initialize minimums and maximums.
     */
    @Override
    public void reset() {
        this.minimums = new EnumMap<>(DataType.class);
        this.maximums = new EnumMap<>(DataType.class);
    }

    @Override
    public boolean addValue(final String value) {
        for (final DataType type : parseableAs(value)) {
            final Comparable<?> currentMin = minimums.get(type);
            final Comparable<?> currentMax = maximums.get(type);
            try {
                final Comparable<?> v = type.parse(value);
                log.trace("Trying new value {} against current min {} and current max {} for type {}", v,
                        currentMin, currentMax, type);
                // TODO avoid this repeated conditional
                minimums.put(type, (currentMin == null) ? v : natural().min(currentMin, v));
                maximums.put(type, (currentMax == null) ? v : natural().max(currentMax, v));
                log.trace("Tried new value {} and got new min {} and new max {} for type {}", v, minimums.get(type),
                        maximums.get(type), type);

            } catch (final ParsingException e) {
                // we are only parsing for types that have already been checked
                throw new AssertionError("Could not parse to a type that was passed as parsing!", e);
            }
        }
        return true;
    }

    @Override
    public Map<DataType, Range<?>> results() {
        return asMap(DataType.valuesSet(), getRangeForType());
    }

    private Function<DataType, Range<?>> getRangeForType() {
        return new Function<DataType, Range<?>>() {

            @Override
            public Range<?> apply(final DataType type) {
                final boolean hasMin = minimums.containsKey(type);
                final boolean hasMax = maximums.containsKey(type);
                final Comparable<?> min = minimums.get(type);
                final Comparable<?> max = maximums.get(type);
                if (hasMin) {
                    if (hasMax) {
                        return Range.closed(min, max);
                    }
                    return atLeast(min);
                }
                if (hasMax) {
                    return atMost(max);
                }
                return Range.all();
            }
        };
    }

    @Override
    public RunningMinMaxHeuristic get() {
        return new RunningMinMaxHeuristic();
    }
}