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

checker.src.org.checkerframework.checker.units.UnitsRelationsDefault Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java’s type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.42.0
Show newest version
package org.checkerframework.checker.units;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.util.Elements;

import org.checkerframework.checker.units.qual.Prefix;
import org.checkerframework.checker.units.qual.h;
import org.checkerframework.checker.units.qual.km2;
import org.checkerframework.checker.units.qual.kmPERh;
import org.checkerframework.checker.units.qual.m;
import org.checkerframework.checker.units.qual.m2;
import org.checkerframework.checker.units.qual.mPERs;
import org.checkerframework.checker.units.qual.mPERs2;
import org.checkerframework.checker.units.qual.mm2;
import org.checkerframework.checker.units.qual.s;
import org.checkerframework.framework.type.AnnotatedTypeMirror;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
 */

/**
 * Default relations between SI units.
 * TODO: what relations are missing?
 */
public class UnitsRelationsDefault implements UnitsRelations {
    protected AnnotationMirror m, km, mm, m2, km2, mm2, s, h, mPERs, kmPERh, mPERs2;
    protected Elements elements;

    /**
     * Constructs various AnnotationMirrors representing specific
     * checker-framework provided Units involved in the rules resolved in this
     * UnitsRelations implementation
     */
    @Override
    public UnitsRelations init(ProcessingEnvironment env) {
        elements = env.getElementUtils();

        m = UnitsRelationsTools.buildAnnoMirrorWithDefaultPrefix(env, m.class);
        km = UnitsRelationsTools.buildAnnoMirrorWithSpecificPrefix(env, m.class, Prefix.kilo);
        mm = UnitsRelationsTools.buildAnnoMirrorWithSpecificPrefix(env, m.class, Prefix.milli);

        m2 = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, m2.class);
        km2 = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, km2.class);
        mm2 = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, mm2.class);

        s = UnitsRelationsTools.buildAnnoMirrorWithDefaultPrefix(env, s.class);
        h = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, h.class);

        mPERs = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, mPERs.class);
        kmPERh = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, kmPERh.class);

        mPERs2 = UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(env, mPERs2.class);

        return this;
    }

    /**
     * Provides rules for resolving the result Unit of the multiplication of
     * checker-framework provided Units
     */
    @Override
    public /*@Nullable*/ AnnotationMirror multiplication(AnnotatedTypeMirror lht, AnnotatedTypeMirror rht) {
        // TODO: does this handle scaling correctly?

        // length * length => area
        // checking SI units only
        if (UnitsRelationsTools.hasSpecificUnitIgnoringPrefix(lht, m) && UnitsRelationsTools.hasSpecificUnitIgnoringPrefix(rht, m)) {
            if (UnitsRelationsTools.hasNoPrefix(lht) && UnitsRelationsTools.hasNoPrefix(rht)) {
                // m * m
                return m2;
            }

            Prefix lhtPrefix = UnitsRelationsTools.getPrefix(lht);
            Prefix rhtPrefix = UnitsRelationsTools.getPrefix(rht);

            if (bothHaveSpecificPrefix(lhtPrefix, rhtPrefix, Prefix.kilo)) {
                // km * km
                return km2;
            } else if (bothHaveSpecificPrefix(lhtPrefix, rhtPrefix, Prefix.one)) {
                // m(Prefix.one) * m(Prefix.one)
                return m2;
            } else if (bothHaveSpecificPrefix(lhtPrefix, rhtPrefix, Prefix.milli)) {
                // mm * mm
                return mm2;
            } else {
                return null;
            }
        } else if (havePairOfUnitsIgnoringOrder(lht, s, rht, mPERs)) {
            // s * mPERs or mPERs * s => m
            return m;
        } else if (havePairOfUnitsIgnoringOrder(lht, s, rht, mPERs2)) {
            // s * mPERs2 or mPERs2 * s => mPERs
            return mPERs;
        } else if (havePairOfUnitsIgnoringOrder(lht, h, rht, kmPERh)) {
            // h * kmPERh or kmPERh * h => km
            return km;
        } else {
            return null;
        }
    }

    /**
     * Provides rules for resolving the result Unit of the division of
     * checker-framework provided Units
     */
    @Override
    public /*@Nullable*/ AnnotationMirror division(AnnotatedTypeMirror lht, AnnotatedTypeMirror rht) {
        if (havePairOfUnits(lht, m, rht, s)) {
            // m / s => mPERs
            return mPERs;
        } else if (havePairOfUnits(lht, km, rht, h)) {
            // km / h => kmPERh
            return kmPERh;
        } else if (havePairOfUnits(lht, m2, rht, m)) {
            // m2 / m => m
            return m;
        } else if (havePairOfUnits(lht, km2, rht, km)) {
            // km2 / km => km
            return km;
        } else if (havePairOfUnits(lht, mm2, rht, mm)) {
            // mm2 / mm => mm
            return mm;
        } else if (havePairOfUnits(lht, m, rht, mPERs)) {
            // m / mPERs => s
            return s;
        } else if (havePairOfUnits(lht, km, rht, kmPERh)) {
            // km / kmPERh => h
            return h;
        } else if (havePairOfUnits(lht, mPERs, rht, s)) {
            // mPERs / s = mPERs2
            return mPERs2;
        } else if (havePairOfUnits(lht, mPERs, rht, mPERs2)) {
            // mPERs / mPERs2 => s  (velocity / acceleration == time)
            return s;
        } else {
            return null;
        }
    }

    /**
     * Checks to see if both lhtPrefix and rhtPrefix have the same prefix as
     * specificPrefix
     *
     * @param lhtPrefix left hand side prefix
     * @param rhtPrefix right hand side prefix
     * @param specificPrefix specific desired prefix to match
     * @return true if all 3 Prefix are the same, false otherwise
     */
    protected boolean bothHaveSpecificPrefix(Prefix lhtPrefix, Prefix rhtPrefix, Prefix specificPrefix) {
        if (lhtPrefix == null || rhtPrefix == null || specificPrefix == null) {
            return false;
        }

        return (lhtPrefix.equals(rhtPrefix) && rhtPrefix.equals(specificPrefix));
    }

    /**
     * Checks to see if lht has the unit ul and if rht has the unit ur all at
     * the same time
     *
     * @param lht left hand annotated type
     * @param ul left hand unit
     * @param rht right hand annotated type
     * @param ur right hand unit
     * @return true if lht has lu and rht has ru, false otherwise
     */
    protected boolean havePairOfUnits(AnnotatedTypeMirror lht, AnnotationMirror ul, AnnotatedTypeMirror rht, AnnotationMirror ur) {
        return UnitsRelationsTools.hasSpecificUnit(lht, ul) && UnitsRelationsTools.hasSpecificUnit(rht, ur);
    }

    /**
     * Checks to see if lht and rht have the pair of units u1 and u2 regardless
     * of order
     *
     * @param lht left hand annotated type
     * @param u1 unit 1
     * @param rht right hand annotated type
     * @param u2 unit 2
     * @return true if lht and rht have the pair of units u1 and u2 regardless
     *         of order, false otherwise
     */
    protected boolean havePairOfUnitsIgnoringOrder(AnnotatedTypeMirror lht, AnnotationMirror u1, AnnotatedTypeMirror rht, AnnotationMirror u2) {
        return havePairOfUnits(lht, u1, rht, u2) || havePairOfUnits(lht, u2, rht, u1);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy