package org.checkerframework.checker.units;

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.checker.initialization.qual.UnderInitialization;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
import org.checkerframework.checker.signature.qual.BinaryName;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers;
import org.checkerframework.checker.units.qual.MixedUnits;
import org.checkerframework.checker.units.qual.Prefix;
import org.checkerframework.checker.units.qual.UnitsBottom;
import org.checkerframework.checker.units.qual.UnitsMultiple;
import org.checkerframework.checker.units.qual.UnknownUnits;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.qual.AnnotatedFor;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeFormatter;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotationClassLoader;
import org.checkerframework.framework.type.MostlyNoElementQualifierHierarchy;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.LiteralTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.PropagationTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.util.DefaultQualifierKindHierarchy;
import org.checkerframework.framework.util.QualifierKind;
import org.checkerframework.framework.util.QualifierKindHierarchy;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.checkerframework.javacutil.UserError;
import org.plumelib.reflection.Signatures;

/**
 * Annotated type factory for the Units Checker.
 *
 * <p>Handles multiple names for the same unit, with different prefixes, e.g. @kg is the same
 * as @g(Prefix.kilo).
 *
 * <p>Supports relations between units, e.g. if "m" is a variable of type "@m" and "s" is a variable
 * of type "@s", the division "m/s" is automatically annotated as "mPERs", the correct unit for the
 * result.
 */
public class UnitsAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
  private static final Class<org.checkerframework.checker.units.qual.UnitsRelations>
      unitsRelationsAnnoClass = org.checkerframework.checker.units.qual.UnitsRelations.class;

  protected final AnnotationMirror mixedUnits =
      AnnotationBuilder.fromClass(elements, MixedUnits.class);
  protected final AnnotationMirror TOP = AnnotationBuilder.fromClass(elements, UnknownUnits.class);
  protected final AnnotationMirror BOTTOM =
      AnnotationBuilder.fromClass(elements, UnitsBottom.class);

  /** The UnitsMultiple.prefix argument/element. */
  private final ExecutableElement unitsMultiplePrefixElement =
      TreeUtils.getMethod(UnitsMultiple.class, "prefix", 0, processingEnv);
  /** The UnitsMultiple.quantity argument/element. */
  private final ExecutableElement unitsMultipleQuantityElement =
      TreeUtils.getMethod(UnitsMultiple.class, "quantity", 0, processingEnv);
  /** The UnitsRelations.value argument/element. */
  private final ExecutableElement unitsRelationsValueElement =
      TreeUtils.getMethod(
          org.checkerframework.checker.units.qual.UnitsRelations.class, "value", 0, processingEnv);

  /**
   * Map from canonical class name to the corresponding UnitsRelations instance. We use the string
   * to prevent instantiating the UnitsRelations multiple times.
   */
  private Map<@CanonicalName String, UnitsRelations> unitsRel;

  /** Map from canonical name of external qualifiers, to their Class. */
  private static final Map<@CanonicalName String, Class<? extends Annotation>> externalQualsMap =
      new HashMap<>();

  private static final Map<String, AnnotationMirror> aliasMap = new HashMap<>();

  public UnitsAnnotatedTypeFactory(BaseTypeChecker checker) {
    // use true to enable flow inference, false to disable it
    super(checker, false);

    this.postInit();
  }

  // In Units Checker, we always want to print out the Invisible Qualifiers (UnknownUnits), and to
  // format the print out of qualifiers by removing Prefix.one
  @Override
  protected AnnotatedTypeFormatter createAnnotatedTypeFormatter() {
    return new UnitsAnnotatedTypeFormatter(checker);
  }

  // Converts all metric-prefixed units' alias annotations (eg @kg) into base unit annotations
  // with prefix values (eg @g(Prefix.kilo))
  @Override
  public AnnotationMirror canonicalAnnotation(AnnotationMirror anno) {
    // Get the name of the aliased annotation
    String aname = AnnotationUtils.annotationName(anno);

    // See if we already have a map from this aliased annotation to its corresponding base unit
    // annotation
    if (aliasMap.containsKey(aname)) {
      // if so return it
      return aliasMap.get(aname);
    }

    boolean built = false;
    AnnotationMirror result = null;
    // if not, look for the UnitsMultiple meta annotations of this aliased annotation
    for (AnnotationMirror metaAnno : anno.getAnnotationType().asElement().getAnnotationMirrors()) {
      // see if the meta annotation is UnitsMultiple
      if (isUnitsMultiple(metaAnno)) {
        // retrieve the Class of the base unit annotation
        Name baseUnitAnnoClass =
            AnnotationUtils.getElementValueClassName(metaAnno, unitsMultipleQuantityElement);

        // retrieve the SI Prefix of the aliased annotation
        Prefix prefix =
            AnnotationUtils.getElementValueEnum(
                metaAnno, unitsMultiplePrefixElement, Prefix.class, Prefix.one);

        // Build a base unit annotation with the prefix applied
        result =
            UnitsRelationsTools.buildAnnoMirrorWithSpecificPrefix(
                processingEnv, baseUnitAnnoClass, prefix);

        // TODO: assert that this annotation is a prefix multiple of a Unit that's in the supported
        // type qualifiers list currently this breaks for externally loaded annotations if the order
        // was an alias before a base annotation.
        // assert isSupportedQualifier(result);

        built = true;
        break;
      }
    }

    if (built) {
      // aliases shouldn't have Prefix.one, but if it does then clean it up here
      if (UnitsRelationsTools.getPrefix(result) == Prefix.one) {
        result = removePrefix(result);
      }

      // add this to the alias map
      aliasMap.put(aname, result);
      return result;
    }

    return super.canonicalAnnotation(anno);
  }

  /**
   * Returns a map from canonical class name to the corresponding UnitsRelations instance.
   *
   * @return a map from canonical class name to the corresponding UnitsRelations instance
   */
  protected Map<@CanonicalName String, UnitsRelations> getUnitsRel() {
    if (unitsRel == null) {
      unitsRel = new HashMap<>();
      // Always add the default units relations, for the standard units.
      // Other code adds more relations.
      unitsRel.put(
          UnitsRelationsDefault.class.getCanonicalName(),
          new UnitsRelationsDefault().init(processingEnv));
    }
    return unitsRel;
  }

  @Override
  protected AnnotationClassLoader createAnnotationClassLoader() {
    // Use the UnitsAnnotationClassLoader instead of the default one
    return new UnitsAnnotationClassLoader(checker);
  }

  @Override
  protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
    // get all the loaded annotations
    Set<Class<? extends Annotation>> qualSet = getBundledTypeQualifiers();

    // load all the external units
    loadAllExternalUnits();

    // copy all loaded external Units to qual set
    qualSet.addAll(externalQualsMap.values());

    return qualSet;
  }

  private void loadAllExternalUnits() {
    // load external individually named units
    String qualNames = checker.getOption("units");
    if (qualNames != null) {
      for (String qualName : qualNames.split(",")) {
        if (!Signatures.isBinaryName(qualName)) {
          throw new UserError("Malformed qualifier name \"%s\" in -Aunits=%s", qualName, qualNames);
        }
        loadExternalUnit(qualName);
      }
    }

    // load external directories of units
    String qualDirectories = checker.getOption("unitsDirs");
    if (qualDirectories != null) {
      for (String directoryName : qualDirectories.split(":")) {
        loadExternalDirectory(directoryName);
      }
    }
  }

  /**
   * Loads and processes a single external units qualifier.
   *
   * @param annoName the name of a units qualifier
   */
  private void loadExternalUnit(@BinaryName String annoName) {
    // loadExternalAnnotationClass() returns null for alias units
    Class<? extends Annotation> loadedClass = loader.loadExternalAnnotationClass(annoName);
    if (loadedClass != null) {
      addUnitToExternalQualMap(loadedClass);
    }
  }

  /** Loads and processes the units qualifiers from a single external directory. */
  private void loadExternalDirectory(String directoryName) {
    Set<Class<? extends Annotation>> annoClassSet =
        loader.loadExternalAnnotationClassesFromDirectory(directoryName);

    for (Class<? extends Annotation> annoClass : annoClassSet) {
      addUnitToExternalQualMap(annoClass);
    }
  }

  /** Adds the annotation class to the external qualifier map if it is not an alias annotation. */
  private void addUnitToExternalQualMap(final Class<? extends Annotation> annoClass) {
    AnnotationMirror mirror =
        UnitsRelationsTools.buildAnnoMirrorWithNoPrefix(
            processingEnv, annoClass.getCanonicalName());

    // if it is not an aliased annotation, add to external quals map if it isn't already in map
    if (!isAliasedAnnotation(mirror)) {
      String unitClassName = annoClass.getCanonicalName();
      if (!externalQualsMap.containsKey(unitClassName)) {
        externalQualsMap.put(unitClassName, annoClass);
      }
    }
    // if it is an aliased annotation
    else {
      // ensure it has a base unit
      @CanonicalName Name baseUnitClass = getBaseUnitAnno(mirror);
      if (baseUnitClass != null) {
        // if the base unit isn't already added, add that first
        @SuppressWarnings("signature") // https://tinyurl.com/cfissue/658
        @DotSeparatedIdentifiers String baseUnitClassName = baseUnitClass.toString();
        if (!externalQualsMap.containsKey(baseUnitClassName)) {
          loadExternalUnit(baseUnitClassName);
        }

        // then add the aliased annotation to the alias map
        // TODO: refactor so we can directly add to alias map, skipping the assert check in
        // canonicalAnnotation.
        canonicalAnnotation(mirror);
      } else {
        // error: somehow the aliased annotation has @UnitsMultiple meta annotation, but no
        // base class defined in that meta annotation
        // TODO: error abort
      }
    }

    // process the units annotation and add its corresponding units relations class
    addUnitsRelations(annoClass);
  }

  private boolean isAliasedAnnotation(AnnotationMirror anno) {
    // loop through the meta annotations of the annotation, look for UnitsMultiple
    for (AnnotationMirror metaAnno : anno.getAnnotationType().asElement().getAnnotationMirrors()) {
      // see if the meta annotation is UnitsMultiple
      if (isUnitsMultiple(metaAnno)) {
        // TODO: does every alias have to have Prefix?
        return true;
      }
    }

    // if we are unable to find UnitsMultiple meta annotation, then this is not an Aliased
    // Annotation
    return false;
  }

  /**
   * Return the name of the given annotation, if it is meta-annotated with UnitsMultiple; otherwise
   * return null.
   *
   * @param anno the annotation to examine
   * @return the annotation's name, if it is meta-annotated with UnitsMultiple; otherwise null
   */
  private @Nullable @CanonicalName Name getBaseUnitAnno(AnnotationMirror anno) {
    // loop through the meta annotations of the annotation, look for UnitsMultiple
    for (AnnotationMirror metaAnno : anno.getAnnotationType().asElement().getAnnotationMirrors()) {
      // see if the meta annotation is UnitsMultiple
      if (isUnitsMultiple(metaAnno)) {
        // TODO: does every alias have to have Prefix?
        // Retrieve the base unit annotation.
        Name baseUnitAnnoClass =
            AnnotationUtils.getElementValueClassName(metaAnno, unitsMultipleQuantityElement);
        return baseUnitAnnoClass;
      }
    }
    return null;
  }

  /**
   * Returns true if {@code metaAnno} is {@link UnitsMultiple}.
   *
   * @param metaAnno an annotation mirror
   * @return true if {@code metaAnno} is {@link UnitsMultiple}
   */
  private boolean isUnitsMultiple(AnnotationMirror metaAnno) {
    return areSameByClass(metaAnno, UnitsMultiple.class);
  }

  /**
   * Look for an @UnitsRelations annotation on the qualifier and add it to the list of
   * UnitsRelations.
   *
   * @param qual the qualifier to investigate
   */
  private void addUnitsRelations(Class<? extends Annotation> qual) {
    AnnotationMirror am = AnnotationBuilder.fromClass(elements, qual);

    for (AnnotationMirror ama : am.getAnnotationType().asElement().getAnnotationMirrors()) {
      if (areSameByClass(ama, unitsRelationsAnnoClass)) {
        String theclassname =
            AnnotationUtils.getElementValueClassName(ama, unitsRelationsValueElement).toString();
        if (!Signatures.isClassGetName(theclassname)) {
          throw new UserError(
              "Malformed class name \"%s\" should be in ClassGetName format in annotation %s",
              theclassname, ama);
        }
        Class<?> valueElement;
        try {
          ClassLoader classLoader = InternalUtils.getClassLoaderForClass(AnnotationUtils.class);
          valueElement = Class.forName(theclassname, true, classLoader);
        } catch (ClassNotFoundException e) {
          String msg =
              String.format(
                  "Could not load class '%s' for field 'value' in annotation %s",
                  theclassname, ama);
          throw new UserError(msg, e);
        }
        Class<? extends UnitsRelations> unitsRelationsClass;
        try {
          unitsRelationsClass = valueElement.asSubclass(UnitsRelations.class);
        } catch (ClassCastException ex) {
          throw new UserError(
              "Invalid @UnitsRelations meta-annotation found in %s. "
                  + "@UnitsRelations value %s is not a subclass of "
                  + "org.checkerframework.checker.units.UnitsRelations.",
              qual, ama);
        }
        String classname = unitsRelationsClass.getCanonicalName();

        if (!getUnitsRel().containsKey(classname)) {
          try {
            unitsRel.put(
                classname,
                unitsRelationsClass.getDeclaredConstructor().newInstance().init(processingEnv));
          } catch (Throwable e) {
            throw new BugInCF("Throwable when instantiating UnitsRelations", e);
          }
        }
      }
    }
  }

  @Override
  public TreeAnnotator createTreeAnnotator() {
    // Don't call super.createTreeAnnotator because it includes PropagationTreeAnnotator which
    // is incorrect.
    return new ListTreeAnnotator(
        new UnitsPropagationTreeAnnotator(this),
        new LiteralTreeAnnotator(this).addStandardLiteralQualifiers(),
        new UnitsTreeAnnotator(this));
  }

  private static class UnitsPropagationTreeAnnotator extends PropagationTreeAnnotator {

    public UnitsPropagationTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
      super(atypeFactory);
    }

    // Handled completely by UnitsTreeAnnotator
    @Override
    public Void visitBinary(BinaryTree node, AnnotatedTypeMirror type) {
      return null;
    }

    // Handled completely by UnitsTreeAnnotator
    @Override
    public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
      return null;
    }
  }

  /** A class for adding annotations based on tree. */
  private class UnitsTreeAnnotator extends TreeAnnotator {

    UnitsTreeAnnotator(UnitsAnnotatedTypeFactory atypeFactory) {
      super(atypeFactory);
    }

    @Override
    public Void visitBinary(BinaryTree node, AnnotatedTypeMirror type) {
      AnnotatedTypeMirror lht = getAnnotatedType(node.getLeftOperand());
      AnnotatedTypeMirror rht = getAnnotatedType(node.getRightOperand());
      Tree.Kind kind = node.getKind();

      // Remove Prefix.one
      if (UnitsRelationsTools.getPrefix(lht) == Prefix.one) {
        lht = UnitsRelationsTools.removePrefix(elements, lht);
      }
      if (UnitsRelationsTools.getPrefix(rht) == Prefix.one) {
        rht = UnitsRelationsTools.removePrefix(elements, rht);
      }

      AnnotationMirror bestres = null;
      for (UnitsRelations ur : getUnitsRel().values()) {
        AnnotationMirror res = useUnitsRelation(kind, ur, lht, rht);

        if (bestres != null && res != null && !bestres.equals(res)) {
          checker.message(
              Kind.WARNING,
              "UnitsRelation mismatch, taking neither! Previous: "
                  + bestres
                  + " and current: "
                  + res);
          return null; // super.visitBinary(node, type);
        }

        if (res != null) {
          bestres = res;
        }
      }

      if (bestres != null) {
        type.replaceAnnotation(bestres);
      } else {
        // If none of the units relations classes could resolve the units, then apply default rules

        switch (kind) {
          case MINUS:
          case PLUS:
            if (lht.getAnnotations().equals(rht.getAnnotations())) {
              // The sum or difference has the same units as both operands.
              type.replaceAnnotations(lht.getAnnotations());
            } else {
              // otherwise it results in mixed
              type.replaceAnnotation(mixedUnits);
            }
            break;
          case DIVIDE:
            if (lht.getAnnotations().equals(rht.getAnnotations())) {
              // If the units of the division match, return TOP
              type.replaceAnnotation(TOP);
            } else if (UnitsRelationsTools.hasNoUnits(rht)) {
              // any unit divided by a scalar keeps that unit
              type.replaceAnnotations(lht.getAnnotations());
            } else if (UnitsRelationsTools.hasNoUnits(lht)) {
              // scalar divided by any unit returns mixed
              type.replaceAnnotation(mixedUnits);
            } else {
              // else it is a division of two units that have no defined relations
              // from a relations class
              // return mixed
              type.replaceAnnotation(mixedUnits);
            }
            break;
          case MULTIPLY:
            if (UnitsRelationsTools.hasNoUnits(lht)) {
              // any unit multiplied by a scalar keeps the unit
              type.replaceAnnotations(rht.getAnnotations());
            } else if (UnitsRelationsTools.hasNoUnits(rht)) {
              // any scalar multiplied by a unit becomes the unit
              type.replaceAnnotations(lht.getAnnotations());
            } else {
              // else it is a multiplication of two units that have no defined
              // relations from a relations class
              // return mixed
              type.replaceAnnotation(mixedUnits);
            }
            break;
          case REMAINDER:
            // in modulo operation, it always returns the left unit regardless of what
            // it is (unknown, or some unit)
            type.replaceAnnotations(lht.getAnnotations());
            break;
          default:
            // Placeholders for unhandled binary operations
            // Do nothing
        }
      }

      return null;
    }

    @Override
    public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
      ExpressionTree var = node.getVariable();
      AnnotatedTypeMirror varType = getAnnotatedType(var);

      type.replaceAnnotations(varType.getAnnotations());
      return null;
    }

    private AnnotationMirror useUnitsRelation(
        Tree.Kind kind, UnitsRelations ur, AnnotatedTypeMirror lht, AnnotatedTypeMirror rht) {

      AnnotationMirror res = null;
      if (ur != null) {
        switch (kind) {
          case DIVIDE:
            res = ur.division(lht, rht);
            break;
          case MULTIPLY:
            res = ur.multiplication(lht, rht);
            break;
          default:
            // Do nothing
        }
      }
      return res;
    }
  }

  /** Set the Bottom qualifier as the bottom of the hierarchy. */
  @Override
  public QualifierHierarchy createQualifierHierarchy() {
    return new UnitsQualifierHierarchy();
  }

  /** Qualifier Hierarchy for the Units Checker. */
  @AnnotatedFor("nullness")
  protected class UnitsQualifierHierarchy extends MostlyNoElementQualifierHierarchy {
    /** Constructor. */
    public UnitsQualifierHierarchy() {
      super(UnitsAnnotatedTypeFactory.this.getSupportedTypeQualifiers(), elements);
    }

    @Override
    protected QualifierKindHierarchy createQualifierKindHierarchy(
        @UnderInitialization UnitsQualifierHierarchy this,
        Collection<Class<? extends Annotation>> qualifierClasses) {
      return new UnitsQualifierKindHierarchy(qualifierClasses, elements);
    }

    @Override
    protected boolean isSubtypeWithElements(
        AnnotationMirror subAnno,
        QualifierKind subKind,
        AnnotationMirror superAnno,
        QualifierKind superKind) {
      return AnnotationUtils.areSame(subAnno, superAnno);
    }

    @Override
    protected AnnotationMirror leastUpperBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind lubKind) {
      if (qualifierKind1.isBottom()) {
        return a2;
      } else if (qualifierKind2.isBottom()) {
        return a1;
      } else if (qualifierKind1 == qualifierKind2) {
        if (AnnotationUtils.areSame(a1, a2)) {
          return a1;
        } else {
          @SuppressWarnings({
            "nullness:assignment" // Every qualifier kind is a
            // key in directSuperQualifierMap.
          })
          @NonNull AnnotationMirror lub =
              ((UnitsQualifierKindHierarchy) qualifierKindHierarchy)
                  .directSuperQualifierMap.get(qualifierKind1);
          return lub;
        }
      }
      throw new BugInCF("Unexpected QualifierKinds: %s %s", qualifierKind1, qualifierKind2);
    }

    @Override
    protected AnnotationMirror greatestLowerBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind glbKind) {
      return UnitsAnnotatedTypeFactory.this.BOTTOM;
    }
  }

  /** UnitsQualifierKindHierarchy. */
  @AnnotatedFor("nullness")
  protected static class UnitsQualifierKindHierarchy extends DefaultQualifierKindHierarchy {

    /**
     * Mapping from QualifierKind to an AnnotationMirror that represents its direct super qualifier.
     * Every qualifier kind maps to a nonnull AnnotationMirror.
     */
    private final Map<QualifierKind, AnnotationMirror> directSuperQualifierMap;

    /**
     * Creates a UnitsQualifierKindHierarchy.
     *
     * @param qualifierClasses classes of annotations that are the qualifiers for this hierarchy
     * @param elements element utils
     */
    public UnitsQualifierKindHierarchy(
        Collection<Class<? extends Annotation>> qualifierClasses, Elements elements) {
      super(qualifierClasses, UnitsBottom.class);
      directSuperQualifierMap = createDirectSuperQualifierMap(elements);
    }

    /**
     * Creates the direct super qualifier map.
     *
     * @param elements element utils
     * @return the map
     */
    @RequiresNonNull("this.qualifierKinds")
    private Map<QualifierKind, AnnotationMirror> createDirectSuperQualifierMap(
        @UnderInitialization UnitsQualifierKindHierarchy this, Elements elements) {
      Map<QualifierKind, AnnotationMirror> directSuperType = new TreeMap<>();
      for (QualifierKind qualifierKind : qualifierKinds) {
        QualifierKind directSuperTypeKind = getDirectSuperQualifierKind(qualifierKind);
        AnnotationMirror directSuperTypeAnno;
        try {
          directSuperTypeAnno = AnnotationBuilder.fromName(elements, directSuperTypeKind.getName());
        } catch (BugInCF ex) {
          throw new TypeSystemError("Unit annotations must have a default for all elements.");
        }
        if (directSuperTypeAnno == null) {
          throw new TypeSystemError("Could not create AnnotationMirror: %s", directSuperTypeAnno);
        }
        directSuperType.put(qualifierKind, directSuperTypeAnno);
      }
      return directSuperType;
    }

    /**
     * Get the direct super qualifier for the given qualifier kind.
     *
     * @param qualifierKind qualifier kind
     * @return direct super qualifier kind
     */
    private QualifierKind getDirectSuperQualifierKind(
        @UnderInitialization UnitsQualifierKindHierarchy this, QualifierKind qualifierKind) {
      if (qualifierKind.isTop()) {
        return qualifierKind;
      }
      Set<QualifierKind> superQuals = new TreeSet<>(qualifierKind.getStrictSuperTypes());
      while (superQuals.size() > 0) {
        Set<QualifierKind> lowest = findLowestQualifiers(superQuals);
        if (lowest.size() == 1) {
          return lowest.iterator().next();
        }
        superQuals.removeAll(lowest);
      }
      throw new BugInCF("No direct super qualifier found for %s", qualifierKind);
    }
  }

  private AnnotationMirror removePrefix(AnnotationMirror anno) {
    return UnitsRelationsTools.removePrefix(elements, anno);
  }
}
