/** Print a class's relations */
  public void printRelations(ClassDoc c) {
    Options opt = optionProvider.getOptionsFor(c);
    if (hidden(c)
        || c.name()
            .equals("")) // avoid phantom classes, they may pop up when the source uses annotations
    return;
    String className = c.toString();

    // Print generalization (through the Java superclass)
    Type s = c.superclassType();
    if (s != null
        && !s.toString().equals("java.lang.Object")
        && !c.isEnum()
        && !hidden(s.asClassDoc())) {
      ClassDoc sc = s.asClassDoc();
      w.println(
          "\t//"
              + c
              + " extends "
              + s
              + "\n"
              + "\t"
              + relationNode(sc)
              + " -> "
              + relationNode(c)
              + " [dir=back,arrowtail=empty];");
      getClassInfo(className)
          .addRelation(sc.toString(), RelationType.EXTENDS, RelationDirection.OUT);
      getClassInfo(sc.toString())
          .addRelation(className, RelationType.EXTENDS, RelationDirection.IN);
    }

    // Print generalizations (through @extends tags)
    for (Tag tag : c.tags("extends"))
      if (!hidden(tag.text())) {
        ClassDoc from = c.findClass(tag.text());
        w.println(
            "\t//"
                + c
                + " extends "
                + tag.text()
                + "\n"
                + "\t"
                + relationNode(from, tag.text())
                + " -> "
                + relationNode(c)
                + " [dir=back,arrowtail=empty];");
        getClassInfo(className)
            .addRelation(tag.text(), RelationType.EXTENDS, RelationDirection.OUT);
        getClassInfo(tag.text()).addRelation(className, RelationType.EXTENDS, RelationDirection.IN);
      }
    // Print realizations (Java interfaces)
    for (Type iface : c.interfaceTypes()) {
      ClassDoc ic = iface.asClassDoc();
      if (!hidden(ic)) {
        w.println(
            "\t//"
                + c
                + " implements "
                + ic
                + "\n\t"
                + relationNode(ic)
                + " -> "
                + relationNode(c)
                + " [dir=back,arrowtail=empty,style=dashed];");
        getClassInfo(className)
            .addRelation(ic.toString(), RelationType.IMPLEMENTS, RelationDirection.OUT);
        getClassInfo(ic.toString())
            .addRelation(className, RelationType.IMPLEMENTS, RelationDirection.IN);
      }
    }
    // Print other associations
    allRelation(opt, RelationType.ASSOC, c);
    allRelation(opt, RelationType.NAVASSOC, c);
    allRelation(opt, RelationType.HAS, c);
    allRelation(opt, RelationType.NAVHAS, c);
    allRelation(opt, RelationType.COMPOSED, c);
    allRelation(opt, RelationType.NAVCOMPOSED, c);
    allRelation(opt, RelationType.DEPEND, c);
  }
  /**
   * Print all relations for a given's class's tag
   *
   * @param tagname the tag containing the given relation
   * @param from the source class
   * @param edgetype the dot edge specification
   */
  private void allRelation(Options opt, RelationType rt, ClassDoc from) {
    String tagname = rt.toString().toLowerCase();
    for (Tag tag : from.tags(tagname)) {
      String t[] = StringUtil.tokenize(tag.text()); // l-src label l-dst target
      if (t.length != 4) {
        System.err.println(
            "Error in "
                + from
                + "\n"
                + tagname
                + " expects four fields (l-src label l-dst target): "
                + tag.text());
        return;
      }
      ClassDoc to = from.findClass(t[3]);

      if (to != null) {
        if (hidden(to)) continue;
        relation(opt, rt, from, to, t[0], t[1], t[2]);
      } else {
        if (hidden(t[3])) continue;
        relation(opt, rt, from, from.toString(), to, t[3], t[0], t[1], t[2]);
      }
    }
  }