diff env/lib/python3.7/site-packages/schema_salad/java_codegen.py @ 0:26e78fe6e8c4 draft

"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author shellac
date Sat, 02 May 2020 07:14:21 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.7/site-packages/schema_salad/java_codegen.py	Sat May 02 07:14:21 2020 -0400
@@ -0,0 +1,788 @@
+"""Work-in-progress Java code generator for a given schema salad definition."""
+import os
+import pkg_resources
+import string
+import shutil
+from io import open as io_open
+from typing import Any, Dict, List, MutableMapping, MutableSequence, Optional, Union
+
+from six import iteritems, itervalues
+from six.moves import cStringIO, urllib
+from typing_extensions import Text  # pylint: disable=unused-import
+
+from . import schema
+from .codegen_base import CodeGenBase, TypeDef
+from .exceptions import SchemaException
+from .schema import shortname
+
+# move to a regular typing import when Python 3.3-3.6 is no longer supported
+
+# experiment at providing more typed objects building a optional type that allows
+# referencing one or a list of objects. It is useful for improving the RootLoader
+# for simple schema with a single root loader - but doesn't help with CWL at all and
+# may even confuse things a bit so turning these off be default.
+USE_ONE_OR_LIST_OF_TYPES = False
+
+
+def _ensure_directory_and_write(path, contents):
+    # type: (Text, Text) -> None
+    dirname = os.path.dirname(path)
+    _safe_makedirs(dirname)
+    with io_open(path, mode="w", encoding="utf-8") as f:
+        f.write(contents)
+
+
+def doc_to_doc_string(doc, indent_level=0):
+    # type: (Text, int) -> Text
+    lead = " " + "  " * indent_level + "* " * indent_level
+    if doc:
+        doc_str = "{}<BLOCKQUOTE>\n".format(lead)
+        doc_str += "\n".join(["{}{}".format(lead, l) for l in doc.split("\n")])
+        doc_str += "{}</BLOCKQUOTE>".format(lead)
+    else:
+        doc_str = ""
+    return doc_str
+
+
+def _safe_makedirs(path):
+    # type: (Text) -> None
+    if not os.path.exists(path):
+        os.makedirs(path)
+
+
+class JavaCodeGen(CodeGenBase):
+    def __init__(self, base, target, examples):
+        # type: (Text, Optional[str], Optional[str]) -> None
+        super(JavaCodeGen, self).__init__()
+        self.base_uri = base
+        sp = urllib.parse.urlsplit(base)
+        self.examples = examples
+        self.package = ".".join(
+            list(reversed(sp.netloc.split("."))) + sp.path.strip("/").split("/")
+        )
+        self.artifact = self.package.split(".")[-1]
+        target = target or "."
+        self.target_dir = target
+        rel_package_dir = self.package.replace(".", "/")
+        self.rel_package_dir = rel_package_dir
+        self.main_src_dir = os.path.join(
+            self.target_dir, "src", "main", "java", rel_package_dir
+        )
+        self.test_src_dir = os.path.join(
+            self.target_dir, "src", "test", "java", rel_package_dir
+        )
+        self.test_resources_dir = os.path.join(
+            self.target_dir, "src", "test", "resources", rel_package_dir
+        )
+
+    def prologue(self):  # type: () -> None
+        for src_dir in [self.main_src_dir, self.test_src_dir]:
+            _safe_makedirs(src_dir)
+
+        for primitive in itervalues(self.prims):
+            self.declare_type(primitive)
+
+    @staticmethod
+    def property_name(name):  # type: (Text) -> Text
+        avn = schema.avro_name(name)
+        return avn
+
+    @staticmethod
+    def safe_name(name):  # type: (Text) -> Text
+        avn = JavaCodeGen.property_name(name)
+        if avn in ("class", "extends", "abstract", "default", "package"):
+            # reserved words
+            avn = avn + "_"
+        return avn
+
+    def interface_name(self, n):
+        # type: (Text) -> Text
+        return self.safe_name(n)
+
+    def begin_class(
+        self,
+        classname,  # type: Text
+        extends,  # type: MutableSequence[Text]
+        doc,  # type: Text
+        abstract,  # type: bool
+        field_names,  # type: MutableSequence[Text]
+        idfield,  # type: Text
+    ):  # type: (...) -> None
+        cls = self.interface_name(classname)
+        self.current_class = cls
+        self.current_class_is_abstract = abstract
+        self.current_loader = cStringIO()
+        self.current_fieldtypes = {}  # type: Dict[Text, TypeDef]
+        self.current_fields = cStringIO()
+        interface_doc_str = u"* Auto-generated interface for <I>%s</I><BR>" % classname
+        if not abstract:
+            implemented_by = u"This interface is implemented by {{@link {}Impl}}<BR>"
+            interface_doc_str += implemented_by.format(cls)
+        interface_doc_str += doc_to_doc_string(doc)
+        class_doc_str = u"* Auto-generated class implementation for <I>{}</I><BR>".format(
+            classname
+        )
+        class_doc_str += doc_to_doc_string(doc)
+        with open(os.path.join(self.main_src_dir, "{}.java".format(cls)), "w") as f:
+
+            if extends:
+                ext = (
+                    "extends "
+                    + ", ".join(self.interface_name(e) for e in extends)
+                    + ", Savable"
+                )
+            else:
+                ext = "extends Savable"
+            f.write(
+                """package {package};
+
+import {package}.utils.Savable;
+
+/**
+{interface_doc_str}
+ */
+public interface {cls} {ext} {{""".format(
+                    package=self.package,
+                    cls=cls,
+                    ext=ext,
+                    interface_doc_str=interface_doc_str,
+                )
+            )
+
+        if self.current_class_is_abstract:
+            return
+
+        with open(os.path.join(self.main_src_dir, "{}Impl.java".format(cls)), "w") as f:
+            f.write(
+                """package {package};
+
+import {package}.utils.LoaderInstances;
+import {package}.utils.LoadingOptions;
+import {package}.utils.LoadingOptionsBuilder;
+import {package}.utils.SavableImpl;
+import {package}.utils.ValidationException;
+
+/**
+{class_doc_str}
+ */
+public class {cls}Impl extends SavableImpl implements {cls} {{
+  private LoadingOptions loadingOptions_ = new LoadingOptionsBuilder().build();
+  private java.util.Map<String, Object> extensionFields_ =
+      new java.util.HashMap<String, Object>();
+""".format(
+                    package=self.package, cls=cls, class_doc_str=class_doc_str
+                )
+            )
+        self.current_loader.write(
+            """
+  /**
+   * Used by {{@link {package}.utils.RootLoader}} to construct instances of {cls}Impl.
+   *
+   * @param __doc_            Document fragment to load this record object from (presumably a
+                              {{@link java.util.Map}}).
+   * @param __baseUri_        Base URI to generate child document IDs against.
+   * @param __loadingOptions  Context for loading URIs and populating objects.
+   * @param __docRoot_        ID at this position in the document (if available) (maybe?)
+   * @throws ValidationException If the document fragment is not a {{@link java.util.Map}}
+   *                             or validation of fields fails.
+   */
+  public {cls}Impl(
+      final Object __doc_,
+      final String __baseUri_,
+      LoadingOptions __loadingOptions,
+      final String __docRoot_) {{
+    super(__doc_, __baseUri_, __loadingOptions, __docRoot_);
+    // Prefix plumbing variables with '__' to reduce likelihood of collision with
+    // generated names.
+    String __baseUri = __baseUri_;
+    String __docRoot = __docRoot_;
+    if (!(__doc_ instanceof java.util.Map)) {{
+      throw new ValidationException("{cls}Impl called on non-map");
+    }}
+    final java.util.Map<String, Object> __doc = (java.util.Map<String, Object>) __doc_;
+    final java.util.List<ValidationException> __errors =
+        new java.util.ArrayList<ValidationException>();
+    if (__loadingOptions != null) {{
+      this.loadingOptions_ = __loadingOptions;
+    }}
+""".format(
+                cls=cls, package=self.package
+            )
+        )
+
+    def end_class(self, classname, field_names):
+        # type: (Text, List[Text]) -> None
+        with open(
+            os.path.join(self.main_src_dir, "{}.java".format(self.current_class)), "a"
+        ) as f:
+            f.write(
+                """
+}
+"""
+            )
+        if self.current_class_is_abstract:
+            return
+
+        self.current_loader.write(
+            """    if (!__errors.isEmpty()) {
+      throw new ValidationException("Trying 'RecordField'", __errors);
+    }
+"""
+        )
+        for fieldname in field_names:
+            fieldtype = self.current_fieldtypes.get(fieldname)
+            if fieldtype is None:
+                continue
+            self.current_loader.write(
+                """    this.{safename} = ({type}) {safename};
+""".format(
+                    safename=self.safe_name(fieldname), type=fieldtype.instance_type
+                )
+            )
+
+        self.current_loader.write("""  }""")
+
+        with open(
+            os.path.join(self.main_src_dir, "{}Impl.java".format(self.current_class)),
+            "a",
+        ) as f:
+            f.write(self.current_fields.getvalue())
+            f.write(self.current_loader.getvalue())
+            f.write(
+                """
+}
+"""
+            )
+
+    prims = {
+        u"http://www.w3.org/2001/XMLSchema#string": TypeDef(
+            instance_type="String",
+            init="new PrimitiveLoader<String>(String.class)",
+            name="StringInstance",
+            loader_type="Loader<String>",
+        ),
+        u"http://www.w3.org/2001/XMLSchema#int": TypeDef(
+            instance_type="Integer",
+            init="new PrimitiveLoader<Integer>(Integer.class)",
+            name="IntegerInstance",
+            loader_type="Loader<Integer>",
+        ),
+        u"http://www.w3.org/2001/XMLSchema#long": TypeDef(
+            instance_type="Long",
+            name="LongInstance",
+            loader_type="Loader<Long>",
+            init="new PrimitiveLoader<Long>(Long.class)",
+        ),
+        u"http://www.w3.org/2001/XMLSchema#float": TypeDef(
+            instance_type="Float",
+            name="FloatInstance",
+            loader_type="Loader<Float>",
+            init="new PrimitiveLoader<Float>(Float.class)",
+        ),
+        u"http://www.w3.org/2001/XMLSchema#double": TypeDef(
+            instance_type="Double",
+            name="DoubleInstance",
+            loader_type="Loader<Double>",
+            init="new PrimitiveLoader<Double>(Double.class)",
+        ),
+        u"http://www.w3.org/2001/XMLSchema#boolean": TypeDef(
+            instance_type="Boolean",
+            name="BooleanInstance",
+            loader_type="Loader<Boolean>",
+            init="new PrimitiveLoader<Boolean>(Boolean.class)",
+        ),
+        u"https://w3id.org/cwl/salad#null": TypeDef(
+            instance_type="Object",
+            name="NullInstance",
+            loader_type="Loader<Object>",
+            init="new NullLoader()",
+        ),
+        u"https://w3id.org/cwl/salad#Any": TypeDef(
+            instance_type="Object",
+            name="AnyInstance",
+            init="new AnyLoader()",
+            loader_type="Loader<Object>",
+        ),
+    }
+
+    def type_loader(self, type_declaration):
+        # type: (Union[List[Any], Dict[Text, Any], Text]) -> TypeDef
+        if isinstance(type_declaration, MutableSequence):
+            sub = [self.type_loader(i) for i in type_declaration]
+            if len(sub) < 2:
+                return sub[0]
+
+            if len(sub) == 2:
+                type_1 = sub[0]
+                type_2 = sub[1]
+                type_1_name = type_1.name
+                type_2_name = type_2.name
+                if type_1_name == "NullInstance" or type_2_name == "NullInstance":
+                    non_null_type = type_1 if type_1.name != "NullInstance" else type_2
+                    return self.declare_type(
+                        TypeDef(
+                            instance_type="java.util.Optional<{}>".format(
+                                non_null_type.instance_type
+                            ),
+                            init="new OptionalLoader({})".format(non_null_type.name),
+                            name="optional_{}".format(non_null_type.name),
+                            loader_type="Loader<java.util.Optional<{}>>".format(
+                                non_null_type.instance_type
+                            ),
+                        )
+                    )
+                if (
+                    type_1_name == "array_of_{}".format(type_2_name)
+                    or type_2_name == "array_of_{}".format(type_1_name)
+                ) and USE_ONE_OR_LIST_OF_TYPES:
+                    if type_1_name == "array_of_{}".format(type_2_name):
+                        single_type = type_2
+                        array_type = type_1
+                    else:
+                        single_type = type_1
+                        array_type = type_2
+                    fqclass = "{}.{}".format(self.package, single_type.instance_type)
+                    return self.declare_type(
+                        TypeDef(
+                            instance_type="{}.utils.OneOrListOf<{}>".format(
+                                self.package, fqclass
+                            ),
+                            init="new OneOrListOfLoader<{}>({}, {})".format(
+                                fqclass, single_type.name, array_type.name
+                            ),
+                            name="one_or_array_of_{}".format(single_type.name),
+                            loader_type="Loader<{}.utils.OneOrListOf<{}>>".format(
+                                self.package, fqclass
+                            ),
+                        )
+                    )
+            return self.declare_type(
+                TypeDef(
+                    instance_type="Object",
+                    init="new UnionLoader(new Loader[] {{ {} }})".format(
+                        ", ".join(s.name for s in sub)
+                    ),
+                    name="union_of_{}".format("_or_".join(s.name for s in sub)),
+                    loader_type="Loader<Object>",
+                )
+            )
+        if isinstance(type_declaration, MutableMapping):
+            if type_declaration["type"] in (
+                "array",
+                "https://w3id.org/cwl/salad#array",
+            ):
+                i = self.type_loader(type_declaration["items"])
+                return self.declare_type(
+                    TypeDef(
+                        # special doesn't work out with subclassing, gotta be more clever
+                        # instance_type="List<{}>".format(i.instance_type),
+                        instance_type="java.util.List<Object>",
+                        name="array_of_{}".format(i.name),
+                        init="new ArrayLoader({})".format(i.name),
+                        loader_type="Loader<java.util.List<{}>>".format(
+                            i.instance_type
+                        ),
+                    )
+                )
+            if type_declaration["type"] in ("enum", "https://w3id.org/cwl/salad#enum"):
+                return self.type_loader_enum(type_declaration)
+            if type_declaration["type"] in (
+                "record",
+                "https://w3id.org/cwl/salad#record",
+            ):
+                is_abstract = type_declaration.get("abstract", False)
+                fqclass = "{}.{}".format(
+                    self.package, self.safe_name(type_declaration["name"])
+                )
+                return self.declare_type(
+                    TypeDef(
+                        instance_type=self.safe_name(type_declaration["name"]),
+                        name=self.safe_name(type_declaration["name"]),
+                        init="new RecordLoader<{clazz}>({clazz}{ext}.class)".format(
+                            clazz=fqclass, ext="Impl" if not is_abstract else "",
+                        ),
+                        loader_type="Loader<{}>".format(fqclass),
+                    )
+                )
+            raise SchemaException("wft {}".format(type_declaration["type"]))
+        if type_declaration in self.prims:
+            return self.prims[type_declaration]
+        return self.collected_types[self.safe_name(type_declaration)]
+
+    def type_loader_enum(self, type_declaration):
+        # type: (Dict[Text, Any]) -> TypeDef
+        symbols = [self.property_name(sym) for sym in type_declaration["symbols"]]
+        for sym in symbols:
+            self.add_vocab(shortname(sym), sym)
+        clazz = self.safe_name(type_declaration["name"])
+        symbols_decl = 'new String[] {{"{}"}}'.format(
+            '", "'.join(sym for sym in symbols)
+        )
+        enum_path = os.path.join(self.main_src_dir, "{}.java".format(clazz))
+        with open(enum_path, "w") as f:
+            f.write(
+                """package {package};
+
+import {package}.utils.ValidationException;
+
+public enum {clazz} {{
+""".format(
+                    package=self.package, clazz=clazz
+                )
+            )
+            for i, sym in enumerate(symbols):
+                suffix = "," if i < (len(symbols) - 1) else ";"
+                const = self.safe_name(sym).replace("-", "_").replace(".", "_").upper()
+                f.write(
+                    """  {const}("{val}"){suffix}\n""".format(
+                        const=const, val=sym, suffix=suffix
+                    )
+                )
+            f.write(
+                """
+  private static String[] symbols = {symbols_decl};
+  private String docVal;
+
+  private {clazz}(final String docVal) {{
+    this.docVal = docVal;
+  }}
+
+  public static {clazz} fromDocumentVal(final String docVal) {{
+    for(final {clazz} val : {clazz}.values()) {{
+      if(val.docVal.equals(docVal)) {{
+        return val;
+      }}
+    }}
+    throw new ValidationException(String.format("Expected one of %s", {clazz}.symbols, docVal));
+  }}
+}}
+""".format(
+                    clazz=clazz, symbols_decl=symbols_decl
+                )
+            )
+        return self.declare_type(
+            TypeDef(
+                instance_type=clazz,
+                name=self.safe_name(type_declaration["name"]),
+                loader_type="Loader<{clazz}>".format(clazz=clazz),
+                init="new EnumLoader({clazz}.class)".format(clazz=clazz),
+            )
+        )
+
+    def declare_field(self, name, fieldtype, doc, optional):
+        # type: (Text, TypeDef, Text, bool) -> None
+        fieldname = name
+        property_name = self.property_name(fieldname)
+        cap_case_property_name = property_name[0].upper() + property_name[1:]
+        if cap_case_property_name == "Class":
+            cap_case_property_name = "Class_"
+
+        safename = self.safe_name(fieldname)
+        self.current_fieldtypes[property_name] = fieldtype
+        getter_doc_str = """  /**
+   * Getter for property <I>{fieldname}</I><BR>
+{field_doc_str}
+   */
+""".format(
+            fieldname=fieldname, field_doc_str=doc_to_doc_string(doc, indent_level=1)
+        )
+        with open(
+            os.path.join(self.main_src_dir, "{}.java".format(self.current_class)), "a"
+        ) as f:
+            f.write(
+                """
+{getter_doc_str}
+  {type} get{capfieldname}();""".format(
+                    getter_doc_str=getter_doc_str,
+                    capfieldname=cap_case_property_name,
+                    type=fieldtype.instance_type,
+                )
+            )
+
+        if self.current_class_is_abstract:
+            return
+
+        self.current_fields.write(
+            """
+  private {type} {safename};
+
+{getter_doc_str}
+  public {type} get{capfieldname}() {{
+    return this.{safename};
+  }}
+""".format(
+                safename=safename,
+                capfieldname=cap_case_property_name,
+                getter_doc_str=getter_doc_str,
+                type=fieldtype.instance_type,
+            )
+        )
+
+        self.current_loader.write(
+            """    {type} {safename};
+""".format(
+                type=fieldtype.instance_type, safename=safename
+            )
+        )
+        if optional:
+            self.current_loader.write(
+                """
+    if (__doc.containsKey("{fieldname}")) {{
+""".format(
+                    fieldname=property_name
+                )
+            )
+            spc = "  "
+        else:
+            spc = ""
+
+        self.current_loader.write(
+            """{spc}    try {{
+{spc}      {safename} =
+{spc}          LoaderInstances
+{spc}              .{fieldtype}
+{spc}              .loadField(__doc.get("{fieldname}"), __baseUri, __loadingOptions);
+{spc}    }} catch (ValidationException e) {{
+{spc}      {safename} = null; // won't be used but prevents compiler from complaining.
+{spc}      final String __message = "the `{fieldname}` field is not valid because:";
+{spc}      __errors.add(new ValidationException(__message, e));
+{spc}    }}
+""".format(
+                fieldtype=fieldtype.name,
+                safename=safename,
+                fieldname=property_name,
+                spc=spc,
+            )
+        )
+
+        if optional:
+            self.current_loader.write(
+                """
+    }} else {{
+      {safename} = null;
+    }}
+""".format(
+                    safename=safename
+                )
+            )
+
+    def declare_id_field(self, name, fieldtype, doc, optional):
+        # type: (Text, TypeDef, Text, bool) -> None
+        if self.current_class_is_abstract:
+            return
+
+        self.declare_field(name, fieldtype, doc, True)
+        if optional:
+            set_uri = """
+    if ({safename} == null) {{
+      if (__docRoot != null) {{
+        {safename} = java.util.Optional.of(__docRoot);
+      }} else {{
+        {safename} = java.util.Optional.of("_:" + java.util.UUID.randomUUID().toString());
+      }}
+    }}
+    __baseUri = (String) {safename}.orElse(null);
+"""
+        else:
+            set_uri = """
+    if ({safename} == null) {{
+      if (__docRoot != null) {{
+        {safename} = __docRoot;
+      }} else {{
+        throw new ValidationException("Missing {fieldname}");
+      }}
+    }}
+    __baseUri = (String) {safename};
+"""
+        self.current_loader.write(
+            set_uri.format(safename=self.safe_name(name), fieldname=shortname(name))
+        )
+
+    def uri_loader(self, inner, scoped_id, vocab_term, ref_scope):
+        # type: (TypeDef, bool, bool, Union[int, None]) -> TypeDef
+        assert inner is not None
+        instance_type = inner.instance_type or "Object"
+        return self.declare_type(
+            TypeDef(
+                instance_type=instance_type,  # ?
+                name="uri_{}_{}_{}_{}".format(
+                    inner.name, scoped_id, vocab_term, ref_scope
+                ),
+                init="new UriLoader({}, {}, {}, {})".format(
+                    inner.name,
+                    self.to_java(scoped_id),
+                    self.to_java(vocab_term),
+                    self.to_java(ref_scope),
+                ),
+                is_uri=True,
+                scoped_id=scoped_id,
+                ref_scope=ref_scope,
+                loader_type="Loader<{}>".format(instance_type),
+            )
+        )
+
+    def idmap_loader(self, field, inner, map_subject, map_predicate):
+        # type: (Text, TypeDef, Text, Union[Text, None]) -> TypeDef
+        assert inner is not None
+        instance_type = inner.instance_type or "Object"
+        return self.declare_type(
+            TypeDef(
+                instance_type=instance_type,
+                name="idmap_{}_{}".format(self.safe_name(field), inner.name),
+                init='new IdMapLoader({}, "{}", "{}")'.format(
+                    inner.name, map_subject, map_predicate
+                ),
+                loader_type="Loader<{}>".format(instance_type),
+            )
+        )
+
+    def typedsl_loader(self, inner, ref_scope):
+        # type: (TypeDef, Union[int, None]) -> TypeDef
+        assert inner is not None
+        instance_type = inner.instance_type or "Object"
+        return self.declare_type(
+            TypeDef(
+                instance_type=instance_type,
+                name="typedsl_{}_{}".format(inner.name, ref_scope),
+                init="new TypeDslLoader({}, {})".format(inner.name, ref_scope),
+                loader_type="Loader<{}>".format(instance_type),
+            )
+        )
+
+        return inner
+
+    def to_java(self, val):  # type: (Any) -> Any
+        if val is True:
+            return "true"
+        elif val is None:
+            return "null"
+        elif val is False:
+            return "false"
+        return val
+
+    def epilogue(self, root_loader):  # type: (TypeDef) -> None
+        pd = u"This project contains Java objects and utilities "
+        pd = pd + ' auto-generated by <a href="https://github.com/'
+        pd = pd + 'common-workflow-language/schema_salad">Schema Salad</a>'
+        pd = pd + " for parsing documents corresponding to the "
+        pd = pd + str(self.base_uri) + " schema."
+
+        template_vars = dict(
+            base_uri=self.base_uri,
+            package=self.package,
+            group_id=self.package,
+            artifact_id=self.artifact,
+            version="0.0.1-SNAPSHOT",
+            project_name=self.package,
+            project_description=pd,
+            license_name="Apache License, Version 2.0",
+            license_url="https://www.apache.org/licenses/LICENSE-2.0.txt",
+        )  # type: MutableMapping[Text, Text]
+
+        def template_from_resource(resource):
+            # type: (str) -> string.Template
+            template_str = pkg_resources.resource_string(
+                __name__, "java/%s" % resource
+            ).decode("utf-8")
+            template = string.Template(template_str)
+            return template
+
+        def expand_resource_template_to(resource, path):
+            # type: (str, str) -> None
+            template = template_from_resource(resource)
+            src = template.safe_substitute(template_vars)
+            _ensure_directory_and_write(path, src)
+
+        expand_resource_template_to("pom.xml", os.path.join(self.target_dir, "pom.xml"))
+        expand_resource_template_to(
+            "gitignore", os.path.join(self.target_dir, ".gitignore")
+        )
+        expand_resource_template_to(
+            "package.html", os.path.join(self.main_src_dir, "package.html")
+        )
+        expand_resource_template_to(
+            "overview.html",
+            os.path.join(self.target_dir, "src", "main", "javadoc", "overview.html"),
+        )
+        expand_resource_template_to(
+            "MANIFEST.MF",
+            os.path.join(
+                self.target_dir, "src", "main", "resources", "META-INF", "MANIFEST.MF"
+            ),
+        )
+        expand_resource_template_to(
+            "README.md", os.path.join(self.target_dir, "README.md"),
+        )
+
+        vocab = ""
+        rvocab = ""
+        for k in sorted(self.vocab.keys()):
+            vocab += """    vocab.put("{}", "{}");\n""".format(k, self.vocab[k])
+            rvocab += """    rvocab.put("{}", "{}");\n""".format(self.vocab[k], k)
+
+        loader_instances = ""
+        for _, collected_type in iteritems(self.collected_types):
+            loader_instances += "  public static {} {} = {};\n".format(
+                collected_type.loader_type, collected_type.name, collected_type.init
+            )
+
+        example_tests = ""
+        if self.examples:
+            _safe_makedirs(self.test_resources_dir)
+            utils_resources = os.path.join(self.test_resources_dir, "utils")
+            if os.path.exists(utils_resources):
+                shutil.rmtree(utils_resources)
+            shutil.copytree(self.examples, utils_resources)
+            for example_name in os.listdir(self.examples):
+                if example_name.startswith("valid"):
+                    basename = os.path.basename(example_name).split(".", 1)[0]
+                    example_tests += """
+  @org.junit.Test
+  public void test{basename}ByString() throws Exception {{
+    String path = java.nio.file.Paths.get(".").toAbsolutePath().normalize().toString();
+    String baseUri = Uris.fileUri(path) + "/";
+    java.net.URL url = getClass().getResource("{example_name}");
+    java.nio.file.Path resPath = java.nio.file.Paths.get(url.toURI());
+    String yaml = new String(java.nio.file.Files.readAllBytes(resPath), "UTF8");
+    RootLoader.loadDocument(yaml, baseUri);
+  }}
+
+  @org.junit.Test
+  public void test{basename}ByPath() throws Exception {{
+    java.net.URL url = getClass().getResource("{example_name}");
+    java.nio.file.Path resPath = java.nio.file.Paths.get(url.toURI());
+    RootLoader.loadDocument(resPath);
+  }}
+
+  @org.junit.Test
+  public void test{basename}ByMap() throws Exception {{
+    java.net.URL url = getClass().getResource("{example_name}");
+    java.nio.file.Path resPath = java.nio.file.Paths.get(url.toURI());
+    String yaml = new String(java.nio.file.Files.readAllBytes(resPath), "UTF8");
+    java.util.Map<String, Object> doc;
+    doc = (java.util.Map<String, Object>) YamlUtils.mapFromString(yaml);
+    RootLoader.loadDocument(doc);
+  }}""".format(
+                        basename=basename, example_name=example_name,
+                    )
+
+        template_args = dict(
+            package=self.package,
+            vocab=vocab,
+            rvocab=rvocab,
+            loader_instances=loader_instances,
+            root_loader_name=root_loader.name,
+            root_loader_instance_type=root_loader.instance_type or "Object",
+            example_tests=example_tests,
+        )  # type: MutableMapping[Text, Text]
+
+        util_src_dirs = {
+            "main_utils": self.main_src_dir,
+            "test_utils": self.test_src_dir,
+        }
+        for (util_src, util_target) in util_src_dirs.items():
+            for util in pkg_resources.resource_listdir(__name__, "java/%s" % util_src):
+                src_path = os.path.join(util_target, "utils", util)
+                src_template = template_from_resource(os.path.join(util_src, util))
+                src = src_template.safe_substitute(template_args)
+                _ensure_directory_and_write(src_path, src)