All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.applic.mountability.core.Computer Maven / Gradle / Ivy

The newest version!
package cdc.applic.mountability.core;

import java.io.PrintStream;
import java.util.List;
import java.util.function.UnaryOperator;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.io.IoBuilder;

import cdc.applic.expressions.Expression;
import cdc.applic.mountability.Interchangeability;
import cdc.applic.mountability.handlers.MountabilityHandler;
import cdc.util.events.ProgressSupplier;

/**
 * Internal class used to compute mountability at a single Use Point.
 *
 * @param  The use point type.
 * @param  The variant type.
 */
public class Computer {
    private static final Logger LOGGER = LogManager.getLogger(Computer.class);
    private static final PrintStream OUT = IoBuilder.forLogger(LOGGER).setLevel(Level.DEBUG).buildPrintStream();
    /** The Use point. */
    private final U usePoint;
    /** The variants wrappers. */
    private final List> buckets;

    public Computer(U usePoint,
                    List> buckets) {
        LOGGER.debug("init<>({}, ...)", usePoint);
        this.usePoint = usePoint;
        this.buckets = buckets;
        if (LOGGER.isDebugEnabled()) {
            print(OUT);
        }
    }

    public void process(MountabilityHandler handler,
                        UnaryOperator simplify,
                        ProgressSupplier progress) {
        LOGGER.debug("process(...)");
        // The number of variants
        final int size = buckets.size();
        // Iterate on each possible pair of variants

        // Iterate on first variant
        for (int index1 = 0; index1 < size; index1++) {
            LOGGER.debug("   index1: {}", index1);
            // Iterate on second variant
            for (int index2 = 0; index2 < size; index2++) {
                final boolean replaceable = isReplaceable(index2, index1);
                LOGGER.debug("      index2: {} replaceable by: {}: {}", index2, index1, replaceable);
                if (replaceable) {
                    buckets.get(index1).p.add(buckets.get(index2).applicability);
                } else {
                    if (index2 > index1) {
                        buckets.get(index1).n.add(buckets.get(index2).applicability);
                    }
                }
            }
            progress.incrementValue();
        }

        for (final Bucket bucket : buckets) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("{} {}", usePoint, bucket.variant);
                LOGGER.debug("   {}", bucket.getMountability());
                LOGGER.debug("   {}", simplify.apply(bucket.getMountability()));
            }
            handler.processVariantMountability(usePoint,
                                               bucket.variant,
                                               simplify.apply(bucket.getMountability()));
        }
    }

    /**
     * Computes replaceability based on interchangeability.
     *
     * @param at The index of the reference variant that could be replaced.
     * @param by The index of variant that could replace the reference variant.
     * @return {@code true} if the reference variant {@code at} can be replaced by the variant {@code by}.
     */
    private boolean isReplaceable(int at,
                                  int by) {
        if (at < by) {
            // The candidate replacer is after the reference variant
            // No intermediate interchangeability can be NOT_INTERCHANGEABLE
            for (int index = at + 1; index <= by; index++) {
                if (buckets.get(index).interchangeability == Interchangeability.NOT_INTERCHANGEABLE) {
                    return false;
                }
            }
            return true;
        } else if (at == by) {
            // A variant can be replaced by itself
            return true;
        } else {
            // The candidate replacer is before the reference variant
            // All intermediate interchangeability must be TWO_WAYS
            for (int index = at; index > by; index--) {
                if (buckets.get(index).interchangeability != Interchangeability.TWO_WAYS) {
                    return false;
                }
            }
            return true;
        }
    }

    public void print(PrintStream out) {
        out.println("Use Point: " + usePoint);
        for (final Bucket bucket : buckets) {
            out.println("   Variant: " + bucket.variant + " " + bucket.interchangeability + " " + bucket.applicability);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy