/**
   * Returns a class which has a static method with the same name as 'method', whose body creates an
   * new instance of 'specimen', casts it to 'iface' (including the type parameters) and invokes
   * 'method' upon it via an invokeinterface instruction with 'args' as function call parameters.
   */
  private Class invokeInterfaceHarness(
      Class specimen, Extends iface, AbstractMethod method, String... args) {
    Interface istub =
        new Interface(
            iface.getType().getName(),
            iface.getType().getAccessFlags(),
            iface.getType().getParameters(),
            null,
            Arrays.asList((Method) method));
    Class cstub = new Class(specimen.getName());

    String params = toJoinedString(args, ", ");

    ConcreteMethod sm =
        new ConcreteMethod(
            "int",
            SourceModel.stdMethodName,
            String.format(
                "return ((%s)(new %s())).%s(%s);",
                iface.toString(), specimen.getName(), method.getName(), params),
            new AccessFlag("public"),
            new AccessFlag("static"));
    sm.suppressWarnings();

    Class ii = new Class("II_" + specimen.getName() + "_" + iface.getType().getName(), sm);
    ii.addCompilationDependency(istub);
    ii.addCompilationDependency(cstub);
    ii.addCompilationDependency(method);
    return ii;
  }
  /**
   * Returns a class which has a static method with the same name as 'method', whose body creates an
   * new instance of 'specimen' and invokes 'method' upon it via an invokevirtual instruction with
   * 'args' as function call parameters.
   *
   * <p>'returns' is a dummy return value that need only match 'methods' return type (it is only
   * used in the dummy class when compiling IV).
   */
  private Class invokeVirtualHarness(
      Class specimen, ConcreteMethod method, String returns, String... args) {
    Method cm =
        new ConcreteMethod(
            method.getReturnType(),
            method.getName(),
            "return " + returns + ";",
            method.getElements());
    Class stub = new Class(specimen.getName(), cm);

    String params = toJoinedString(args, ", ");

    ConcreteMethod sm =
        new ConcreteMethod(
            method.getReturnType(),
            method.getName(),
            String.format(
                "return (new %s()).%s(%s);", specimen.getName(), method.getName(), params),
            new AccessFlag("public"),
            new AccessFlag("static"));

    Class iv = new Class("IV_" + specimen.getName(), sm);

    iv.addCompilationDependency(stub);
    iv.addCompilationDependency(cm);

    return iv;
  }