private void genFunctor(String functorType, String parameterList, String argumentList, String errorClassName, PrintWriter pw) {
        String definitionClass = "org.eigenbase.resgen.ResourceDefinition";
        final String classNameSansPackage = Util.removePackage(className);
        final String bundleThis = classNameSansPackage + ".this";
        String argumentArray = argumentList.equals("") ?
            "emptyObjectArray" :
            "new Object[] {" + argumentList + "}";
        pw.println();
        pw.println("    /**");
        pw.println("     * Definition for resources which");
        if (errorClassName != null) {
            pw.println("     * return a "
                + "{@link " + errorClassName + "} exception and");
        }
        pw.println("     * take arguments '" + parameterList + "'.");
        pw.println("     */");
        pw.println("    public final class " + functorType + " extends " + definitionClass + " {");
        pw.println("        " + functorType + "(String key, String baseMessage, String[] props) {");
        pw.println("            super(key, baseMessage, props);");
        pw.println("        }");
        pw.println("        public String str(" + parameterList + ") {");
        pw.println("            return instantiate(" + addLists(bundleThis, argumentArray) + ").toString();");
        pw.println("        }");
        if (errorClassName != null) {
            final ExceptionDescription ed = new ExceptionDescription(errorClassName);
            if (ed.hasInstCon()) {
                pw.println("        public " + errorClassName + " ex(" + parameterList + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "));");
                pw.println("        }");
            } else if (ed.hasInstThrowCon()) {
                pw.println("        public " + errorClassName + " ex(" + parameterList + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "), null);");
                pw.println("        }");
            } else if (ed.hasStringCon()) {
                pw.println("        public " + errorClassName + " ex(" + parameterList + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString());");
                pw.println("        }");
            } else if (ed.hasStringThrowCon()) {
                pw.println("        public " + errorClassName + " ex(" + parameterList + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString(), null);");
                pw.println("        }");
            }
            if (ed.hasInstThrowCon()) {
                pw.println("        public " + errorClassName + " ex(" + addLists(parameterList, "Throwable err") + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "), err);");
                pw.println("        }");
            } else if (ed.hasStringThrowCon()) {
                pw.println("        public " + errorClassName + " ex(" + addLists(parameterList, "Throwable err") + ") {");
                pw.println("            return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString(), err);");
                pw.println("        }");
            }
        }
        pw.println("    }");
    }