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

framework.src.org.checkerframework.qualframework.poly.Wildcard Maven / Gradle / Ivy

package org.checkerframework.qualframework.poly;

import java.util.*;

/** A qualifier wildcard, bounded above and below by {@link PolyQual}s.
 */
public class Wildcard {
    private final PolyQual lower;
    private final PolyQual upper;

    public Wildcard(PolyQual lower, PolyQual upper) {
        // Don't let the user pass in `null`.  We use `null` to represent the
        // special empty wildcard.
        if (lower == null || upper == null) {
            throw new IllegalArgumentException("wildcard bounds may not be null");
        }
        this.lower = lower;
        this.upper = upper;
    }

    public Wildcard(PolyQual qual) {
        this(qual, qual);
    }

    public Wildcard(Q groundLower, Q groundUpper) {
        this(new PolyQual.GroundQual(groundLower), new PolyQual.GroundQual(groundUpper));
    }

    public Wildcard(Q groundQual) {
        this(new PolyQual.GroundQual(groundQual));
    }


    /**
     * Force the user to write `Wildcard.empty()` instead of `new Wildcard()`,
     * to make it clear that they're getting something special, rather than
     * a normal wildcard with default bounds or something like that.
     */
    private Wildcard() {
        this.lower = null;
        this.upper = null;
    }

    /** Produce the empty wildcard. */
    public static  Wildcard empty() {
        return new Wildcard();
    }


    /** Get the lower bound of the wildcard, or {@code null} if this is the
     * empty wildcard. */
    public PolyQual getLowerBound() {
        return this.lower;
    }

    /** Get the upper bound of the wildcard, or {@code null} if this is the
     * empty wildcard. */
    public PolyQual getUpperBound() {
        return this.upper;
    }

    /** Check if this is the empty wildcard. */
    public boolean isEmpty() {
        return this.lower == null;
    }

    /** Substitute wildcards for qualifier parameters. */
    public Wildcard substitute(Map> substs) {
        Map> lowerSubsts = new HashMap<>();
        Map> upperSubsts = new HashMap<>();

        for (String k : substs.keySet()) {
            lowerSubsts.put(k, substs.get(k).getLowerBound());
            upperSubsts.put(k, substs.get(k).getUpperBound());
        }

        PolyQual newLower = lower.substitute(lowerSubsts);
        PolyQual newUpper = upper.substitute(upperSubsts);
        return new Wildcard(newLower, newUpper);
    }

    /** Combine with another wildcard, using the provided {@link
     * CombiningOperation}s for the upper and lower bounds.
     */
    public Wildcard combineWith(Wildcard other,
            CombiningOperation lowerOp, CombiningOperation upperOp) {
        return new Wildcard(
                this.getLowerBound().combineWith(other.getLowerBound(), lowerOp),
                this.getUpperBound().combineWith(other.getUpperBound(), upperOp));
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || o.getClass() != this.getClass()) {
            return false;
        }
        @SuppressWarnings("rawtypes")
        Wildcard other = (Wildcard)o;
        return this.lower.equals(other.lower)
            && this.upper.equals(other.upper);
    }

    @Override
    public int hashCode() {
        return this.lower.hashCode() * 37
            + this.upper.hashCode() * 59;
    }

    @Override
    public String toString() {
        if (this.isEmpty()) {
            return "ø";
        } else if (lower.equals(upper)) {
            return lower.toString();
        } else {
            return "? ∈ [" + lower + ".." + upper + "]";
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy