com.skelril.nitro.point.ValueMapping.java Source code

Java tutorial

Introduction

Here is the source code for com.skelril.nitro.point.ValueMapping.java

Source

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package com.skelril.nitro.point;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.lang3.Validate;

import java.util.*;
import java.util.function.BiFunction;

public abstract class ValueMapping<KeyType, IndexType, PointType extends Comparable<PointType>> {
    protected List<PointValue<KeyType, PointType>> values;
    protected PointType zeroValue, oneValue;
    protected BiFunction<PointType, PointType, PointType> pointTypeDiv, pointTypeMod;

    protected Multimap<IndexType, PointValue<KeyType, PointType>> valueMap = ArrayListMultimap.create();

    public ValueMapping(List<PointValue<KeyType, PointType>> values, PointType zeroValue, PointType oneValue,
            BiFunction<PointType, PointType, PointType> pointTypeDiv,
            BiFunction<PointType, PointType, PointType> pointTypeMod) {
        this.values = new ArrayList<>(values);
        this.zeroValue = zeroValue;
        this.oneValue = oneValue;
        this.pointTypeDiv = pointTypeDiv;
        this.pointTypeMod = pointTypeMod;

        Collections.sort(this.values);
        Validate.isTrue(!this.values.isEmpty() && this.values.get(0).getPoints().compareTo(zeroValue) > 0);

        for (PointValue<KeyType, PointType> pointVal : this.values) {
            for (KeyType satisfier : pointVal.getSatisfiers()) {
                valueMap.put(createIndexOf(satisfier), pointVal);
            }
        }
    }

    protected abstract IndexType createIndexOf(KeyType keyType);

    public Collection<KeyType> getBestSatisifers(PointType value) {
        ListIterator<PointValue<KeyType, PointType>> satisfier = values.listIterator(values.size());
        while (satisfier.hasPrevious()) {
            PointValue<KeyType, PointType> curVal = satisfier.previous();
            PointType type = curVal.getPoints();
            if (type.compareTo(value) <= 0) {
                return curVal.getSatisfiers();
            }
        }
        return Collections.emptyList();
    }

    protected abstract Collection<KeyType> collect(Collection<KeyType> satisfiers, PointType amt);

    public Collection<KeyType> satisfy(PointType value) {
        List<KeyType> results = new ArrayList<>();
        ListIterator<PointValue<KeyType, PointType>> it = values.listIterator(values.size());

        while (it.hasPrevious()) {
            PointValue<KeyType, PointType> cur = it.previous();

            PointType amt = pointTypeDiv.apply(value, cur.getPoints());
            value = pointTypeMod.apply(value, cur.getPoints());

            results.addAll(collect(cur.getSatisfiers(), amt));
        }
        return results;
    }

    protected abstract Optional<PointType> matches(Collection<KeyType> a, Collection<KeyType> b,
            PointType matchPoints);

    public Optional<PointType> getValue(Collection<KeyType> key) {
        Validate.isTrue(!key.isEmpty());
        Collection<PointValue<KeyType, PointType>> possibleMatches = valueMap
                .get(createIndexOf(key.iterator().next()));
        for (PointValue<KeyType, PointType> possibleMatch : possibleMatches) {
            Optional<PointType> optPoints = matches(key, possibleMatch.getSatisfiers(), possibleMatch.getPoints());
            if (optPoints.isPresent()) {
                return optPoints;
            }
        }
        return Optional.empty();
    }
}