code: private String genericTypeAsString(GenericsType genericsType, boolean showRedirect) {
          String ret = genericsType.getName();
          if (genericsType.getUpperBounds() != null) {
              ret += " extends ";
              for (int i = 0; i < genericsType.getUpperBounds().length; i++) {
                  ClassNode classNode = genericsType.getUpperBounds()[i];
                  if (classNode.equals(this)) {
                      ret += classNode.getName();
                  } else {
                      ret += classNode.toString(showRedirect);
                  }
                  if (i + 1 < genericsType.getUpperBounds().length) ret += " & ";
              }
          } else if (genericsType.getLowerBound() !=null) {
              ClassNode classNode = genericsType.getLowerBound();
              if (classNode.equals(this)) {
                  ret += " super " + classNode.getName();
              } else {
                  ret += " super " + classNode;
              }
          }
          return ret;
      }
docs: This exists to avoid a recursive definition of toString. The default toString
  in GenericsType calls ClassNode.toString(), which calls GenericsType.toString(), etc.
  @param genericsType
  @param showRedirect
  @return the string representing the generic type