protected SFlowGraphQualifierHierarchy(GraphFactory f) {
   super(f);
   reimQuals = AnnotationUtils.createAnnotationSet();
   reimQuals.add(SFlowChecker.READONLY);
   reimQuals.add(SFlowChecker.POLYREAD);
   reimQuals.add(SFlowChecker.MUTABLE);
 }
  @Override
  public boolean isSubtype(Collection<AnnotationMirror> rhs, Collection<AnnotationMirror> lhs) {
    if (lhs.isEmpty() || rhs.isEmpty()) {
      //            throw new RuntimeException("QualifierHierarchy: Empty annotations in lhs: " +
      // lhs + " or rhs: " + rhs);
      //            System.err.println("WARN: QualifierHierarchy: Empty annotations in lhs: " + lhs
      // + " or rhs: " + rhs + " -- ignored");
      return false;
    }
    // check if lhs contains Readonly and remove all ReIm annotations
    // I don't trust the equal method for AnnotationMirror...
    // FIXME: The following code is very ugly!!!
    boolean isLhsReadonly = false;
    for (Iterator<AnnotationMirror> it = lhs.iterator(); it.hasNext(); ) {
      AnnotationMirror anno = it.next();
      if (anno.toString().equals(SFlowChecker.READONLY.toString())) {
        isLhsReadonly = true;
      }
    }
    Set<AnnotationMirror> rSet = AnnotationUtils.createAnnotationSet();
    rSet.addAll(rhs);
    Set<AnnotationMirror> lSet = AnnotationUtils.createAnnotationSet();
    lSet.addAll(lhs);
    rSet = InferenceUtils.differAnnotations(rSet, reimQuals);
    lSet = InferenceUtils.differAnnotations(lSet, reimQuals);

    for (AnnotationMirror lhsAnno : lSet) {
      for (AnnotationMirror rhsAnno : rSet) {
        if (isLhsReadonly || rhsAnno.toString().equals(SFlowChecker.BOTTOM.toString())) {
          if (isSubtype(rhsAnno, lhsAnno)) {
            return true;
          }
        } else {
          // We enforce equality
          if (rhsAnno.toString().equals(lhsAnno.toString())) return true;
        }
      }
    }
    return false;
  }
 @Override
 public Void visitVariable(VariableTree node, AnnotatedTypeMirror p) {
   typeAnnotator.visit(p);
   VariableElement varElt = TreeUtils.elementFromDeclaration((VariableTree) node);
   if (!p.isAnnotated() && ElementUtils.isStatic(varElt)) {
     p.clearAnnotations();
     Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
     set.add(checker.ANY);
     set.add(checker.PEER);
     annotateConstants(p, set);
   }
   return super.visitVariable(node, p);
 }
 @Override
 public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
   if (!type.isAnnotated()) {
     //				if (type.getKind() == TypeKind.NULL) {
     type.clearAnnotations();
     Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
     set.add(checker.BOTTOM);
     annotateConstants(type, set);
     //				}
     //				else
     //					type.addAnnotation(checker.READONLY);
   }
   return super.visitLiteral(tree, type);
 }
  private void annotateMethod(ExecutableElement methodElt, AnnotatedExecutableType methodType) {
    if (checker.isChecking() || methodType.isAnnotated()) {
      return;
    }
    // First annotate the receiver
    annotateThis(methodType.getReceiverType());

    // If it is from library
    if (checker.isFromLibrary(methodElt)) {
      Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
      set.add(checker.PEER);
      annotateConstants(methodType, set);
    }
    // methodType.isAnnotated() only checks the annotations on methodType,
    // but not the type of its receiver, parameters or return;
    if (!methodType.isAnnotated()) methodType.addAnnotation(checker.BOTTOM);
  }
    @Override
    public Void visitDeclared(AnnotatedDeclaredType type, ElementKind p) {
      Element elt = type.getElement();
      if (!type.isAnnotated()
          && (
          /*checker.isDefaultAnyType(type) ||*/
          elt != null
              && ElementUtils.isStatic(elt)
              && (elt.getKind() == ElementKind.FIELD
                  || elt.getKind() == ElementKind.LOCAL_VARIABLE
                  || elt.getKind() == ElementKind.EXCEPTION_PARAMETER
                  || elt.getKind() == ElementKind.ENUM_CONSTANT
                  || elt.getKind() == ElementKind.PARAMETER))) {
        type.clearAnnotations();
        Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
        set.add(checker.ANY);
        if (elt != null && ElementUtils.isStatic(elt)) set.add(checker.PEER);

        annotateConstants(type, set);
      }
      return super.visitDeclared(type, p);
    }