#
# This file was autogenerated using schema-salad-tool --codegen=python
# The code itself is released under the Apache 2.0 license and the help text is
# subject to the license of the original schema.
import copy
import logging
import os
import pathlib
import tempfile
import uuid as _uuid__  # pylint: disable=unused-import # noqa: F401
import xml.sax  # nosec
from abc import ABC, abstractmethod
from io import StringIO
from itertools import chain
from typing import (
    Any,
    Dict,
    List,
    MutableMapping,
    MutableSequence,
    Optional,
    Sequence,
    Tuple,
    Type,
    Union,
    cast,
)
from urllib.parse import quote, urldefrag, urlparse, urlsplit, urlunsplit
from urllib.request import pathname2url

from rdflib import Graph
from rdflib.plugins.parsers.notation3 import BadSyntax
from ruamel.yaml.comments import CommentedMap

from schema_salad.exceptions import SchemaSaladException, ValidationException
from schema_salad.fetcher import DefaultFetcher, Fetcher, MemoryCachingFetcher
from schema_salad.sourceline import SourceLine, add_lc_filename
from schema_salad.utils import CacheType, yaml_no_ts  # requires schema-salad v8.2+

_vocab: Dict[str, str] = {}
_rvocab: Dict[str, str] = {}

_logger = logging.getLogger("salad")


IdxType = MutableMapping[str, Tuple[Any, "LoadingOptions"]]


class LoadingOptions:
    idx: IdxType
    fileuri: Optional[str]
    baseuri: str
    namespaces: MutableMapping[str, str]
    schemas: MutableSequence[str]
    original_doc: Optional[Any]
    addl_metadata: MutableMapping[str, Any]
    fetcher: Fetcher
    vocab: Dict[str, str]
    rvocab: Dict[str, str]
    cache: CacheType
    imports: List[str]
    includes: List[str]
    no_link_check: Optional[bool]
    container: Optional[str]

    def __init__(
        self,
        fetcher: Optional[Fetcher] = None,
        namespaces: Optional[Dict[str, str]] = None,
        schemas: Optional[List[str]] = None,
        fileuri: Optional[str] = None,
        copyfrom: Optional["LoadingOptions"] = None,
        original_doc: Optional[Any] = None,
        addl_metadata: Optional[Dict[str, str]] = None,
        baseuri: Optional[str] = None,
        idx: Optional[IdxType] = None,
        imports: Optional[List[str]] = None,
        includes: Optional[List[str]] = None,
        no_link_check: Optional[bool] = None,
        container: Optional[str] = None,
    ) -> None:
        """Create a LoadingOptions object."""
        self.original_doc = original_doc

        if idx is not None:
            self.idx = idx
        else:
            self.idx = copyfrom.idx if copyfrom is not None else {}

        if fileuri is not None:
            self.fileuri = fileuri
        else:
            self.fileuri = copyfrom.fileuri if copyfrom is not None else None

        if baseuri is not None:
            self.baseuri = baseuri
        else:
            self.baseuri = copyfrom.baseuri if copyfrom is not None else ""

        if namespaces is not None:
            self.namespaces = namespaces
        else:
            self.namespaces = copyfrom.namespaces if copyfrom is not None else {}

        if schemas is not None:
            self.schemas = schemas
        else:
            self.schemas = copyfrom.schemas if copyfrom is not None else []

        if addl_metadata is not None:
            self.addl_metadata = addl_metadata
        else:
            self.addl_metadata = copyfrom.addl_metadata if copyfrom is not None else {}

        if imports is not None:
            self.imports = imports
        else:
            self.imports = copyfrom.imports if copyfrom is not None else []

        if includes is not None:
            self.includes = includes
        else:
            self.includes = copyfrom.includes if copyfrom is not None else []

        if no_link_check is not None:
            self.no_link_check = no_link_check
        else:
            self.no_link_check = copyfrom.no_link_check if copyfrom is not None else False

        if container is not None:
            self.container = container
        else:
            self.container = copyfrom.container if copyfrom is not None else None

        if fetcher is not None:
            self.fetcher = fetcher
        elif copyfrom is not None:
            self.fetcher = copyfrom.fetcher
        else:
            import requests
            from cachecontrol.caches import FileCache
            from cachecontrol.wrapper import CacheControl

            root = pathlib.Path(os.environ.get("HOME", tempfile.gettempdir()))
            session = CacheControl(
                requests.Session(),
                cache=FileCache(root / ".cache" / "salad"),
            )
            self.fetcher: Fetcher = DefaultFetcher({}, session)

        self.cache = self.fetcher.cache if isinstance(self.fetcher, MemoryCachingFetcher) else {}

        self.vocab = _vocab
        self.rvocab = _rvocab

        if self.namespaces is not None:
            self.vocab = self.vocab.copy()
            self.rvocab = self.rvocab.copy()
            for k, v in self.namespaces.items():
                self.vocab[k] = v
                self.rvocab[v] = k

    @property
    def graph(self) -> Graph:
        """Generate a merged rdflib.Graph from all entries in self.schemas."""
        graph = Graph()
        if not self.schemas:
            return graph
        key = str(hash(tuple(self.schemas)))
        if key in self.cache:
            return cast(Graph, self.cache[key])
        for schema in self.schemas:
            fetchurl = (
                self.fetcher.urljoin(self.fileuri, schema)
                if self.fileuri is not None
                else pathlib.Path(schema).resolve().as_uri()
            )
            if fetchurl not in self.cache or self.cache[fetchurl] is True:
                _logger.debug("Getting external schema %s", fetchurl)
                try:
                    content = self.fetcher.fetch_text(fetchurl)
                except Exception as e:
                    _logger.warning("Could not load extension schema %s: %s", fetchurl, str(e))
                    continue
                newGraph = Graph()
                err_msg = "unknown error"
                for fmt in ["xml", "turtle"]:
                    try:
                        newGraph.parse(data=content, format=fmt, publicID=str(fetchurl))
                        self.cache[fetchurl] = newGraph
                        graph += newGraph
                        break
                    except (xml.sax.SAXParseException, TypeError, BadSyntax) as e:
                        err_msg = str(e)
                else:
                    _logger.warning("Could not load extension schema %s: %s", fetchurl, err_msg)
        self.cache[key] = graph
        return graph


class Saveable(ABC):
    """Mark classes than have a save() and fromDoc() function."""

    @classmethod
    @abstractmethod
    def fromDoc(
        cls,
        _doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
    ) -> "Saveable":
        """Construct this object from the result of yaml.load()."""

    @abstractmethod
    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        """Convert this object to a JSON/YAML friendly dictionary."""


def load_field(
    val: Union[str, Dict[str, str]],
    fieldtype: "_Loader",
    baseuri: str,
    loadingOptions: LoadingOptions,
    lc: Optional[List[Any]] = None,
) -> Any:
    """Load field."""
    if isinstance(val, MutableMapping):
        if "$import" in val:
            if loadingOptions.fileuri is None:
                raise SchemaSaladException("Cannot load $import without fileuri")
            url = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$import"])
            result, metadata = _document_load_by_url(
                fieldtype,
                url,
                loadingOptions,
            )
            loadingOptions.imports.append(url)
            return result
        if "$include" in val:
            if loadingOptions.fileuri is None:
                raise SchemaSaladException("Cannot load $import without fileuri")
            url = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$include"])
            val = loadingOptions.fetcher.fetch_text(url)
            loadingOptions.includes.append(url)
    return fieldtype.load(val, baseuri, loadingOptions, lc=lc)


save_type = Optional[Union[MutableMapping[str, Any], MutableSequence[Any], int, float, bool, str]]


def extract_type(val_type: Type[Any]) -> str:
    """Take a type of value, and extracts the value as a string."""
    val_str = str(val_type)
    return val_str.split("'")[1]


def convert_typing(val_type: str) -> str:
    """Normalize type names to schema-salad types."""
    if "None" in val_type:
        return "null"
    if "CommentedSeq" in val_type or "list" in val_type:
        return "array"
    if "CommentedMap" in val_type or "dict" in val_type:
        return "object"
    if "False" in val_type or "True" in val_type:
        return "boolean"
    return val_type


def parse_errors(error_message: str) -> Tuple[str, str, str]:
    """Parse error messages from several loaders into one error message."""
    if not error_message.startswith("Expected"):
        return error_message, "", ""
    vals = error_message.split("\n")
    if len(vals) == 1:
        return error_message, "", ""
    types = set()
    for val in vals:
        individual_vals = val.split(" ")
        if val == "":
            continue
        if individual_vals[1] == "one":
            individual_vals = val.split("(")[1].split(",")
            for t in individual_vals:
                types.add(t.strip(" ").strip(")\n"))
        elif individual_vals[2] == "<class":
            types.add(individual_vals[3].strip(">").replace("'", ""))
        elif individual_vals[0] == "Value":
            types.add(individual_vals[-1].strip("."))
        else:
            types.add(individual_vals[1].replace(",", ""))
    types = set(val for val in types if val != "NoneType")
    if "str" in types:
        types = set(convert_typing(val) for val in types if "'" not in val)
    to_print = ""
    for val in types:
        if "'" in val:
            to_print = "value" if len(types) == 1 else "values"

    if to_print == "":
        to_print = "type" if len(types) == 1 else "types"

    verb_tensage = "is" if len(types) == 1 else "are"

    return str(types).replace("{", "(").replace("}", ")").replace("'", ""), to_print, verb_tensage


def save(
    val: Any,
    top: bool = True,
    base_url: str = "",
    relative_uris: bool = True,
) -> save_type:
    if isinstance(val, Saveable):
        return val.save(top=top, base_url=base_url, relative_uris=relative_uris)
    if isinstance(val, MutableSequence):
        return [save(v, top=False, base_url=base_url, relative_uris=relative_uris) for v in val]
    if isinstance(val, MutableMapping):
        newdict = {}
        for key in val:
            newdict[key] = save(val[key], top=False, base_url=base_url, relative_uris=relative_uris)
        return newdict
    if val is None or isinstance(val, (int, float, bool, str)):
        return val
    raise Exception("Not Saveable: %s" % type(val))


def save_with_metadata(
    val: Any,
    valLoadingOpts: LoadingOptions,
    top: bool = True,
    base_url: str = "",
    relative_uris: bool = True,
) -> save_type:
    """Save and set $namespaces, $schemas, $base and any other metadata fields at the top level."""
    saved_val = save(val, top, base_url, relative_uris)
    newdict: MutableMapping[str, Any] = {}
    if isinstance(saved_val, MutableSequence):
        newdict = {"$graph": saved_val}
    elif isinstance(saved_val, MutableMapping):
        newdict = saved_val

    if valLoadingOpts.namespaces:
        newdict["$namespaces"] = valLoadingOpts.namespaces
    if valLoadingOpts.schemas:
        newdict["$schemas"] = valLoadingOpts.schemas
    if valLoadingOpts.baseuri:
        newdict["$base"] = valLoadingOpts.baseuri
    for k, v in valLoadingOpts.addl_metadata.items():
        if k not in newdict:
            newdict[k] = v

    return newdict


def expand_url(
    url: str,
    base_url: str,
    loadingOptions: LoadingOptions,
    scoped_id: bool = False,
    vocab_term: bool = False,
    scoped_ref: Optional[int] = None,
) -> str:
    if url in ("@id", "@type"):
        return url

    if vocab_term and url in loadingOptions.vocab:
        return url

    if bool(loadingOptions.vocab) and ":" in url:
        prefix = url.split(":")[0]
        if prefix in loadingOptions.vocab:
            url = loadingOptions.vocab[prefix] + url[len(prefix) + 1 :]

    split = urlsplit(url)

    if (
        (bool(split.scheme) and split.scheme in loadingOptions.fetcher.supported_schemes())
        or url.startswith("$(")
        or url.startswith("${")
    ):
        pass
    elif scoped_id and not bool(split.fragment):
        splitbase = urlsplit(base_url)
        frg = ""
        if bool(splitbase.fragment):
            frg = splitbase.fragment + "/" + split.path
        else:
            frg = split.path
        pt = splitbase.path if splitbase.path != "" else "/"
        url = urlunsplit((splitbase.scheme, splitbase.netloc, pt, splitbase.query, frg))
    elif scoped_ref is not None and not bool(split.fragment):
        splitbase = urlsplit(base_url)
        sp = splitbase.fragment.split("/")
        n = scoped_ref
        while n > 0 and len(sp) > 0:
            sp.pop()
            n -= 1
        sp.append(url)
        url = urlunsplit(
            (
                splitbase.scheme,
                splitbase.netloc,
                splitbase.path,
                splitbase.query,
                "/".join(sp),
            )
        )
    else:
        url = loadingOptions.fetcher.urljoin(base_url, url)

    if vocab_term:
        split = urlsplit(url)
        if bool(split.scheme):
            if url in loadingOptions.rvocab:
                return loadingOptions.rvocab[url]
        else:
            raise ValidationException(f"Term {url!r} not in vocabulary")

    return url


class _Loader:
    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        pass


class _AnyLoader(_Loader):
    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if doc is not None:
            return doc
        raise ValidationException("Expected non-null")


class _PrimitiveLoader(_Loader):
    def __init__(self, tp: Union[type, Tuple[Type[str], Type[str]]]) -> None:
        self.tp = tp

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if not isinstance(doc, self.tp):
            raise ValidationException(
                "Expected a {} but got {}".format(self.tp, doc.__class__.__name__)
            )
        return doc

    def __repr__(self) -> str:
        return str(self.tp)


class _ArrayLoader(_Loader):
    def __init__(self, items: _Loader) -> None:
        self.items = items

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if not isinstance(doc, MutableSequence):
            raise ValidationException(
                f"Value is a {convert_typing(extract_type(type(doc)))}, "
                f"but valid type for this field is an array."
            )
        r: List[Any] = []
        errors: List[SchemaSaladException] = []
        fields: List[str] = []
        for i in range(0, len(doc)):
            try:
                lf = load_field(
                    doc[i], _UnionLoader(([self, self.items])), baseuri, loadingOptions, lc=lc
                )
                flatten = loadingOptions.container != "@list"
                if flatten and isinstance(lf, MutableSequence):
                    r.extend(lf)
                else:
                    r.append(lf)

                if isinstance(doc[i], CommentedMap):
                    if doc[i].get("id") is not None:
                        if doc[i].get("id") in fields:
                            errors.append(
                                ValidationException(
                                    f"Duplicate field {doc[i].get('id')!r}",
                                    SourceLine(doc[i], "id", str),
                                    [],
                                )
                            )
                        else:
                            fields.append(doc[i].get("id"))

            except ValidationException as e:
                e = ValidationException(
                    "array item is invalid because", SourceLine(doc, i, str), [e]
                )
                errors.append(e)
        if errors:
            raise ValidationException("", None, errors)
        return r

    def __repr__(self) -> str:
        return f"array<{self.items}>"


class _MapLoader(_Loader):
    def __init__(
        self,
        values: _Loader,
        name: Optional[str] = None,
        container: Optional[str] = None,
        no_link_check: Optional[bool] = None,
    ) -> None:
        self.values = values
        self.name = name
        self.container = container
        self.no_link_check = no_link_check

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if not isinstance(doc, MutableMapping):
            raise ValidationException(f"Expected a map, was {type(doc)}")
        if self.container is not None or self.no_link_check is not None:
            loadingOptions = LoadingOptions(
                copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check
            )
        r: Dict[str, Any] = {}
        errors: List[SchemaSaladException] = []
        for k, v in doc.items():
            try:
                lf = load_field(v, self.values, baseuri, loadingOptions, lc)
                r[k] = lf
            except ValidationException as e:
                errors.append(e.with_sourceline(SourceLine(doc, k, str)))
        if errors:
            raise ValidationException("", None, errors)
        return r

    def __repr__(self) -> str:
        return self.name if self.name is not None else f"map<string, {self.values}>"


class _EnumLoader(_Loader):
    def __init__(self, symbols: Sequence[str], name: str) -> None:
        self.symbols = symbols
        self.name = name

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if doc in self.symbols:
            return doc
        raise ValidationException(f"Expected one of {self.symbols}")

    def __repr__(self) -> str:
        return self.name


class _SecondaryDSLLoader(_Loader):
    def __init__(self, inner: _Loader) -> None:
        self.inner = inner

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        r: List[Dict[str, Any]] = []
        if isinstance(doc, MutableSequence):
            for d in doc:
                if isinstance(d, str):
                    if d.endswith("?"):
                        r.append({"pattern": d[:-1], "required": False})
                    else:
                        r.append({"pattern": d})
                elif isinstance(d, dict):
                    new_dict: Dict[str, Any] = {}
                    dict_copy = copy.deepcopy(d)
                    if "pattern" in dict_copy:
                        new_dict["pattern"] = dict_copy.pop("pattern")
                    else:
                        raise ValidationException(
                            f"Missing pattern in secondaryFiles specification entry: {d}"
                        )
                    new_dict["required"] = (
                        dict_copy.pop("required") if "required" in dict_copy else None
                    )

                    if len(dict_copy):
                        raise ValidationException(
                            "Unallowed values in secondaryFiles specification entry: {}".format(
                                dict_copy
                            )
                        )
                    r.append(new_dict)

                else:
                    raise ValidationException(
                        "Expected a string or sequence of (strings or mappings)."
                    )
        elif isinstance(doc, MutableMapping):
            new_dict = {}
            doc_copy = copy.deepcopy(doc)
            if "pattern" in doc_copy:
                new_dict["pattern"] = doc_copy.pop("pattern")
            else:
                raise ValidationException(
                    f"Missing pattern in secondaryFiles specification entry: {doc}"
                )
            new_dict["required"] = doc_copy.pop("required") if "required" in doc_copy else None

            if len(doc_copy):
                raise ValidationException(
                    f"Unallowed values in secondaryFiles specification entry: {doc_copy}"
                )
            r.append(new_dict)

        elif isinstance(doc, str):
            if doc.endswith("?"):
                r.append({"pattern": doc[:-1], "required": False})
            else:
                r.append({"pattern": doc})
        else:
            raise ValidationException("Expected str or sequence of str")
        return self.inner.load(r, baseuri, loadingOptions, docRoot, lc=lc)


class _RecordLoader(_Loader):
    def __init__(
        self,
        classtype: Type[Saveable],
        container: Optional[str] = None,
        no_link_check: Optional[bool] = None,
    ) -> None:
        self.classtype = classtype
        self.container = container
        self.no_link_check = no_link_check

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if not isinstance(doc, MutableMapping):
            raise ValidationException(
                f"Value is a {convert_typing(extract_type(type(doc)))}, "
                f"but valid type for this field is an object."
            )
        if self.container is not None or self.no_link_check is not None:
            loadingOptions = LoadingOptions(
                copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check
            )
        return self.classtype.fromDoc(doc, baseuri, loadingOptions, docRoot=docRoot)

    def __repr__(self) -> str:
        return str(self.classtype.__name__)


class _ExpressionLoader(_Loader):
    def __init__(self, items: Type[str]) -> None:
        self.items = items

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if not isinstance(doc, str):
            raise ValidationException(
                f"Value is a {convert_typing(extract_type(type(doc)))}, "
                f"but valid type for this field is a str."
            )
        return doc


class _UnionLoader(_Loader):
    def __init__(self, alternates: Sequence[_Loader], name: Optional[str] = None) -> None:
        self.alternates = alternates
        self.name = name

    def add_loaders(self, loaders: Sequence[_Loader]) -> None:
        self.alternates = tuple(loader for loader in chain(self.alternates, loaders))

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        errors = []

        if lc is None:
            lc = []

        for t in self.alternates:
            try:
                return t.load(doc, baseuri, loadingOptions, docRoot=docRoot, lc=lc)
            except ValidationException as e:
                if isinstance(t, _ArrayLoader) and len(self.alternates) > 1:
                    continue
                if isinstance(doc, (CommentedMap, dict)):
                    if "class" in doc:
                        if str(doc.get("class")) == str(t):
                            errors.append(
                                ValidationException(
                                    f"Object `{baseuri.split('/')[-1]}` is not valid because:",
                                    SourceLine(doc, next(iter(doc)), str),
                                    [e],
                                )
                            )
                    else:
                        if "array" in str(t):
                            continue
                        else:
                            if "id" in doc:
                                id = baseuri.split("/")[-1] + "#" + str(doc.get("id"))
                                if "id" in lc:
                                    errors.append(
                                        ValidationException(
                                            f"checking object `{id}`",
                                            SourceLine(lc, "id", str),
                                            [e],
                                        )
                                    )
                                else:
                                    errors.append(
                                        ValidationException(
                                            f"checking object `{id}`",
                                            SourceLine(lc, doc.get("id"), str),
                                            [e],
                                        )
                                    )
                            else:
                                if not isinstance(
                                    t, (_PrimitiveLoader)
                                ):  # avoids 'tried <class "NoneType"> was {x}' errors
                                    errors.append(
                                        ValidationException(f"tried `{t}` but", None, [e])
                                    )
                else:
                    # avoids "tried <class "CWLType"> but x" and instead returns the values for parsing
                    errors.append(ValidationException("", None, [e]))

        if isinstance(doc, (CommentedMap, dict)) and "class" in doc:
            if str(doc.get("class")) not in str(self.alternates):
                errors.append(
                    ValidationException(
                        "Field `class` contains undefined reference to "
                        + "`"
                        + "/".join(baseuri.split("/")[0:-1])
                        + "/"
                        + str(doc.get("class"))
                        + "`",
                        SourceLine(doc, "class", str),
                        [],
                    )
                )
        raise ValidationException("", None, errors, "*")

    def __repr__(self) -> str:
        return self.name if self.name is not None else " | ".join(str(a) for a in self.alternates)


class _URILoader(_Loader):
    def __init__(
        self,
        inner: _Loader,
        scoped_id: bool,
        vocab_term: bool,
        scoped_ref: Optional[int],
        no_link_check: Optional[bool],
    ) -> None:
        self.inner = inner
        self.scoped_id = scoped_id
        self.vocab_term = vocab_term
        self.scoped_ref = scoped_ref
        self.no_link_check = no_link_check

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if self.no_link_check is not None:
            loadingOptions = LoadingOptions(
                copyfrom=loadingOptions, no_link_check=self.no_link_check
            )
        if isinstance(doc, MutableSequence):
            newdoc = []
            for i in doc:
                if isinstance(i, str):
                    newdoc.append(
                        expand_url(
                            i,
                            baseuri,
                            loadingOptions,
                            self.scoped_id,
                            self.vocab_term,
                            self.scoped_ref,
                        )
                    )
                else:
                    newdoc.append(i)
            doc = newdoc
        elif isinstance(doc, str):
            doc = expand_url(
                doc,
                baseuri,
                loadingOptions,
                self.scoped_id,
                self.vocab_term,
                self.scoped_ref,
            )
        if isinstance(doc, str):
            if not loadingOptions.no_link_check:
                errors = []
                try:
                    if not loadingOptions.fetcher.check_exists(doc):
                        errors.append(
                            ValidationException(f"contains undefined reference to `{doc}`")
                        )
                except ValidationException:
                    pass
                if len(errors) > 0:
                    raise ValidationException("", None, errors)
        return self.inner.load(doc, baseuri, loadingOptions, lc=lc)


class _TypeDSLLoader(_Loader):
    def __init__(self, inner: _Loader, refScope: Optional[int], salad_version: str) -> None:
        self.inner = inner
        self.refScope = refScope
        self.salad_version = salad_version

    def resolve(
        self,
        doc: str,
        baseuri: str,
        loadingOptions: LoadingOptions,
    ) -> Union[List[Union[Dict[str, Any], str]], Dict[str, Any], str]:
        doc_ = doc
        optional = False
        if doc_.endswith("?"):
            optional = True
            doc_ = doc_[0:-1]

        if doc_.endswith("[]"):
            salad_versions = [int(v) for v in self.salad_version[1:].split(".")]
            items: Union[List[Union[Dict[str, Any], str]], Dict[str, Any], str] = ""
            rest = doc_[0:-2]
            if salad_versions < [1, 3]:
                if rest.endswith("[]"):
                    # To show the error message with the original type
                    return doc
                else:
                    items = expand_url(rest, baseuri, loadingOptions, False, True, self.refScope)
            else:
                items = self.resolve(rest, baseuri, loadingOptions)
                if isinstance(items, str):
                    items = expand_url(items, baseuri, loadingOptions, False, True, self.refScope)
            expanded: Union[Dict[str, Any], str] = {"type": "array", "items": items}
        else:
            expanded = expand_url(doc_, baseuri, loadingOptions, False, True, self.refScope)

        if optional:
            return ["null", expanded]
        else:
            return expanded

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if isinstance(doc, MutableSequence):
            r: List[Any] = []
            for d in doc:
                if isinstance(d, str):
                    resolved = self.resolve(d, baseuri, loadingOptions)
                    if isinstance(resolved, MutableSequence):
                        for i in resolved:
                            if i not in r:
                                r.append(i)
                    else:
                        if resolved not in r:
                            r.append(resolved)
                else:
                    r.append(d)
            doc = r
        elif isinstance(doc, str):
            doc = self.resolve(doc, baseuri, loadingOptions)

        return self.inner.load(doc, baseuri, loadingOptions, lc=lc)


class _IdMapLoader(_Loader):
    def __init__(self, inner: _Loader, mapSubject: str, mapPredicate: Optional[str]) -> None:
        self.inner = inner
        self.mapSubject = mapSubject
        self.mapPredicate = mapPredicate

    def load(
        self,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None,
        lc: Optional[List[Any]] = None,
    ) -> Any:
        if isinstance(doc, MutableMapping):
            r: List[Any] = []
            for k in sorted(doc.keys()):
                val = doc[k]
                if isinstance(val, CommentedMap):
                    v = copy.copy(val)
                    v.lc.data = val.lc.data
                    v.lc.filename = val.lc.filename
                    v[self.mapSubject] = k
                    r.append(v)
                elif isinstance(val, MutableMapping):
                    v2 = copy.copy(val)
                    v2[self.mapSubject] = k
                    r.append(v2)
                else:
                    if self.mapPredicate:
                        v3 = {self.mapPredicate: val}
                        v3[self.mapSubject] = k
                        r.append(v3)
                    else:
                        raise ValidationException("No mapPredicate")
            doc = r
        return self.inner.load(doc, baseuri, loadingOptions, lc=lc)


def _document_load(
    loader: _Loader,
    doc: Union[str, MutableMapping[str, Any], MutableSequence[Any]],
    baseuri: str,
    loadingOptions: LoadingOptions,
    addl_metadata_fields: Optional[MutableSequence[str]] = None,
) -> Tuple[Any, LoadingOptions]:
    if isinstance(doc, str):
        return _document_load_by_url(
            loader,
            loadingOptions.fetcher.urljoin(baseuri, doc),
            loadingOptions,
            addl_metadata_fields=addl_metadata_fields,
        )

    if isinstance(doc, MutableMapping):
        addl_metadata = {}
        if addl_metadata_fields is not None:
            for mf in addl_metadata_fields:
                if mf in doc:
                    addl_metadata[mf] = doc[mf]

        docuri = baseuri
        if "$base" in doc:
            baseuri = doc["$base"]

        loadingOptions = LoadingOptions(
            copyfrom=loadingOptions,
            namespaces=doc.get("$namespaces", None),
            schemas=doc.get("$schemas", None),
            baseuri=doc.get("$base", None),
            addl_metadata=addl_metadata,
        )

        doc = copy.copy(doc)
        if "$namespaces" in doc:
            doc.pop("$namespaces")
        if "$schemas" in doc:
            doc.pop("$schemas")
        if "$base" in doc:
            doc.pop("$base")

        if "$graph" in doc:
            loadingOptions.idx[baseuri] = (
                loader.load(doc["$graph"], baseuri, loadingOptions),
                loadingOptions,
            )
        else:
            loadingOptions.idx[baseuri] = (
                loader.load(doc, baseuri, loadingOptions, docRoot=baseuri),
                loadingOptions,
            )

        if docuri != baseuri:
            loadingOptions.idx[docuri] = loadingOptions.idx[baseuri]

        return loadingOptions.idx[baseuri]

    if isinstance(doc, MutableSequence):
        loadingOptions.idx[baseuri] = (
            loader.load(doc, baseuri, loadingOptions),
            loadingOptions,
        )
        return loadingOptions.idx[baseuri]

    raise ValidationException(
        "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc)
    )


def _document_load_by_url(
    loader: _Loader,
    url: str,
    loadingOptions: LoadingOptions,
    addl_metadata_fields: Optional[MutableSequence[str]] = None,
) -> Tuple[Any, LoadingOptions]:
    if url in loadingOptions.idx:
        return loadingOptions.idx[url]

    doc_url, frg = urldefrag(url)

    text = loadingOptions.fetcher.fetch_text(doc_url)
    textIO = StringIO(text)
    textIO.name = str(doc_url)
    yaml = yaml_no_ts()
    result = yaml.load(textIO)
    add_lc_filename(result, doc_url)

    loadingOptions = LoadingOptions(copyfrom=loadingOptions, fileuri=doc_url)

    _document_load(
        loader,
        result,
        doc_url,
        loadingOptions,
        addl_metadata_fields=addl_metadata_fields,
    )

    return loadingOptions.idx[url]


def file_uri(path: str, split_frag: bool = False) -> str:
    """Transform a file path into a URL with file scheme."""
    if path.startswith("file://"):
        return path
    if split_frag:
        pathsp = path.split("#", 2)
        frag = "#" + quote(str(pathsp[1])) if len(pathsp) == 2 else ""
        urlpath = pathname2url(str(pathsp[0]))
    else:
        urlpath = pathname2url(path)
        frag = ""
    if urlpath.startswith("//"):
        return f"file:{urlpath}{frag}"
    return f"file://{urlpath}{frag}"


def prefix_url(url: str, namespaces: Dict[str, str]) -> str:
    """Expand short forms into full URLs using the given namespace dictionary."""
    for k, v in namespaces.items():
        if url.startswith(v):
            return k + ":" + url[len(v) :]
    return url


def save_relative_uri(
    uri: Any,
    base_url: str,
    scoped_id: bool,
    ref_scope: Optional[int],
    relative_uris: bool,
) -> Any:
    """Convert any URI to a relative one, obeying the scoping rules."""
    if isinstance(uri, MutableSequence):
        return [save_relative_uri(u, base_url, scoped_id, ref_scope, relative_uris) for u in uri]
    elif isinstance(uri, str):
        if not relative_uris or uri == base_url:
            return uri
        urisplit = urlsplit(uri)
        basesplit = urlsplit(base_url)
        if urisplit.scheme == basesplit.scheme and urisplit.netloc == basesplit.netloc:
            if urisplit.path != basesplit.path:
                p = os.path.relpath(urisplit.path, os.path.dirname(basesplit.path))
                if urisplit.fragment:
                    p = p + "#" + urisplit.fragment
                return p

            basefrag = basesplit.fragment + "/"
            if ref_scope:
                sp = basefrag.split("/")
                i = 0
                while i < ref_scope:
                    sp.pop()
                    i += 1
                basefrag = "/".join(sp)

            if urisplit.fragment.startswith(basefrag):
                return urisplit.fragment[len(basefrag) :]
            return urisplit.fragment
        return uri
    else:
        return save(uri, top=False, base_url=base_url, relative_uris=relative_uris)


def shortname(inputid: str) -> str:
    """
    Compute the shortname of a fully qualified identifier.

    See https://w3id.org/cwl/v1.2/SchemaSalad.html#Short_names.
    """
    parsed_id = urlparse(inputid)
    if parsed_id.fragment:
        return parsed_id.fragment.split("/")[-1]
    return parsed_id.path.split("/")[-1]


def parser_info() -> str:
    return "org.w3id.cwl.v1_0"


class Documented(Saveable):
    pass


class RecordField(Documented):
    """
    A field of a record.
    """

    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, RecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "RecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type"])


class RecordSchema(Saveable):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, RecordSchema):
            return bool(self.fields == other.fields and self.type_ == other.type_)
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "RecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type"])


class EnumSchema(Saveable):
    """
    Define an enumerated type.

    """

    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name
        self.symbols = symbols
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, EnumSchema):
            return bool(
                self.name == other.name
                and self.symbols == other.symbols
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash((self.name, self.symbols, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "EnumSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        try:
            if _doc.get("symbols") is None:
                raise ValidationException("missing required field `symbols`", None, [])

            symbols = load_field(
                _doc.get("symbols"),
                uri_array_of_strtype_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("symbols")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `symbols`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("symbols"))))
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Enum_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `name`, `symbols`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            symbols=symbols,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["name", "symbols", "type"])


class ArraySchema(Saveable):
    def __init__(
        self,
        items: Any,
        type_: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ArraySchema):
            return bool(self.items == other.items and self.type_ == other.type_)
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type"])


class MapSchema(Saveable):
    def __init__(
        self,
        type_: Any,
        values: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.type_ = type_
        self.values = values

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, MapSchema):
            return bool(self.type_ == other.type_ and self.values == other.values)
        return False

    def __hash__(self) -> int:
        return hash((self.type_, self.values))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "MapSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Map_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("values") is None:
                raise ValidationException("missing required field `values`", None, [])

            values = load_field(
                _doc.get("values"),
                uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("values")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `values`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("values"))))
                    _errors__.append(
                        ValidationException(
                            "the `values` field is not valid because:",
                            SourceLine(_doc, "values", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `values` field is not valid because:",
                            SourceLine(_doc, "values", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `type`, `values`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            type_=type_,
            values=values,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.values is not None:
            u = save_relative_uri(self.values, base_url, False, 2, relative_uris)
            r["values"] = u

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["type", "values"])


class UnionSchema(Saveable):
    def __init__(
        self,
        names: Any,
        type_: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.names = names
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, UnionSchema):
            return bool(self.names == other.names and self.type_ == other.type_)
        return False

    def __hash__(self) -> int:
        return hash((self.names, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "UnionSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("names") is None:
                raise ValidationException("missing required field `names`", None, [])

            names = load_field(
                _doc.get("names"),
                uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("names")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `names`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("names"))))
                    _errors__.append(
                        ValidationException(
                            "the `names` field is not valid because:",
                            SourceLine(_doc, "names", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `names` field is not valid because:",
                            SourceLine(_doc, "names", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Union_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `names`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            names=names,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.names is not None:
            u = save_relative_uri(self.names, base_url, False, 2, relative_uris)
            r["names"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["names", "type"])


class CWLArraySchema(ArraySchema):
    def __init__(
        self,
        items: Any,
        type_: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CWLArraySchema):
            return bool(self.items == other.items and self.type_ == other.type_)
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CWLArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type"])


class CWLRecordField(RecordField):
    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CWLRecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CWLRecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type"])


class CWLRecordSchema(RecordSchema):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CWLRecordSchema):
            return bool(self.fields == other.fields and self.type_ == other.type_)
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CWLRecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type"])


class File(Saveable):
    """
    Represents a file (or group of files when `secondaryFiles` is provided) that
    will be accessible by tools using standard POSIX file system call API such as
    open(2) and read(2).

    Files are represented as objects with `class` of `File`.  File objects have
    a number of properties that provide metadata about the file.

    The `location` property of a File is a URI that uniquely identifies the
    file.  Implementations must support the file:// URI scheme and may support
    other schemes such as http://.  The value of `location` may also be a
    relative reference, in which case it must be resolved relative to the URI
    of the document it appears in.  Alternately to `location`, implementations
    must also accept the `path` property on File, which must be a filesystem
    path available on the same host as the CWL runner (for inputs) or the
    runtime environment of a command line tool execution (for command line tool
    outputs).

    If no `location` or `path` is specified, a file object must specify
    `contents` with the UTF-8 text content of the file.  This is a "file
    literal".  File literals do not correspond to external resources, but are
    created on disk with `contents` with when needed for a executing a tool.
    Where appropriate, expressions can return file literals to define new files
    on a runtime.  The maximum size of `contents` is 64 kilobytes.

    The `basename` property defines the filename on disk where the file is
    staged.  This may differ from the resource name.  If not provided,
    `basename` must be computed from the last path part of `location` and made
    available to expressions.

    The `secondaryFiles` property is a list of File or Directory objects that
    must be staged in the same directory as the primary file.  It is an error
    for file names to be duplicated in `secondaryFiles`.

    The `size` property is the size in bytes of the File.  It must be computed
    from the resource and made available to expressions.  The `checksum` field
    contains a cryptographic hash of the file content for use it verifying file
    contents.  Implementations may, at user option, enable or disable
    computation of the `checksum` field for performance or other reasons.
    However, the ability to compute output checksums is required to pass the
    CWL conformance test suite.

    When executing a CommandLineTool, the files and secondary files may be
    staged to an arbitrary directory, but must use the value of `basename` for
    the filename.  The `path` property must be file path in the context of the
    tool execution runtime (local to the compute node, or within the executing
    container).  All computed properties should be available to expressions.
    File literals also must be staged and `path` must be set.

    When collecting CommandLineTool outputs, `glob` matching returns file paths
    (with the `path` property) and the derived properties. This can all be
    modified by `outputEval`.  Alternately, if the file `cwl.output.json` is
    present in the output, `outputBinding` is ignored.

    File objects in the output must provide either a `location` URI or a `path`
    property in the context of the tool execution runtime (local to the compute
    node, or within the executing container).

    When evaluating an ExpressionTool, file objects must be referenced via
    `location` (the expression tool does not have access to files on disk so
    `path` is meaningless) or as file literals.  It is legal to return a file
    object with an existing `location` but a different `basename`.  The
    `loadContents` field of ExpressionTool inputs behaves the same as on
    CommandLineTool inputs, however it is not meaningful on the outputs.

    An ExpressionTool may forward file references from input to output by using
    the same value for `location`.

    """

    def __init__(
        self,
        location: Optional[Any] = None,
        path: Optional[Any] = None,
        basename: Optional[Any] = None,
        dirname: Optional[Any] = None,
        nameroot: Optional[Any] = None,
        nameext: Optional[Any] = None,
        checksum: Optional[Any] = None,
        size: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        format: Optional[Any] = None,
        contents: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "File"
        self.location = location
        self.path = path
        self.basename = basename
        self.dirname = dirname
        self.nameroot = nameroot
        self.nameext = nameext
        self.checksum = checksum
        self.size = size
        self.secondaryFiles = secondaryFiles
        self.format = format
        self.contents = contents

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, File):
            return bool(
                self.class_ == other.class_
                and self.location == other.location
                and self.path == other.path
                and self.basename == other.basename
                and self.dirname == other.dirname
                and self.nameroot == other.nameroot
                and self.nameext == other.nameext
                and self.checksum == other.checksum
                and self.size == other.size
                and self.secondaryFiles == other.secondaryFiles
                and self.format == other.format
                and self.contents == other.contents
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.class_,
                self.location,
                self.path,
                self.basename,
                self.dirname,
                self.nameroot,
                self.nameext,
                self.checksum,
                self.size,
                self.secondaryFiles,
                self.format,
                self.contents,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "File":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "File":
            raise ValidationException("tried `File` but")

        if "location" in _doc:
            try:
                location = load_field(
                    _doc.get("location"),
                    uri_union_of_None_type_or_strtype_False_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("location")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `location`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("location"))))
                        _errors__.append(
                            ValidationException(
                                "the `location` field is not valid because:",
                                SourceLine(_doc, "location", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `location` field is not valid because:",
                                SourceLine(_doc, "location", str),
                                [e],
                            )
                        )
        else:
            location = None
        if "path" in _doc:
            try:
                path = load_field(
                    _doc.get("path"),
                    uri_union_of_None_type_or_strtype_False_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("path")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `path`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("path"))))
                        _errors__.append(
                            ValidationException(
                                "the `path` field is not valid because:",
                                SourceLine(_doc, "path", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `path` field is not valid because:",
                                SourceLine(_doc, "path", str),
                                [e],
                            )
                        )
        else:
            path = None
        if "basename" in _doc:
            try:
                basename = load_field(
                    _doc.get("basename"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("basename")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `basename`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("basename"))))
                        _errors__.append(
                            ValidationException(
                                "the `basename` field is not valid because:",
                                SourceLine(_doc, "basename", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `basename` field is not valid because:",
                                SourceLine(_doc, "basename", str),
                                [e],
                            )
                        )
        else:
            basename = None
        if "dirname" in _doc:
            try:
                dirname = load_field(
                    _doc.get("dirname"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dirname")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dirname`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dirname"))))
                        _errors__.append(
                            ValidationException(
                                "the `dirname` field is not valid because:",
                                SourceLine(_doc, "dirname", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dirname` field is not valid because:",
                                SourceLine(_doc, "dirname", str),
                                [e],
                            )
                        )
        else:
            dirname = None
        if "nameroot" in _doc:
            try:
                nameroot = load_field(
                    _doc.get("nameroot"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("nameroot")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `nameroot`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("nameroot"))))
                        _errors__.append(
                            ValidationException(
                                "the `nameroot` field is not valid because:",
                                SourceLine(_doc, "nameroot", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `nameroot` field is not valid because:",
                                SourceLine(_doc, "nameroot", str),
                                [e],
                            )
                        )
        else:
            nameroot = None
        if "nameext" in _doc:
            try:
                nameext = load_field(
                    _doc.get("nameext"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("nameext")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `nameext`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("nameext"))))
                        _errors__.append(
                            ValidationException(
                                "the `nameext` field is not valid because:",
                                SourceLine(_doc, "nameext", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `nameext` field is not valid because:",
                                SourceLine(_doc, "nameext", str),
                                [e],
                            )
                        )
        else:
            nameext = None
        if "checksum" in _doc:
            try:
                checksum = load_field(
                    _doc.get("checksum"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("checksum")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `checksum`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("checksum"))))
                        _errors__.append(
                            ValidationException(
                                "the `checksum` field is not valid because:",
                                SourceLine(_doc, "checksum", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `checksum` field is not valid because:",
                                SourceLine(_doc, "checksum", str),
                                [e],
                            )
                        )
        else:
            checksum = None
        if "size" in _doc:
            try:
                size = load_field(
                    _doc.get("size"),
                    union_of_None_type_or_inttype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("size")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `size`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("size"))))
                        _errors__.append(
                            ValidationException(
                                "the `size` field is not valid because:",
                                SourceLine(_doc, "size", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `size` field is not valid because:",
                                SourceLine(_doc, "size", str),
                                [e],
                            )
                        )
        else:
            size = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "contents" in _doc:
            try:
                contents = load_field(
                    _doc.get("contents"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("contents")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `contents`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("contents"))))
                        _errors__.append(
                            ValidationException(
                                "the `contents` field is not valid because:",
                                SourceLine(_doc, "contents", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `contents` field is not valid because:",
                                SourceLine(_doc, "contents", str),
                                [e],
                            )
                        )
        else:
            contents = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `dirname`, `nameroot`, `nameext`, `checksum`, `size`, `secondaryFiles`, `format`, `contents`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            location=location,
            path=path,
            basename=basename,
            dirname=dirname,
            nameroot=nameroot,
            nameext=nameext,
            checksum=checksum,
            size=size,
            secondaryFiles=secondaryFiles,
            format=format,
            contents=contents,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "File"
        if self.location is not None:
            u = save_relative_uri(self.location, base_url, False, None, relative_uris)
            r["location"] = u
        if self.path is not None:
            u = save_relative_uri(self.path, base_url, False, None, relative_uris)
            r["path"] = u
        if self.basename is not None:
            r["basename"] = save(
                self.basename, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.dirname is not None:
            r["dirname"] = save(
                self.dirname, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.nameroot is not None:
            r["nameroot"] = save(
                self.nameroot, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.nameext is not None:
            r["nameext"] = save(
                self.nameext, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.checksum is not None:
            r["checksum"] = save(
                self.checksum, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.size is not None:
            r["size"] = save(
                self.size, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.format is not None:
            u = save_relative_uri(self.format, base_url, True, None, relative_uris)
            r["format"] = u
        if self.contents is not None:
            r["contents"] = save(
                self.contents, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "class",
            "location",
            "path",
            "basename",
            "dirname",
            "nameroot",
            "nameext",
            "checksum",
            "size",
            "secondaryFiles",
            "format",
            "contents",
        ]
    )


class Directory(Saveable):
    """
    Represents a directory to present to a command line tool.

    Directories are represented as objects with `class` of `Directory`.  Directory objects have
    a number of properties that provide metadata about the directory.

    The `location` property of a Directory is a URI that uniquely identifies
    the directory.  Implementations must support the file:// URI scheme and may
    support other schemes such as http://.  Alternately to `location`,
    implementations must also accept the `path` property on Directory, which
    must be a filesystem path available on the same host as the CWL runner (for
    inputs) or the runtime environment of a command line tool execution (for
    command line tool outputs).

    A Directory object may have a `listing` field.  This is a list of File and
    Directory objects that are contained in the Directory.  For each entry in
    `listing`, the `basename` property defines the name of the File or
    Subdirectory when staged to disk.  If `listing` is not provided, the
    implementation must have some way of fetching the Directory listing at
    runtime based on the `location` field.

    If a Directory does not have `location`, it is a Directory literal.  A
    Directory literal must provide `listing`.  Directory literals must be
    created on disk at runtime as needed.

    The resources in a Directory literal do not need to have any implied
    relationship in their `location`.  For example, a Directory listing may
    contain two files located on different hosts.  It is the responsibility of
    the runtime to ensure that those files are staged to disk appropriately.
    Secondary files associated with files in `listing` must also be staged to
    the same Directory.

    When executing a CommandLineTool, Directories must be recursively staged
    first and have local values of `path` assigend.

    Directory objects in CommandLineTool output must provide either a
    `location` URI or a `path` property in the context of the tool execution
    runtime (local to the compute node, or within the executing container).

    An ExpressionTool may forward file references from input to output by using
    the same value for `location`.

    Name conflicts (the same `basename` appearing multiple times in `listing`
    or in any entry in `secondaryFiles` in the listing) is a fatal error.

    """

    def __init__(
        self,
        location: Optional[Any] = None,
        path: Optional[Any] = None,
        basename: Optional[Any] = None,
        listing: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "Directory"
        self.location = location
        self.path = path
        self.basename = basename
        self.listing = listing

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, Directory):
            return bool(
                self.class_ == other.class_
                and self.location == other.location
                and self.path == other.path
                and self.basename == other.basename
                and self.listing == other.listing
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.class_, self.location, self.path, self.basename, self.listing)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "Directory":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "Directory":
            raise ValidationException("tried `Directory` but")

        if "location" in _doc:
            try:
                location = load_field(
                    _doc.get("location"),
                    uri_union_of_None_type_or_strtype_False_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("location")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `location`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("location"))))
                        _errors__.append(
                            ValidationException(
                                "the `location` field is not valid because:",
                                SourceLine(_doc, "location", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `location` field is not valid because:",
                                SourceLine(_doc, "location", str),
                                [e],
                            )
                        )
        else:
            location = None
        if "path" in _doc:
            try:
                path = load_field(
                    _doc.get("path"),
                    uri_union_of_None_type_or_strtype_False_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("path")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `path`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("path"))))
                        _errors__.append(
                            ValidationException(
                                "the `path` field is not valid because:",
                                SourceLine(_doc, "path", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `path` field is not valid because:",
                                SourceLine(_doc, "path", str),
                                [e],
                            )
                        )
        else:
            path = None
        if "basename" in _doc:
            try:
                basename = load_field(
                    _doc.get("basename"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("basename")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `basename`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("basename"))))
                        _errors__.append(
                            ValidationException(
                                "the `basename` field is not valid because:",
                                SourceLine(_doc, "basename", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `basename` field is not valid because:",
                                SourceLine(_doc, "basename", str),
                                [e],
                            )
                        )
        else:
            basename = None
        if "listing" in _doc:
            try:
                listing = load_field(
                    _doc.get("listing"),
                    union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("listing")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `listing`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("listing"))))
                        _errors__.append(
                            ValidationException(
                                "the `listing` field is not valid because:",
                                SourceLine(_doc, "listing", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `listing` field is not valid because:",
                                SourceLine(_doc, "listing", str),
                                [e],
                            )
                        )
        else:
            listing = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `listing`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            location=location,
            path=path,
            basename=basename,
            listing=listing,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "Directory"
        if self.location is not None:
            u = save_relative_uri(self.location, base_url, False, None, relative_uris)
            r["location"] = u
        if self.path is not None:
            u = save_relative_uri(self.path, base_url, False, None, relative_uris)
            r["path"] = u
        if self.basename is not None:
            r["basename"] = save(
                self.basename, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.listing is not None:
            r["listing"] = save(
                self.listing, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "location", "path", "basename", "listing"])


class SchemaBase(Saveable):
    pass


class Parameter(SchemaBase):
    """
    Define an input or output parameter to a process.

    """

    pass


class InputBinding(Saveable):
    pass


class OutputBinding(Saveable):
    pass


class InputSchema(SchemaBase):
    pass


class OutputSchema(SchemaBase):
    pass


class InputRecordField(CWLRecordField):
    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        label: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_
        self.inputBinding = inputBinding
        self.label = label

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InputRecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
                and self.inputBinding == other.inputBinding
                and self.label == other.label
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_, self.inputBinding, self.label))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InputRecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`, `inputBinding`, `label`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            inputBinding=inputBinding,
            label=label,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type", "inputBinding", "label"])


class InputRecordSchema(CWLRecordSchema, InputSchema):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        label: Optional[Any] = None,
        name: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_
        self.label = label
        self.name = name

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InputRecordSchema):
            return bool(
                self.fields == other.fields
                and self.type_ == other.type_
                and self.label == other.label
                and self.name == other.name
            )
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_, self.label, self.name))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InputRecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            label=label,
            name=name,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type", "label", "name"])


class InputEnumSchema(EnumSchema, InputSchema):
    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Optional[Any] = None,
        label: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name
        self.symbols = symbols
        self.type_ = type_
        self.label = label
        self.inputBinding = inputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InputEnumSchema):
            return bool(
                self.name == other.name
                and self.symbols == other.symbols
                and self.type_ == other.type_
                and self.label == other.label
                and self.inputBinding == other.inputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.name, self.symbols, self.type_, self.label, self.inputBinding)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InputEnumSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        try:
            if _doc.get("symbols") is None:
                raise ValidationException("missing required field `symbols`", None, [])

            symbols = load_field(
                _doc.get("symbols"),
                uri_array_of_strtype_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("symbols")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `symbols`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("symbols"))))
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Enum_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `inputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            symbols=symbols,
            type_=type_,
            label=label,
            inputBinding=inputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["name", "symbols", "type", "label", "inputBinding"])


class InputArraySchema(CWLArraySchema, InputSchema):
    def __init__(
        self,
        items: Any,
        type_: Any,
        label: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_
        self.label = label
        self.inputBinding = inputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InputArraySchema):
            return bool(
                self.items == other.items
                and self.type_ == other.type_
                and self.label == other.label
                and self.inputBinding == other.inputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_, self.label, self.inputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InputArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`, `label`, `inputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            label=label,
            inputBinding=inputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type", "label", "inputBinding"])


class OutputRecordField(CWLRecordField):
    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, OutputRecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_, self.outputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "OutputRecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type", "outputBinding"])


class OutputRecordSchema(CWLRecordSchema, OutputSchema):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        label: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_
        self.label = label

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, OutputRecordSchema):
            return bool(
                self.fields == other.fields
                and self.type_ == other.type_
                and self.label == other.label
            )
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_, self.label))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "OutputRecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`, `label`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            label=label,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type", "label"])


class OutputEnumSchema(EnumSchema, OutputSchema):
    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Optional[Any] = None,
        label: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name
        self.symbols = symbols
        self.type_ = type_
        self.label = label
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, OutputEnumSchema):
            return bool(
                self.name == other.name
                and self.symbols == other.symbols
                and self.type_ == other.type_
                and self.label == other.label
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.name, self.symbols, self.type_, self.label, self.outputBinding)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "OutputEnumSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        try:
            if _doc.get("symbols") is None:
                raise ValidationException("missing required field `symbols`", None, [])

            symbols = load_field(
                _doc.get("symbols"),
                uri_array_of_strtype_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("symbols")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `symbols`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("symbols"))))
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Enum_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            symbols=symbols,
            type_=type_,
            label=label,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["name", "symbols", "type", "label", "outputBinding"])


class OutputArraySchema(CWLArraySchema, OutputSchema):
    def __init__(
        self,
        items: Any,
        type_: Any,
        label: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_
        self.label = label
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, OutputArraySchema):
            return bool(
                self.items == other.items
                and self.type_ == other.type_
                and self.label == other.label
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_, self.label, self.outputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "OutputArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`, `label`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            label=label,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type", "label", "outputBinding"])


class InputParameter(Parameter):
    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        format: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        default: Optional[Any] = None,
        type_: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.format = format
        self.inputBinding = inputBinding
        self.default = default
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.format == other.format
                and self.inputBinding == other.inputBinding
                and self.default == other.default
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.format,
                self.inputBinding,
                self.default,
                self.type_,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        if "default" in _doc:
            try:
                default = load_field(
                    _doc.get("default"),
                    union_of_None_type_or_CWLObjectTypeLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("default")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `default`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("default"))))
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [e],
                            )
                        )
        else:
            default = None
        if "type" in _doc:
            try:
                type_ = load_field(
                    _doc.get("type"),
                    typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("type")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `type`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("type"))))
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [e],
                            )
                        )
        else:
            type_ = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            format=format,
            inputBinding=inputBinding,
            default=default,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.default is not None:
            r["default"] = save(
                self.default, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "format",
            "inputBinding",
            "default",
            "type",
        ]
    )


class OutputParameter(Parameter):
    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        format: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.outputBinding = outputBinding
        self.format = format

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, OutputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.outputBinding == other.outputBinding
                and self.format == other.format
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.outputBinding,
                self.format,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "OutputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            outputBinding=outputBinding,
            format=format,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "outputBinding",
            "format",
        ]
    )


class ProcessRequirement(Saveable):
    """
    A process requirement declares a prerequisite that may or must be fulfilled
    before executing a process.  See [`Process.hints`](#process) and
    [`Process.requirements`](#process).

    Process requirements are the primary mechanism for specifying extensions to
    the CWL core specification.

    """

    pass


class Process(Saveable):
    """

    The base executable type in CWL is the `Process` object defined by the
    document.  Note that the `Process` object is abstract and cannot be
    directly executed.

    """

    pass


class InlineJavascriptRequirement(ProcessRequirement):
    """
    Indicates that the workflow platform must support inline Javascript expressions.
    If this requirement is not present, the workflow platform must not perform expression
    interpolatation.

    """

    def __init__(
        self,
        expressionLib: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "InlineJavascriptRequirement"
        self.expressionLib = expressionLib

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InlineJavascriptRequirement):
            return bool(
                self.class_ == other.class_
                and self.expressionLib == other.expressionLib
            )
        return False

    def __hash__(self) -> int:
        return hash((self.class_, self.expressionLib))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InlineJavascriptRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "InlineJavascriptRequirement":
            raise ValidationException("tried `InlineJavascriptRequirement` but")

        if "expressionLib" in _doc:
            try:
                expressionLib = load_field(
                    _doc.get("expressionLib"),
                    union_of_None_type_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("expressionLib")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `expressionLib`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("expressionLib"))))
                        _errors__.append(
                            ValidationException(
                                "the `expressionLib` field is not valid because:",
                                SourceLine(_doc, "expressionLib", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `expressionLib` field is not valid because:",
                                SourceLine(_doc, "expressionLib", str),
                                [e],
                            )
                        )
        else:
            expressionLib = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `expressionLib`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            expressionLib=expressionLib,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "InlineJavascriptRequirement"
        if self.expressionLib is not None:
            r["expressionLib"] = save(
                self.expressionLib,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "expressionLib"])


class SchemaDefRequirement(ProcessRequirement):
    """
    This field consists of an array of type definitions which must be used when
    interpreting the `inputs` and `outputs` fields.  When a `type` field
    contain a IRI, the implementation must check if the type is defined in
    `schemaDefs` and use that definition.  If the type is not found in
    `schemaDefs`, it is an error.  The entries in `schemaDefs` must be
    processed in the order listed such that later schema definitions may refer
    to earlier schema definitions.

    """

    def __init__(
        self,
        types: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SchemaDefRequirement"
        self.types = types

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SchemaDefRequirement):
            return bool(self.class_ == other.class_ and self.types == other.types)
        return False

    def __hash__(self) -> int:
        return hash((self.class_, self.types))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "SchemaDefRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "SchemaDefRequirement":
            raise ValidationException("tried `SchemaDefRequirement` but")

        try:
            if _doc.get("types") is None:
                raise ValidationException("missing required field `types`", None, [])

            types = load_field(
                _doc.get("types"),
                array_of_union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("types")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `types`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("types"))))
                    _errors__.append(
                        ValidationException(
                            "the `types` field is not valid because:",
                            SourceLine(_doc, "types", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `types` field is not valid because:",
                            SourceLine(_doc, "types", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `types`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            types=types,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "SchemaDefRequirement"
        if self.types is not None:
            r["types"] = save(
                self.types, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "types"])


class EnvironmentDef(Saveable):
    """
    Define an environment variable that will be set in the runtime environment
    by the workflow platform when executing the command line tool.  May be the
    result of executing an expression, such as getting a parameter from input.

    """

    def __init__(
        self,
        envName: Any,
        envValue: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.envName = envName
        self.envValue = envValue

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, EnvironmentDef):
            return bool(
                self.envName == other.envName and self.envValue == other.envValue
            )
        return False

    def __hash__(self) -> int:
        return hash((self.envName, self.envValue))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "EnvironmentDef":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("envName") is None:
                raise ValidationException("missing required field `envName`", None, [])

            envName = load_field(
                _doc.get("envName"),
                strtype,
                baseuri,
                loadingOptions,
                lc=_doc.get("envName")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `envName`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("envName"))))
                    _errors__.append(
                        ValidationException(
                            "the `envName` field is not valid because:",
                            SourceLine(_doc, "envName", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `envName` field is not valid because:",
                            SourceLine(_doc, "envName", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("envValue") is None:
                raise ValidationException("missing required field `envValue`", None, [])

            envValue = load_field(
                _doc.get("envValue"),
                union_of_strtype_or_ExpressionLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("envValue")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `envValue`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("envValue"))))
                    _errors__.append(
                        ValidationException(
                            "the `envValue` field is not valid because:",
                            SourceLine(_doc, "envValue", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `envValue` field is not valid because:",
                            SourceLine(_doc, "envValue", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `envName`, `envValue`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            envName=envName,
            envValue=envValue,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.envName is not None:
            r["envName"] = save(
                self.envName, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.envValue is not None:
            r["envValue"] = save(
                self.envValue, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["envName", "envValue"])


class CommandLineBinding(InputBinding):
    """

    When listed under `inputBinding` in the input schema, the term
    "value" refers to the the corresponding value in the input object.  For
    binding objects listed in `CommandLineTool.arguments`, the term "value"
    refers to the effective value after evaluating `valueFrom`.

    The binding behavior when building the command line depends on the data
    type of the value.  If there is a mismatch between the type described by
    the input schema and the effective value, such as resulting from an
    expression evaluation, an implementation must use the data type of the
    effective value.

      - **string**: Add `prefix` and the string to the command line.

      - **number**: Add `prefix` and decimal representation to command line.

      - **boolean**: If true, add `prefix` to the command line.  If false, add
          nothing.

      - **File**: Add `prefix` and the value of
        [`File.path`](#File) to the command line.

      - **Directory**: Add `prefix` and the value of
        [`Directory.path`](#Directory) to the command line.

      - **array**: If `itemSeparator` is specified, add `prefix` and the join
          the array into a single string with `itemSeparator` separating the
          items.  Otherwise first add `prefix`, then recursively process
          individual elements.
          If the array is empty, it does not add anything to command line.

      - **object**: Add `prefix` only, and recursively add object fields for
          which `inputBinding` is specified.

      - **null**: Add nothing.

    """

    def __init__(
        self,
        loadContents: Optional[Any] = None,
        position: Optional[Any] = None,
        prefix: Optional[Any] = None,
        separate: Optional[Any] = None,
        itemSeparator: Optional[Any] = None,
        valueFrom: Optional[Any] = None,
        shellQuote: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.loadContents = loadContents
        self.position = position
        self.prefix = prefix
        self.separate = separate
        self.itemSeparator = itemSeparator
        self.valueFrom = valueFrom
        self.shellQuote = shellQuote

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandLineBinding):
            return bool(
                self.loadContents == other.loadContents
                and self.position == other.position
                and self.prefix == other.prefix
                and self.separate == other.separate
                and self.itemSeparator == other.itemSeparator
                and self.valueFrom == other.valueFrom
                and self.shellQuote == other.shellQuote
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.loadContents,
                self.position,
                self.prefix,
                self.separate,
                self.itemSeparator,
                self.valueFrom,
                self.shellQuote,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandLineBinding":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "loadContents" in _doc:
            try:
                loadContents = load_field(
                    _doc.get("loadContents"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("loadContents")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `loadContents`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("loadContents"))))
                        _errors__.append(
                            ValidationException(
                                "the `loadContents` field is not valid because:",
                                SourceLine(_doc, "loadContents", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `loadContents` field is not valid because:",
                                SourceLine(_doc, "loadContents", str),
                                [e],
                            )
                        )
        else:
            loadContents = None
        if "position" in _doc:
            try:
                position = load_field(
                    _doc.get("position"),
                    union_of_None_type_or_inttype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("position")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `position`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("position"))))
                        _errors__.append(
                            ValidationException(
                                "the `position` field is not valid because:",
                                SourceLine(_doc, "position", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `position` field is not valid because:",
                                SourceLine(_doc, "position", str),
                                [e],
                            )
                        )
        else:
            position = None
        if "prefix" in _doc:
            try:
                prefix = load_field(
                    _doc.get("prefix"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("prefix")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `prefix`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("prefix"))))
                        _errors__.append(
                            ValidationException(
                                "the `prefix` field is not valid because:",
                                SourceLine(_doc, "prefix", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `prefix` field is not valid because:",
                                SourceLine(_doc, "prefix", str),
                                [e],
                            )
                        )
        else:
            prefix = None
        if "separate" in _doc:
            try:
                separate = load_field(
                    _doc.get("separate"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("separate")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `separate`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("separate"))))
                        _errors__.append(
                            ValidationException(
                                "the `separate` field is not valid because:",
                                SourceLine(_doc, "separate", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `separate` field is not valid because:",
                                SourceLine(_doc, "separate", str),
                                [e],
                            )
                        )
        else:
            separate = None
        if "itemSeparator" in _doc:
            try:
                itemSeparator = load_field(
                    _doc.get("itemSeparator"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("itemSeparator")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `itemSeparator`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("itemSeparator"))))
                        _errors__.append(
                            ValidationException(
                                "the `itemSeparator` field is not valid because:",
                                SourceLine(_doc, "itemSeparator", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `itemSeparator` field is not valid because:",
                                SourceLine(_doc, "itemSeparator", str),
                                [e],
                            )
                        )
        else:
            itemSeparator = None
        if "valueFrom" in _doc:
            try:
                valueFrom = load_field(
                    _doc.get("valueFrom"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("valueFrom")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `valueFrom`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("valueFrom"))))
                        _errors__.append(
                            ValidationException(
                                "the `valueFrom` field is not valid because:",
                                SourceLine(_doc, "valueFrom", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `valueFrom` field is not valid because:",
                                SourceLine(_doc, "valueFrom", str),
                                [e],
                            )
                        )
        else:
            valueFrom = None
        if "shellQuote" in _doc:
            try:
                shellQuote = load_field(
                    _doc.get("shellQuote"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("shellQuote")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `shellQuote`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("shellQuote"))))
                        _errors__.append(
                            ValidationException(
                                "the `shellQuote` field is not valid because:",
                                SourceLine(_doc, "shellQuote", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `shellQuote` field is not valid because:",
                                SourceLine(_doc, "shellQuote", str),
                                [e],
                            )
                        )
        else:
            shellQuote = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `loadContents`, `position`, `prefix`, `separate`, `itemSeparator`, `valueFrom`, `shellQuote`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            loadContents=loadContents,
            position=position,
            prefix=prefix,
            separate=separate,
            itemSeparator=itemSeparator,
            valueFrom=valueFrom,
            shellQuote=shellQuote,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.loadContents is not None:
            r["loadContents"] = save(
                self.loadContents,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.position is not None:
            r["position"] = save(
                self.position, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.prefix is not None:
            r["prefix"] = save(
                self.prefix, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.separate is not None:
            r["separate"] = save(
                self.separate, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.itemSeparator is not None:
            r["itemSeparator"] = save(
                self.itemSeparator,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.valueFrom is not None:
            r["valueFrom"] = save(
                self.valueFrom,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.shellQuote is not None:
            r["shellQuote"] = save(
                self.shellQuote,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "loadContents",
            "position",
            "prefix",
            "separate",
            "itemSeparator",
            "valueFrom",
            "shellQuote",
        ]
    )


class CommandOutputBinding(OutputBinding):
    """
    Describes how to generate an output parameter based on the files produced
    by a CommandLineTool.

    The output parameter value is generated by applying these operations in the
    following order:

      - glob
      - loadContents
      - outputEval
      - secondaryFiles

    """

    def __init__(
        self,
        glob: Optional[Any] = None,
        loadContents: Optional[Any] = None,
        outputEval: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.glob = glob
        self.loadContents = loadContents
        self.outputEval = outputEval

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputBinding):
            return bool(
                self.glob == other.glob
                and self.loadContents == other.loadContents
                and self.outputEval == other.outputEval
            )
        return False

    def __hash__(self) -> int:
        return hash((self.glob, self.loadContents, self.outputEval))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputBinding":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "glob" in _doc:
            try:
                glob = load_field(
                    _doc.get("glob"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("glob")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `glob`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("glob"))))
                        _errors__.append(
                            ValidationException(
                                "the `glob` field is not valid because:",
                                SourceLine(_doc, "glob", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `glob` field is not valid because:",
                                SourceLine(_doc, "glob", str),
                                [e],
                            )
                        )
        else:
            glob = None
        if "loadContents" in _doc:
            try:
                loadContents = load_field(
                    _doc.get("loadContents"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("loadContents")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `loadContents`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("loadContents"))))
                        _errors__.append(
                            ValidationException(
                                "the `loadContents` field is not valid because:",
                                SourceLine(_doc, "loadContents", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `loadContents` field is not valid because:",
                                SourceLine(_doc, "loadContents", str),
                                [e],
                            )
                        )
        else:
            loadContents = None
        if "outputEval" in _doc:
            try:
                outputEval = load_field(
                    _doc.get("outputEval"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputEval")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputEval`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputEval"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputEval` field is not valid because:",
                                SourceLine(_doc, "outputEval", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputEval` field is not valid because:",
                                SourceLine(_doc, "outputEval", str),
                                [e],
                            )
                        )
        else:
            outputEval = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `glob`, `loadContents`, `outputEval`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            glob=glob,
            loadContents=loadContents,
            outputEval=outputEval,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.glob is not None:
            r["glob"] = save(
                self.glob, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.loadContents is not None:
            r["loadContents"] = save(
                self.loadContents,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.outputEval is not None:
            r["outputEval"] = save(
                self.outputEval,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["glob", "loadContents", "outputEval"])


class CommandInputRecordField(InputRecordField):
    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        label: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_
        self.inputBinding = inputBinding
        self.label = label

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandInputRecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
                and self.inputBinding == other.inputBinding
                and self.label == other.label
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_, self.inputBinding, self.label))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandInputRecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`, `inputBinding`, `label`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            inputBinding=inputBinding,
            label=label,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type", "inputBinding", "label"])


class CommandInputRecordSchema(InputRecordSchema):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        label: Optional[Any] = None,
        name: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_
        self.label = label
        self.name = name

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandInputRecordSchema):
            return bool(
                self.fields == other.fields
                and self.type_ == other.type_
                and self.label == other.label
                and self.name == other.name
            )
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_, self.label, self.name))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandInputRecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            label=label,
            name=name,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type", "label", "name"])


class CommandInputEnumSchema(InputEnumSchema):
    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Optional[Any] = None,
        label: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name
        self.symbols = symbols
        self.type_ = type_
        self.label = label
        self.inputBinding = inputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandInputEnumSchema):
            return bool(
                self.name == other.name
                and self.symbols == other.symbols
                and self.type_ == other.type_
                and self.label == other.label
                and self.inputBinding == other.inputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.name, self.symbols, self.type_, self.label, self.inputBinding)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandInputEnumSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        try:
            if _doc.get("symbols") is None:
                raise ValidationException("missing required field `symbols`", None, [])

            symbols = load_field(
                _doc.get("symbols"),
                uri_array_of_strtype_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("symbols")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `symbols`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("symbols"))))
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Enum_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `inputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            symbols=symbols,
            type_=type_,
            label=label,
            inputBinding=inputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["name", "symbols", "type", "label", "inputBinding"])


class CommandInputArraySchema(InputArraySchema):
    def __init__(
        self,
        items: Any,
        type_: Any,
        label: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_
        self.label = label
        self.inputBinding = inputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandInputArraySchema):
            return bool(
                self.items == other.items
                and self.type_ == other.type_
                and self.label == other.label
                and self.inputBinding == other.inputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_, self.label, self.inputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandInputArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`, `label`, `inputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            label=label,
            inputBinding=inputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type", "label", "inputBinding"])


class CommandOutputRecordField(OutputRecordField):
    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type_ = type_
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputRecordField):
            return bool(
                self.doc == other.doc
                and self.name == other.name
                and self.type_ == other.type_
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.doc, self.name, self.type_, self.outputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputRecordField":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                _errors__.append(ValidationException("missing name"))
        if not __original_name_is_none:
            baseuri = name
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `doc`, `name`, `type`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            doc=doc,
            name=name,
            type_=type_,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["doc", "name", "type", "outputBinding"])


class CommandOutputRecordSchema(OutputRecordSchema):
    def __init__(
        self,
        type_: Any,
        fields: Optional[Any] = None,
        label: Optional[Any] = None,
        name: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type_ = type_
        self.label = label
        self.name = name

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputRecordSchema):
            return bool(
                self.fields == other.fields
                and self.type_ == other.type_
                and self.label == other.label
                and self.name == other.name
            )
        return False

    def __hash__(self) -> int:
        return hash((self.fields, self.type_, self.label, self.name))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputRecordSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        if "fields" in _doc:
            try:
                fields = load_field(
                    _doc.get("fields"),
                    idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("fields")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `fields`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("fields"))))
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `fields` field is not valid because:",
                                SourceLine(_doc, "fields", str),
                                [e],
                            )
                        )
        else:
            fields = None
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Record_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            fields=fields,
            type_=type_,
            label=label,
            name=name,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.fields is not None:
            r["fields"] = save(
                self.fields, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["fields", "type", "label", "name"])


class CommandOutputEnumSchema(OutputEnumSchema):
    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Optional[Any] = None,
        label: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name
        self.symbols = symbols
        self.type_ = type_
        self.label = label
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputEnumSchema):
            return bool(
                self.name == other.name
                and self.symbols == other.symbols
                and self.type_ == other.type_
                and self.label == other.label
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.name, self.symbols, self.type_, self.label, self.outputBinding)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputEnumSchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "name" in _doc:
            try:
                name = load_field(
                    _doc.get("name"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("name")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `name`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("name"))))
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `name` field is not valid because:",
                                SourceLine(_doc, "name", str),
                                [e],
                            )
                        )
        else:
            name = None

        __original_name_is_none = name is None
        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        if not __original_name_is_none:
            baseuri = name
        try:
            if _doc.get("symbols") is None:
                raise ValidationException("missing required field `symbols`", None, [])

            symbols = load_field(
                _doc.get("symbols"),
                uri_array_of_strtype_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("symbols")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `symbols`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("symbols"))))
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `symbols` field is not valid because:",
                            SourceLine(_doc, "symbols", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Enum_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            symbols=symbols,
            type_=type_,
            label=label,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[name] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["name", "symbols", "type", "label", "outputBinding"])


class CommandOutputArraySchema(OutputArraySchema):
    def __init__(
        self,
        items: Any,
        type_: Any,
        label: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type_ = type_
        self.label = label
        self.outputBinding = outputBinding

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputArraySchema):
            return bool(
                self.items == other.items
                and self.type_ == other.type_
                and self.label == other.label
                and self.outputBinding == other.outputBinding
            )
        return False

    def __hash__(self) -> int:
        return hash((self.items, self.type_, self.label, self.outputBinding))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputArraySchema":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("items") is None:
                raise ValidationException("missing required field `items`", None, [])

            items = load_field(
                _doc.get("items"),
                uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("items")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `items`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("items"))))
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `items` field is not valid because:",
                            SourceLine(_doc, "items", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("type") is None:
                raise ValidationException("missing required field `type`", None, [])

            type_ = load_field(
                _doc.get("type"),
                typedsl_Array_nameLoader_2,
                baseuri,
                loadingOptions,
                lc=_doc.get("type")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `type`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("type"))))
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `type` field is not valid because:",
                            SourceLine(_doc, "type", str),
                            [e],
                        )
                    )
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `items`, `type`, `label`, `outputBinding`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            items=items,
            type_=type_,
            label=label,
            outputBinding=outputBinding,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.items is not None:
            u = save_relative_uri(self.items, base_url, False, 2, relative_uris)
            r["items"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["items", "type", "label", "outputBinding"])


class CommandInputParameter(InputParameter):
    """
    An input parameter for a CommandLineTool.
    """

    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        format: Optional[Any] = None,
        inputBinding: Optional[Any] = None,
        default: Optional[Any] = None,
        type_: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.format = format
        self.inputBinding = inputBinding
        self.default = default
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandInputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.format == other.format
                and self.inputBinding == other.inputBinding
                and self.default == other.default
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.format,
                self.inputBinding,
                self.default,
                self.type_,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandInputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "inputBinding" in _doc:
            try:
                inputBinding = load_field(
                    _doc.get("inputBinding"),
                    union_of_None_type_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("inputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `inputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("inputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `inputBinding` field is not valid because:",
                                SourceLine(_doc, "inputBinding", str),
                                [e],
                            )
                        )
        else:
            inputBinding = None
        if "default" in _doc:
            try:
                default = load_field(
                    _doc.get("default"),
                    union_of_None_type_or_CWLObjectTypeLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("default")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `default`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("default"))))
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [e],
                            )
                        )
        else:
            default = None
        if "type" in _doc:
            try:
                type_ = load_field(
                    _doc.get("type"),
                    typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("type")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `type`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("type"))))
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [e],
                            )
                        )
        else:
            type_ = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            format=format,
            inputBinding=inputBinding,
            default=default,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u
        if self.inputBinding is not None:
            r["inputBinding"] = save(
                self.inputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.default is not None:
            r["default"] = save(
                self.default, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "format",
            "inputBinding",
            "default",
            "type",
        ]
    )


class CommandOutputParameter(OutputParameter):
    """
    An output parameter for a CommandLineTool.
    """

    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        format: Optional[Any] = None,
        type_: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.outputBinding = outputBinding
        self.format = format
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandOutputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.outputBinding == other.outputBinding
                and self.format == other.format
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.outputBinding,
                self.format,
                self.type_,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandOutputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "type" in _doc:
            try:
                type_ = load_field(
                    _doc.get("type"),
                    typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("type")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `type`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("type"))))
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [e],
                            )
                        )
        else:
            type_ = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            outputBinding=outputBinding,
            format=format,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "outputBinding",
            "format",
            "type",
        ]
    )


class CommandLineTool(Process):
    """
    This defines the schema of the CWL Command Line Tool Description document.

    """

    def __init__(
        self,
        inputs: Any,
        outputs: Any,
        id: Optional[Any] = None,
        requirements: Optional[Any] = None,
        hints: Optional[Any] = None,
        label: Optional[Any] = None,
        doc: Optional[Any] = None,
        cwlVersion: Optional[Any] = None,
        baseCommand: Optional[Any] = None,
        arguments: Optional[Any] = None,
        stdin: Optional[Any] = None,
        stderr: Optional[Any] = None,
        stdout: Optional[Any] = None,
        successCodes: Optional[Any] = None,
        temporaryFailCodes: Optional[Any] = None,
        permanentFailCodes: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.label = label
        self.doc = doc
        self.cwlVersion = cwlVersion
        self.class_ = "CommandLineTool"
        self.baseCommand = baseCommand
        self.arguments = arguments
        self.stdin = stdin
        self.stderr = stderr
        self.stdout = stdout
        self.successCodes = successCodes
        self.temporaryFailCodes = temporaryFailCodes
        self.permanentFailCodes = permanentFailCodes

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, CommandLineTool):
            return bool(
                self.id == other.id
                and self.inputs == other.inputs
                and self.outputs == other.outputs
                and self.requirements == other.requirements
                and self.hints == other.hints
                and self.label == other.label
                and self.doc == other.doc
                and self.cwlVersion == other.cwlVersion
                and self.class_ == other.class_
                and self.baseCommand == other.baseCommand
                and self.arguments == other.arguments
                and self.stdin == other.stdin
                and self.stderr == other.stderr
                and self.stdout == other.stdout
                and self.successCodes == other.successCodes
                and self.temporaryFailCodes == other.temporaryFailCodes
                and self.permanentFailCodes == other.permanentFailCodes
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.id,
                self.inputs,
                self.outputs,
                self.requirements,
                self.hints,
                self.label,
                self.doc,
                self.cwlVersion,
                self.class_,
                self.baseCommand,
                self.arguments,
                self.stdin,
                self.stderr,
                self.stdout,
                self.successCodes,
                self.temporaryFailCodes,
                self.permanentFailCodes,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "CommandLineTool":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "CommandLineTool":
            raise ValidationException("tried `CommandLineTool` but")

        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        if not __original_id_is_none:
            baseuri = id
        try:
            if _doc.get("inputs") is None:
                raise ValidationException("missing required field `inputs`", None, [])

            inputs = load_field(
                _doc.get("inputs"),
                idmap_inputs_array_of_CommandInputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("inputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `inputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("inputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("outputs") is None:
                raise ValidationException("missing required field `outputs`", None, [])

            outputs = load_field(
                _doc.get("outputs"),
                idmap_outputs_array_of_CommandOutputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("outputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `outputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("outputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [e],
                        )
                    )
        if "requirements" in _doc:
            try:
                requirements = load_field(
                    _doc.get("requirements"),
                    idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("requirements")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `requirements`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("requirements"))))
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [e],
                            )
                        )
        else:
            requirements = None
        if "hints" in _doc:
            try:
                hints = load_field(
                    _doc.get("hints"),
                    idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("hints")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `hints`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("hints"))))
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [e],
                            )
                        )
        else:
            hints = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "cwlVersion" in _doc:
            try:
                cwlVersion = load_field(
                    _doc.get("cwlVersion"),
                    uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("cwlVersion")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `cwlVersion`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("cwlVersion"))))
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [e],
                            )
                        )
        else:
            cwlVersion = None
        if "baseCommand" in _doc:
            try:
                baseCommand = load_field(
                    _doc.get("baseCommand"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("baseCommand")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `baseCommand`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("baseCommand"))))
                        _errors__.append(
                            ValidationException(
                                "the `baseCommand` field is not valid because:",
                                SourceLine(_doc, "baseCommand", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `baseCommand` field is not valid because:",
                                SourceLine(_doc, "baseCommand", str),
                                [e],
                            )
                        )
        else:
            baseCommand = None
        if "arguments" in _doc:
            try:
                arguments = load_field(
                    _doc.get("arguments"),
                    union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("arguments")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `arguments`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("arguments"))))
                        _errors__.append(
                            ValidationException(
                                "the `arguments` field is not valid because:",
                                SourceLine(_doc, "arguments", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `arguments` field is not valid because:",
                                SourceLine(_doc, "arguments", str),
                                [e],
                            )
                        )
        else:
            arguments = None
        if "stdin" in _doc:
            try:
                stdin = load_field(
                    _doc.get("stdin"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("stdin")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `stdin`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("stdin"))))
                        _errors__.append(
                            ValidationException(
                                "the `stdin` field is not valid because:",
                                SourceLine(_doc, "stdin", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `stdin` field is not valid because:",
                                SourceLine(_doc, "stdin", str),
                                [e],
                            )
                        )
        else:
            stdin = None
        if "stderr" in _doc:
            try:
                stderr = load_field(
                    _doc.get("stderr"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("stderr")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `stderr`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("stderr"))))
                        _errors__.append(
                            ValidationException(
                                "the `stderr` field is not valid because:",
                                SourceLine(_doc, "stderr", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `stderr` field is not valid because:",
                                SourceLine(_doc, "stderr", str),
                                [e],
                            )
                        )
        else:
            stderr = None
        if "stdout" in _doc:
            try:
                stdout = load_field(
                    _doc.get("stdout"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("stdout")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `stdout`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("stdout"))))
                        _errors__.append(
                            ValidationException(
                                "the `stdout` field is not valid because:",
                                SourceLine(_doc, "stdout", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `stdout` field is not valid because:",
                                SourceLine(_doc, "stdout", str),
                                [e],
                            )
                        )
        else:
            stdout = None
        if "successCodes" in _doc:
            try:
                successCodes = load_field(
                    _doc.get("successCodes"),
                    union_of_None_type_or_array_of_inttype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("successCodes")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `successCodes`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("successCodes"))))
                        _errors__.append(
                            ValidationException(
                                "the `successCodes` field is not valid because:",
                                SourceLine(_doc, "successCodes", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `successCodes` field is not valid because:",
                                SourceLine(_doc, "successCodes", str),
                                [e],
                            )
                        )
        else:
            successCodes = None
        if "temporaryFailCodes" in _doc:
            try:
                temporaryFailCodes = load_field(
                    _doc.get("temporaryFailCodes"),
                    union_of_None_type_or_array_of_inttype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("temporaryFailCodes")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `temporaryFailCodes`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("temporaryFailCodes"))))
                        _errors__.append(
                            ValidationException(
                                "the `temporaryFailCodes` field is not valid because:",
                                SourceLine(_doc, "temporaryFailCodes", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `temporaryFailCodes` field is not valid because:",
                                SourceLine(_doc, "temporaryFailCodes", str),
                                [e],
                            )
                        )
        else:
            temporaryFailCodes = None
        if "permanentFailCodes" in _doc:
            try:
                permanentFailCodes = load_field(
                    _doc.get("permanentFailCodes"),
                    union_of_None_type_or_array_of_inttype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("permanentFailCodes")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `permanentFailCodes`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("permanentFailCodes"))))
                        _errors__.append(
                            ValidationException(
                                "the `permanentFailCodes` field is not valid because:",
                                SourceLine(_doc, "permanentFailCodes", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `permanentFailCodes` field is not valid because:",
                                SourceLine(_doc, "permanentFailCodes", str),
                                [e],
                            )
                        )
        else:
            permanentFailCodes = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            id=id,
            inputs=inputs,
            outputs=outputs,
            requirements=requirements,
            hints=hints,
            label=label,
            doc=doc,
            cwlVersion=cwlVersion,
            baseCommand=baseCommand,
            arguments=arguments,
            stdin=stdin,
            stderr=stderr,
            stdout=stdout,
            successCodes=successCodes,
            temporaryFailCodes=temporaryFailCodes,
            permanentFailCodes=permanentFailCodes,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "CommandLineTool"
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.inputs is not None:
            r["inputs"] = save(
                self.inputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputs is not None:
            r["outputs"] = save(
                self.outputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.requirements is not None:
            r["requirements"] = save(
                self.requirements,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.hints is not None:
            r["hints"] = save(
                self.hints, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.cwlVersion is not None:
            u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris)
            r["cwlVersion"] = u
        if self.baseCommand is not None:
            r["baseCommand"] = save(
                self.baseCommand,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.arguments is not None:
            r["arguments"] = save(
                self.arguments, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.stdin is not None:
            r["stdin"] = save(
                self.stdin, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.stderr is not None:
            r["stderr"] = save(
                self.stderr, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.stdout is not None:
            r["stdout"] = save(
                self.stdout, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.successCodes is not None:
            r["successCodes"] = save(
                self.successCodes,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.temporaryFailCodes is not None:
            r["temporaryFailCodes"] = save(
                self.temporaryFailCodes,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.permanentFailCodes is not None:
            r["permanentFailCodes"] = save(
                self.permanentFailCodes,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "id",
            "inputs",
            "outputs",
            "requirements",
            "hints",
            "label",
            "doc",
            "cwlVersion",
            "class",
            "baseCommand",
            "arguments",
            "stdin",
            "stderr",
            "stdout",
            "successCodes",
            "temporaryFailCodes",
            "permanentFailCodes",
        ]
    )


class DockerRequirement(ProcessRequirement):
    """
    Indicates that a workflow component should be run in a
    [Docker](http://docker.com) container, and specifies how to fetch or build
    the image.

    If a CommandLineTool lists `DockerRequirement` under
    `hints` (or `requirements`), it may (or must) be run in the specified Docker
    container.

    The platform must first acquire or install the correct Docker image as
    specified by `dockerPull`, `dockerImport`, `dockerLoad` or `dockerFile`.

    The platform must execute the tool in the container using `docker run` with
    the appropriate Docker image and tool command line.

    The workflow platform may provide input files and the designated output
    directory through the use of volume bind mounts.  The platform should rewrite
    file paths in the input object to correspond to the Docker bind mounted
    locations. That is, the platform should rewrite values in the parameter context
    such as `runtime.outdir`, `runtime.tmpdir` and others to be valid paths
    within the container.

    When running a tool contained in Docker, the workflow platform must not
    assume anything about the contents of the Docker container, such as the
    presence or absence of specific software, except to assume that the
    generated command line represents a valid command within the runtime
    environment of the container.

    ## Interaction with other requirements

    If [EnvVarRequirement](#EnvVarRequirement) is specified alongside a
    DockerRequirement, the environment variables must be provided to Docker
    using `--env` or `--env-file` and interact with the container's preexisting
    environment as defined by Docker.

    """

    def __init__(
        self,
        dockerPull: Optional[Any] = None,
        dockerLoad: Optional[Any] = None,
        dockerFile: Optional[Any] = None,
        dockerImport: Optional[Any] = None,
        dockerImageId: Optional[Any] = None,
        dockerOutputDirectory: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "DockerRequirement"
        self.dockerPull = dockerPull
        self.dockerLoad = dockerLoad
        self.dockerFile = dockerFile
        self.dockerImport = dockerImport
        self.dockerImageId = dockerImageId
        self.dockerOutputDirectory = dockerOutputDirectory

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, DockerRequirement):
            return bool(
                self.class_ == other.class_
                and self.dockerPull == other.dockerPull
                and self.dockerLoad == other.dockerLoad
                and self.dockerFile == other.dockerFile
                and self.dockerImport == other.dockerImport
                and self.dockerImageId == other.dockerImageId
                and self.dockerOutputDirectory == other.dockerOutputDirectory
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.class_,
                self.dockerPull,
                self.dockerLoad,
                self.dockerFile,
                self.dockerImport,
                self.dockerImageId,
                self.dockerOutputDirectory,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "DockerRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "DockerRequirement":
            raise ValidationException("tried `DockerRequirement` but")

        if "dockerPull" in _doc:
            try:
                dockerPull = load_field(
                    _doc.get("dockerPull"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerPull")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerPull`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerPull"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerPull` field is not valid because:",
                                SourceLine(_doc, "dockerPull", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerPull` field is not valid because:",
                                SourceLine(_doc, "dockerPull", str),
                                [e],
                            )
                        )
        else:
            dockerPull = None
        if "dockerLoad" in _doc:
            try:
                dockerLoad = load_field(
                    _doc.get("dockerLoad"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerLoad")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerLoad`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerLoad"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerLoad` field is not valid because:",
                                SourceLine(_doc, "dockerLoad", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerLoad` field is not valid because:",
                                SourceLine(_doc, "dockerLoad", str),
                                [e],
                            )
                        )
        else:
            dockerLoad = None
        if "dockerFile" in _doc:
            try:
                dockerFile = load_field(
                    _doc.get("dockerFile"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerFile")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerFile`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerFile"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerFile` field is not valid because:",
                                SourceLine(_doc, "dockerFile", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerFile` field is not valid because:",
                                SourceLine(_doc, "dockerFile", str),
                                [e],
                            )
                        )
        else:
            dockerFile = None
        if "dockerImport" in _doc:
            try:
                dockerImport = load_field(
                    _doc.get("dockerImport"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerImport")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerImport`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerImport"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerImport` field is not valid because:",
                                SourceLine(_doc, "dockerImport", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerImport` field is not valid because:",
                                SourceLine(_doc, "dockerImport", str),
                                [e],
                            )
                        )
        else:
            dockerImport = None
        if "dockerImageId" in _doc:
            try:
                dockerImageId = load_field(
                    _doc.get("dockerImageId"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerImageId")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerImageId`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerImageId"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerImageId` field is not valid because:",
                                SourceLine(_doc, "dockerImageId", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerImageId` field is not valid because:",
                                SourceLine(_doc, "dockerImageId", str),
                                [e],
                            )
                        )
        else:
            dockerImageId = None
        if "dockerOutputDirectory" in _doc:
            try:
                dockerOutputDirectory = load_field(
                    _doc.get("dockerOutputDirectory"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("dockerOutputDirectory")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `dockerOutputDirectory`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("dockerOutputDirectory"))))
                        _errors__.append(
                            ValidationException(
                                "the `dockerOutputDirectory` field is not valid because:",
                                SourceLine(_doc, "dockerOutputDirectory", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `dockerOutputDirectory` field is not valid because:",
                                SourceLine(_doc, "dockerOutputDirectory", str),
                                [e],
                            )
                        )
        else:
            dockerOutputDirectory = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `dockerPull`, `dockerLoad`, `dockerFile`, `dockerImport`, `dockerImageId`, `dockerOutputDirectory`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            dockerPull=dockerPull,
            dockerLoad=dockerLoad,
            dockerFile=dockerFile,
            dockerImport=dockerImport,
            dockerImageId=dockerImageId,
            dockerOutputDirectory=dockerOutputDirectory,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "DockerRequirement"
        if self.dockerPull is not None:
            r["dockerPull"] = save(
                self.dockerPull,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.dockerLoad is not None:
            r["dockerLoad"] = save(
                self.dockerLoad,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.dockerFile is not None:
            r["dockerFile"] = save(
                self.dockerFile,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.dockerImport is not None:
            r["dockerImport"] = save(
                self.dockerImport,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.dockerImageId is not None:
            r["dockerImageId"] = save(
                self.dockerImageId,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.dockerOutputDirectory is not None:
            r["dockerOutputDirectory"] = save(
                self.dockerOutputDirectory,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "class",
            "dockerPull",
            "dockerLoad",
            "dockerFile",
            "dockerImport",
            "dockerImageId",
            "dockerOutputDirectory",
        ]
    )


class SoftwareRequirement(ProcessRequirement):
    """
    A list of software packages that should be configured in the environment of
    the defined process.

    """

    def __init__(
        self,
        packages: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SoftwareRequirement"
        self.packages = packages

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SoftwareRequirement):
            return bool(self.class_ == other.class_ and self.packages == other.packages)
        return False

    def __hash__(self) -> int:
        return hash((self.class_, self.packages))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "SoftwareRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "SoftwareRequirement":
            raise ValidationException("tried `SoftwareRequirement` but")

        try:
            if _doc.get("packages") is None:
                raise ValidationException("missing required field `packages`", None, [])

            packages = load_field(
                _doc.get("packages"),
                idmap_packages_array_of_SoftwarePackageLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("packages")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `packages`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("packages"))))
                    _errors__.append(
                        ValidationException(
                            "the `packages` field is not valid because:",
                            SourceLine(_doc, "packages", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `packages` field is not valid because:",
                            SourceLine(_doc, "packages", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `packages`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            packages=packages,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "SoftwareRequirement"
        if self.packages is not None:
            r["packages"] = save(
                self.packages, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "packages"])


class SoftwarePackage(Saveable):
    def __init__(
        self,
        package: Any,
        version: Optional[Any] = None,
        specs: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.package = package
        self.version = version
        self.specs = specs

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SoftwarePackage):
            return bool(
                self.package == other.package
                and self.version == other.version
                and self.specs == other.specs
            )
        return False

    def __hash__(self) -> int:
        return hash((self.package, self.version, self.specs))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "SoftwarePackage":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            if _doc.get("package") is None:
                raise ValidationException("missing required field `package`", None, [])

            package = load_field(
                _doc.get("package"),
                strtype,
                baseuri,
                loadingOptions,
                lc=_doc.get("package")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `package`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("package"))))
                    _errors__.append(
                        ValidationException(
                            "the `package` field is not valid because:",
                            SourceLine(_doc, "package", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `package` field is not valid because:",
                            SourceLine(_doc, "package", str),
                            [e],
                        )
                    )
        if "version" in _doc:
            try:
                version = load_field(
                    _doc.get("version"),
                    union_of_None_type_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("version")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `version`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("version"))))
                        _errors__.append(
                            ValidationException(
                                "the `version` field is not valid because:",
                                SourceLine(_doc, "version", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `version` field is not valid because:",
                                SourceLine(_doc, "version", str),
                                [e],
                            )
                        )
        else:
            version = None
        if "specs" in _doc:
            try:
                specs = load_field(
                    _doc.get("specs"),
                    uri_union_of_None_type_or_array_of_strtype_False_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("specs")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `specs`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("specs"))))
                        _errors__.append(
                            ValidationException(
                                "the `specs` field is not valid because:",
                                SourceLine(_doc, "specs", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `specs` field is not valid because:",
                                SourceLine(_doc, "specs", str),
                                [e],
                            )
                        )
        else:
            specs = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `package`, `version`, `specs`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            package=package,
            version=version,
            specs=specs,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.package is not None:
            r["package"] = save(
                self.package, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.version is not None:
            r["version"] = save(
                self.version, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.specs is not None:
            u = save_relative_uri(self.specs, base_url, False, None, relative_uris)
            r["specs"] = u

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["package", "version", "specs"])


class Dirent(Saveable):
    """
    Define a file or subdirectory that must be placed in the designated output
    directory prior to executing the command line tool.  May be the result of
    executing an expression, such as building a configuration file from a
    template.

    """

    def __init__(
        self,
        entry: Any,
        entryname: Optional[Any] = None,
        writable: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.entryname = entryname
        self.entry = entry
        self.writable = writable

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, Dirent):
            return bool(
                self.entryname == other.entryname
                and self.entry == other.entry
                and self.writable == other.writable
            )
        return False

    def __hash__(self) -> int:
        return hash((self.entryname, self.entry, self.writable))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "Dirent":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "entryname" in _doc:
            try:
                entryname = load_field(
                    _doc.get("entryname"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("entryname")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `entryname`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("entryname"))))
                        _errors__.append(
                            ValidationException(
                                "the `entryname` field is not valid because:",
                                SourceLine(_doc, "entryname", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `entryname` field is not valid because:",
                                SourceLine(_doc, "entryname", str),
                                [e],
                            )
                        )
        else:
            entryname = None
        try:
            if _doc.get("entry") is None:
                raise ValidationException("missing required field `entry`", None, [])

            entry = load_field(
                _doc.get("entry"),
                union_of_strtype_or_ExpressionLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("entry")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `entry`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("entry"))))
                    _errors__.append(
                        ValidationException(
                            "the `entry` field is not valid because:",
                            SourceLine(_doc, "entry", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `entry` field is not valid because:",
                            SourceLine(_doc, "entry", str),
                            [e],
                        )
                    )
        if "writable" in _doc:
            try:
                writable = load_field(
                    _doc.get("writable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("writable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `writable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("writable"))))
                        _errors__.append(
                            ValidationException(
                                "the `writable` field is not valid because:",
                                SourceLine(_doc, "writable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `writable` field is not valid because:",
                                SourceLine(_doc, "writable", str),
                                [e],
                            )
                        )
        else:
            writable = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `entryname`, `entry`, `writable`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            entryname=entryname,
            entry=entry,
            writable=writable,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.entryname is not None:
            r["entryname"] = save(
                self.entryname,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.entry is not None:
            r["entry"] = save(
                self.entry, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.writable is not None:
            r["writable"] = save(
                self.writable, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["entryname", "entry", "writable"])


class InitialWorkDirRequirement(ProcessRequirement):
    """
    Define a list of files and subdirectories that must be created by the workflow platform in the designated output directory prior to executing the command line tool.
    """

    def __init__(
        self,
        listing: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "InitialWorkDirRequirement"
        self.listing = listing

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, InitialWorkDirRequirement):
            return bool(self.class_ == other.class_ and self.listing == other.listing)
        return False

    def __hash__(self) -> int:
        return hash((self.class_, self.listing))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "InitialWorkDirRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "InitialWorkDirRequirement":
            raise ValidationException("tried `InitialWorkDirRequirement` but")

        try:
            if _doc.get("listing") is None:
                raise ValidationException("missing required field `listing`", None, [])

            listing = load_field(
                _doc.get("listing"),
                union_of_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("listing")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `listing`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("listing"))))
                    _errors__.append(
                        ValidationException(
                            "the `listing` field is not valid because:",
                            SourceLine(_doc, "listing", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `listing` field is not valid because:",
                            SourceLine(_doc, "listing", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `listing`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            listing=listing,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "InitialWorkDirRequirement"
        if self.listing is not None:
            r["listing"] = save(
                self.listing, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "listing"])


class EnvVarRequirement(ProcessRequirement):
    """
    Define a list of environment variables which will be set in the
    execution environment of the tool.  See `EnvironmentDef` for details.

    """

    def __init__(
        self,
        envDef: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "EnvVarRequirement"
        self.envDef = envDef

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, EnvVarRequirement):
            return bool(self.class_ == other.class_ and self.envDef == other.envDef)
        return False

    def __hash__(self) -> int:
        return hash((self.class_, self.envDef))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "EnvVarRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "EnvVarRequirement":
            raise ValidationException("tried `EnvVarRequirement` but")

        try:
            if _doc.get("envDef") is None:
                raise ValidationException("missing required field `envDef`", None, [])

            envDef = load_field(
                _doc.get("envDef"),
                idmap_envDef_array_of_EnvironmentDefLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("envDef")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `envDef`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("envDef"))))
                    _errors__.append(
                        ValidationException(
                            "the `envDef` field is not valid because:",
                            SourceLine(_doc, "envDef", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `envDef` field is not valid because:",
                            SourceLine(_doc, "envDef", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `envDef`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            envDef=envDef,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "EnvVarRequirement"
        if self.envDef is not None:
            r["envDef"] = save(
                self.envDef, top=False, base_url=base_url, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class", "envDef"])


class ShellCommandRequirement(ProcessRequirement):
    """
    Modify the behavior of CommandLineTool to generate a single string
    containing a shell command line.  Each item in the argument list must be
    joined into a string separated by single spaces and quoted to prevent
    intepretation by the shell, unless `CommandLineBinding` for that argument
    contains `shellQuote: false`.  If `shellQuote: false` is specified, the
    argument is joined into the command string without quoting, which allows
    the use of shell metacharacters such as `|` for pipes.

    """

    def __init__(
        self,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ShellCommandRequirement"

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ShellCommandRequirement):
            return bool(self.class_ == other.class_)
        return False

    def __hash__(self) -> int:
        return hash((self.class_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ShellCommandRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "ShellCommandRequirement":
            raise ValidationException("tried `ShellCommandRequirement` but")

        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "ShellCommandRequirement"

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class"])


class ResourceRequirement(ProcessRequirement):
    """
    Specify basic hardware resource requirements.

    "min" is the minimum amount of a resource that must be reserved to schedule
    a job. If "min" cannot be satisfied, the job should not be run.

    "max" is the maximum amount of a resource that the job shall be permitted
    to use. If a node has sufficient resources, multiple jobs may be scheduled
    on a single node provided each job's "max" resource requirements are
    met. If a job attempts to exceed its "max" resource allocation, an
    implementation may deny additional resources, which may result in job
    failure.

    If "min" is specified but "max" is not, then "max" == "min"
    If "max" is specified by "min" is not, then "min" == "max".

    It is an error if max < min.

    It is an error if the value of any of these fields is negative.

    If neither "min" nor "max" is specified for a resource, an implementation may provide a default.

    """

    def __init__(
        self,
        coresMin: Optional[Any] = None,
        coresMax: Optional[Any] = None,
        ramMin: Optional[Any] = None,
        ramMax: Optional[Any] = None,
        tmpdirMin: Optional[Any] = None,
        tmpdirMax: Optional[Any] = None,
        outdirMin: Optional[Any] = None,
        outdirMax: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ResourceRequirement"
        self.coresMin = coresMin
        self.coresMax = coresMax
        self.ramMin = ramMin
        self.ramMax = ramMax
        self.tmpdirMin = tmpdirMin
        self.tmpdirMax = tmpdirMax
        self.outdirMin = outdirMin
        self.outdirMax = outdirMax

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ResourceRequirement):
            return bool(
                self.class_ == other.class_
                and self.coresMin == other.coresMin
                and self.coresMax == other.coresMax
                and self.ramMin == other.ramMin
                and self.ramMax == other.ramMax
                and self.tmpdirMin == other.tmpdirMin
                and self.tmpdirMax == other.tmpdirMax
                and self.outdirMin == other.outdirMin
                and self.outdirMax == other.outdirMax
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.class_,
                self.coresMin,
                self.coresMax,
                self.ramMin,
                self.ramMax,
                self.tmpdirMin,
                self.tmpdirMax,
                self.outdirMin,
                self.outdirMax,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ResourceRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "ResourceRequirement":
            raise ValidationException("tried `ResourceRequirement` but")

        if "coresMin" in _doc:
            try:
                coresMin = load_field(
                    _doc.get("coresMin"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("coresMin")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `coresMin`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("coresMin"))))
                        _errors__.append(
                            ValidationException(
                                "the `coresMin` field is not valid because:",
                                SourceLine(_doc, "coresMin", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `coresMin` field is not valid because:",
                                SourceLine(_doc, "coresMin", str),
                                [e],
                            )
                        )
        else:
            coresMin = None
        if "coresMax" in _doc:
            try:
                coresMax = load_field(
                    _doc.get("coresMax"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("coresMax")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `coresMax`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("coresMax"))))
                        _errors__.append(
                            ValidationException(
                                "the `coresMax` field is not valid because:",
                                SourceLine(_doc, "coresMax", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `coresMax` field is not valid because:",
                                SourceLine(_doc, "coresMax", str),
                                [e],
                            )
                        )
        else:
            coresMax = None
        if "ramMin" in _doc:
            try:
                ramMin = load_field(
                    _doc.get("ramMin"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("ramMin")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `ramMin`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("ramMin"))))
                        _errors__.append(
                            ValidationException(
                                "the `ramMin` field is not valid because:",
                                SourceLine(_doc, "ramMin", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `ramMin` field is not valid because:",
                                SourceLine(_doc, "ramMin", str),
                                [e],
                            )
                        )
        else:
            ramMin = None
        if "ramMax" in _doc:
            try:
                ramMax = load_field(
                    _doc.get("ramMax"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("ramMax")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `ramMax`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("ramMax"))))
                        _errors__.append(
                            ValidationException(
                                "the `ramMax` field is not valid because:",
                                SourceLine(_doc, "ramMax", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `ramMax` field is not valid because:",
                                SourceLine(_doc, "ramMax", str),
                                [e],
                            )
                        )
        else:
            ramMax = None
        if "tmpdirMin" in _doc:
            try:
                tmpdirMin = load_field(
                    _doc.get("tmpdirMin"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("tmpdirMin")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `tmpdirMin`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("tmpdirMin"))))
                        _errors__.append(
                            ValidationException(
                                "the `tmpdirMin` field is not valid because:",
                                SourceLine(_doc, "tmpdirMin", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `tmpdirMin` field is not valid because:",
                                SourceLine(_doc, "tmpdirMin", str),
                                [e],
                            )
                        )
        else:
            tmpdirMin = None
        if "tmpdirMax" in _doc:
            try:
                tmpdirMax = load_field(
                    _doc.get("tmpdirMax"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("tmpdirMax")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `tmpdirMax`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("tmpdirMax"))))
                        _errors__.append(
                            ValidationException(
                                "the `tmpdirMax` field is not valid because:",
                                SourceLine(_doc, "tmpdirMax", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `tmpdirMax` field is not valid because:",
                                SourceLine(_doc, "tmpdirMax", str),
                                [e],
                            )
                        )
        else:
            tmpdirMax = None
        if "outdirMin" in _doc:
            try:
                outdirMin = load_field(
                    _doc.get("outdirMin"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outdirMin")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outdirMin`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outdirMin"))))
                        _errors__.append(
                            ValidationException(
                                "the `outdirMin` field is not valid because:",
                                SourceLine(_doc, "outdirMin", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outdirMin` field is not valid because:",
                                SourceLine(_doc, "outdirMin", str),
                                [e],
                            )
                        )
        else:
            outdirMin = None
        if "outdirMax" in _doc:
            try:
                outdirMax = load_field(
                    _doc.get("outdirMax"),
                    union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outdirMax")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outdirMax`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outdirMax"))))
                        _errors__.append(
                            ValidationException(
                                "the `outdirMax` field is not valid because:",
                                SourceLine(_doc, "outdirMax", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outdirMax` field is not valid because:",
                                SourceLine(_doc, "outdirMax", str),
                                [e],
                            )
                        )
        else:
            outdirMax = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`, `coresMin`, `coresMax`, `ramMin`, `ramMax`, `tmpdirMin`, `tmpdirMax`, `outdirMin`, `outdirMax`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            coresMin=coresMin,
            coresMax=coresMax,
            ramMin=ramMin,
            ramMax=ramMax,
            tmpdirMin=tmpdirMin,
            tmpdirMax=tmpdirMax,
            outdirMin=outdirMin,
            outdirMax=outdirMax,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "ResourceRequirement"
        if self.coresMin is not None:
            r["coresMin"] = save(
                self.coresMin, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.coresMax is not None:
            r["coresMax"] = save(
                self.coresMax, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.ramMin is not None:
            r["ramMin"] = save(
                self.ramMin, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.ramMax is not None:
            r["ramMax"] = save(
                self.ramMax, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.tmpdirMin is not None:
            r["tmpdirMin"] = save(
                self.tmpdirMin,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.tmpdirMax is not None:
            r["tmpdirMax"] = save(
                self.tmpdirMax,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.outdirMin is not None:
            r["outdirMin"] = save(
                self.outdirMin,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.outdirMax is not None:
            r["outdirMax"] = save(
                self.outdirMax,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "class",
            "coresMin",
            "coresMax",
            "ramMin",
            "ramMax",
            "tmpdirMin",
            "tmpdirMax",
            "outdirMin",
            "outdirMax",
        ]
    )


class ExpressionToolOutputParameter(OutputParameter):
    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        format: Optional[Any] = None,
        type_: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.outputBinding = outputBinding
        self.format = format
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ExpressionToolOutputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.outputBinding == other.outputBinding
                and self.format == other.format
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.outputBinding,
                self.format,
                self.type_,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ExpressionToolOutputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "type" in _doc:
            try:
                type_ = load_field(
                    _doc.get("type"),
                    typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("type")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `type`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("type"))))
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [e],
                            )
                        )
        else:
            type_ = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            outputBinding=outputBinding,
            format=format,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "outputBinding",
            "format",
            "type",
        ]
    )


class ExpressionTool(Process):
    """
    Execute an expression as a Workflow step.

    """

    def __init__(
        self,
        inputs: Any,
        outputs: Any,
        expression: Any,
        id: Optional[Any] = None,
        requirements: Optional[Any] = None,
        hints: Optional[Any] = None,
        label: Optional[Any] = None,
        doc: Optional[Any] = None,
        cwlVersion: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.label = label
        self.doc = doc
        self.cwlVersion = cwlVersion
        self.class_ = "ExpressionTool"
        self.expression = expression

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ExpressionTool):
            return bool(
                self.id == other.id
                and self.inputs == other.inputs
                and self.outputs == other.outputs
                and self.requirements == other.requirements
                and self.hints == other.hints
                and self.label == other.label
                and self.doc == other.doc
                and self.cwlVersion == other.cwlVersion
                and self.class_ == other.class_
                and self.expression == other.expression
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.id,
                self.inputs,
                self.outputs,
                self.requirements,
                self.hints,
                self.label,
                self.doc,
                self.cwlVersion,
                self.class_,
                self.expression,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ExpressionTool":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "ExpressionTool":
            raise ValidationException("tried `ExpressionTool` but")

        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        if not __original_id_is_none:
            baseuri = id
        try:
            if _doc.get("inputs") is None:
                raise ValidationException("missing required field `inputs`", None, [])

            inputs = load_field(
                _doc.get("inputs"),
                idmap_inputs_array_of_InputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("inputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `inputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("inputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("outputs") is None:
                raise ValidationException("missing required field `outputs`", None, [])

            outputs = load_field(
                _doc.get("outputs"),
                idmap_outputs_array_of_ExpressionToolOutputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("outputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `outputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("outputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [e],
                        )
                    )
        if "requirements" in _doc:
            try:
                requirements = load_field(
                    _doc.get("requirements"),
                    idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("requirements")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `requirements`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("requirements"))))
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [e],
                            )
                        )
        else:
            requirements = None
        if "hints" in _doc:
            try:
                hints = load_field(
                    _doc.get("hints"),
                    idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("hints")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `hints`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("hints"))))
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [e],
                            )
                        )
        else:
            hints = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "cwlVersion" in _doc:
            try:
                cwlVersion = load_field(
                    _doc.get("cwlVersion"),
                    uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("cwlVersion")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `cwlVersion`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("cwlVersion"))))
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [e],
                            )
                        )
        else:
            cwlVersion = None
        try:
            if _doc.get("expression") is None:
                raise ValidationException("missing required field `expression`", None, [])

            expression = load_field(
                _doc.get("expression"),
                union_of_strtype_or_ExpressionLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("expression")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `expression`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("expression"))))
                    _errors__.append(
                        ValidationException(
                            "the `expression` field is not valid because:",
                            SourceLine(_doc, "expression", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `expression` field is not valid because:",
                            SourceLine(_doc, "expression", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `expression`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            id=id,
            inputs=inputs,
            outputs=outputs,
            requirements=requirements,
            hints=hints,
            label=label,
            doc=doc,
            cwlVersion=cwlVersion,
            expression=expression,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "ExpressionTool"
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.inputs is not None:
            r["inputs"] = save(
                self.inputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputs is not None:
            r["outputs"] = save(
                self.outputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.requirements is not None:
            r["requirements"] = save(
                self.requirements,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.hints is not None:
            r["hints"] = save(
                self.hints, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.cwlVersion is not None:
            u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris)
            r["cwlVersion"] = u
        if self.expression is not None:
            r["expression"] = save(
                self.expression,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "id",
            "inputs",
            "outputs",
            "requirements",
            "hints",
            "label",
            "doc",
            "cwlVersion",
            "class",
            "expression",
        ]
    )


class WorkflowOutputParameter(OutputParameter):
    """
    Describe an output parameter of a workflow.  The parameter must be
    connected to one or more parameters defined in the workflow that will
    provide the value of the output parameter.

    """

    def __init__(
        self,
        id: Any,
        label: Optional[Any] = None,
        secondaryFiles: Optional[Any] = None,
        streamable: Optional[Any] = None,
        doc: Optional[Any] = None,
        outputBinding: Optional[Any] = None,
        format: Optional[Any] = None,
        outputSource: Optional[Any] = None,
        linkMerge: Optional[Any] = None,
        type_: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.doc = doc
        self.id = id
        self.outputBinding = outputBinding
        self.format = format
        self.outputSource = outputSource
        self.linkMerge = linkMerge
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, WorkflowOutputParameter):
            return bool(
                self.label == other.label
                and self.secondaryFiles == other.secondaryFiles
                and self.streamable == other.streamable
                and self.doc == other.doc
                and self.id == other.id
                and self.outputBinding == other.outputBinding
                and self.format == other.format
                and self.outputSource == other.outputSource
                and self.linkMerge == other.linkMerge
                and self.type_ == other.type_
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.label,
                self.secondaryFiles,
                self.streamable,
                self.doc,
                self.id,
                self.outputBinding,
                self.format,
                self.outputSource,
                self.linkMerge,
                self.type_,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "WorkflowOutputParameter":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "secondaryFiles" in _doc:
            try:
                secondaryFiles = load_field(
                    _doc.get("secondaryFiles"),
                    union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("secondaryFiles")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `secondaryFiles`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("secondaryFiles"))))
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `secondaryFiles` field is not valid because:",
                                SourceLine(_doc, "secondaryFiles", str),
                                [e],
                            )
                        )
        else:
            secondaryFiles = None
        if "streamable" in _doc:
            try:
                streamable = load_field(
                    _doc.get("streamable"),
                    union_of_None_type_or_booltype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("streamable")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `streamable`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("streamable"))))
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `streamable` field is not valid because:",
                                SourceLine(_doc, "streamable", str),
                                [e],
                            )
                        )
        else:
            streamable = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype_or_array_of_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "outputBinding" in _doc:
            try:
                outputBinding = load_field(
                    _doc.get("outputBinding"),
                    union_of_None_type_or_CommandOutputBindingLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputBinding")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputBinding`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputBinding"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputBinding` field is not valid because:",
                                SourceLine(_doc, "outputBinding", str),
                                [e],
                            )
                        )
        else:
            outputBinding = None
        if "format" in _doc:
            try:
                format = load_field(
                    _doc.get("format"),
                    uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("format")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `format`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("format"))))
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `format` field is not valid because:",
                                SourceLine(_doc, "format", str),
                                [e],
                            )
                        )
        else:
            format = None
        if "outputSource" in _doc:
            try:
                outputSource = load_field(
                    _doc.get("outputSource"),
                    uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("outputSource")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `outputSource`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("outputSource"))))
                        _errors__.append(
                            ValidationException(
                                "the `outputSource` field is not valid because:",
                                SourceLine(_doc, "outputSource", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `outputSource` field is not valid because:",
                                SourceLine(_doc, "outputSource", str),
                                [e],
                            )
                        )
        else:
            outputSource = None
        if "linkMerge" in _doc:
            try:
                linkMerge = load_field(
                    _doc.get("linkMerge"),
                    union_of_None_type_or_LinkMergeMethodLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("linkMerge")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `linkMerge`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("linkMerge"))))
                        _errors__.append(
                            ValidationException(
                                "the `linkMerge` field is not valid because:",
                                SourceLine(_doc, "linkMerge", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `linkMerge` field is not valid because:",
                                SourceLine(_doc, "linkMerge", str),
                                [e],
                            )
                        )
        else:
            linkMerge = None
        if "type" in _doc:
            try:
                type_ = load_field(
                    _doc.get("type"),
                    typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("type")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `type`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("type"))))
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `type` field is not valid because:",
                                SourceLine(_doc, "type", str),
                                [e],
                            )
                        )
        else:
            type_ = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `outputSource`, `linkMerge`, `type`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            label=label,
            secondaryFiles=secondaryFiles,
            streamable=streamable,
            doc=doc,
            id=id,
            outputBinding=outputBinding,
            format=format,
            outputSource=outputSource,
            linkMerge=linkMerge,
            type_=type_,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.secondaryFiles is not None:
            r["secondaryFiles"] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.streamable is not None:
            r["streamable"] = save(
                self.streamable,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputBinding is not None:
            r["outputBinding"] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.format is not None:
            u = save_relative_uri(self.format, self.id, True, None, relative_uris)
            r["format"] = u
        if self.outputSource is not None:
            u = save_relative_uri(self.outputSource, self.id, False, 1, relative_uris)
            r["outputSource"] = u
        if self.linkMerge is not None:
            r["linkMerge"] = save(
                self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "label",
            "secondaryFiles",
            "streamable",
            "doc",
            "id",
            "outputBinding",
            "format",
            "outputSource",
            "linkMerge",
            "type",
        ]
    )


class Sink(Saveable):
    pass


class WorkflowStepInput(Sink):
    """
    The input of a workflow step connects an upstream parameter (from the
    workflow inputs, or the outputs of other workflows steps) with the input
    parameters of the underlying step.

    ## Input object

    A WorkflowStepInput object must contain an `id` field in the form
    `#fieldname` or `#prefix/fieldname`.  When the `id` field contains a slash
    `/` the field name consists of the characters following the final slash
    (the prefix portion may contain one or more slashes to indicate scope).
    This defines a field of the workflow step input object with the value of
    the `source` parameter(s).

    ## Merging

    To merge multiple inbound data links,
    [MultipleInputFeatureRequirement](#MultipleInputFeatureRequirement) must be specified
    in the workflow or workflow step requirements.

    If the sink parameter is an array, or named in a [workflow
    scatter](#WorkflowStep) operation, there may be multiple inbound data links
    listed in the `source` field.  The values from the input links are merged
    depending on the method specified in the `linkMerge` field.  If not
    specified, the default method is "merge_nested".

    * **merge_nested**

      The input must be an array consisting of exactly one entry for each
      input link.  If "merge_nested" is specified with a single link, the value
      from the link must be wrapped in a single-item list.

    * **merge_flattened**

      1. The source and sink parameters must be compatible types, or the source
         type must be compatible with single element from the "items" type of
         the destination array parameter.
      2. Source parameters which are arrays are concatenated.
         Source parameters which are single element types are appended as
         single elements.

    """

    def __init__(
        self,
        id: Any,
        source: Optional[Any] = None,
        linkMerge: Optional[Any] = None,
        default: Optional[Any] = None,
        valueFrom: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.source = source
        self.linkMerge = linkMerge
        self.id = id
        self.default = default
        self.valueFrom = valueFrom

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, WorkflowStepInput):
            return bool(
                self.source == other.source
                and self.linkMerge == other.linkMerge
                and self.id == other.id
                and self.default == other.default
                and self.valueFrom == other.valueFrom
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (self.source, self.linkMerge, self.id, self.default, self.valueFrom)
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "WorkflowStepInput":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        if "source" in _doc:
            try:
                source = load_field(
                    _doc.get("source"),
                    uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("source")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `source`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("source"))))
                        _errors__.append(
                            ValidationException(
                                "the `source` field is not valid because:",
                                SourceLine(_doc, "source", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `source` field is not valid because:",
                                SourceLine(_doc, "source", str),
                                [e],
                            )
                        )
        else:
            source = None
        if "linkMerge" in _doc:
            try:
                linkMerge = load_field(
                    _doc.get("linkMerge"),
                    union_of_None_type_or_LinkMergeMethodLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("linkMerge")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `linkMerge`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("linkMerge"))))
                        _errors__.append(
                            ValidationException(
                                "the `linkMerge` field is not valid because:",
                                SourceLine(_doc, "linkMerge", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `linkMerge` field is not valid because:",
                                SourceLine(_doc, "linkMerge", str),
                                [e],
                            )
                        )
        else:
            linkMerge = None
        if "default" in _doc:
            try:
                default = load_field(
                    _doc.get("default"),
                    union_of_None_type_or_CWLObjectTypeLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("default")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `default`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("default"))))
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `default` field is not valid because:",
                                SourceLine(_doc, "default", str),
                                [e],
                            )
                        )
        else:
            default = None
        if "valueFrom" in _doc:
            try:
                valueFrom = load_field(
                    _doc.get("valueFrom"),
                    union_of_None_type_or_strtype_or_ExpressionLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("valueFrom")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `valueFrom`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("valueFrom"))))
                        _errors__.append(
                            ValidationException(
                                "the `valueFrom` field is not valid because:",
                                SourceLine(_doc, "valueFrom", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `valueFrom` field is not valid because:",
                                SourceLine(_doc, "valueFrom", str),
                                [e],
                            )
                        )
        else:
            valueFrom = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `source`, `linkMerge`, `id`, `default`, `valueFrom`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            source=source,
            linkMerge=linkMerge,
            id=id,
            default=default,
            valueFrom=valueFrom,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.source is not None:
            u = save_relative_uri(self.source, self.id, False, 2, relative_uris)
            r["source"] = u
        if self.linkMerge is not None:
            r["linkMerge"] = save(
                self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.default is not None:
            r["default"] = save(
                self.default, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.valueFrom is not None:
            r["valueFrom"] = save(
                self.valueFrom, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["source", "linkMerge", "id", "default", "valueFrom"])


class WorkflowStepOutput(Saveable):
    """
    Associate an output parameter of the underlying process with a workflow
    parameter.  The workflow parameter (given in the `id` field) be may be used
    as a `source` to connect with input parameters of other workflow steps, or
    with an output parameter of the process.

    """

    def __init__(
        self,
        id: Any,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, WorkflowStepOutput):
            return bool(self.id == other.id)
        return False

    def __hash__(self) -> int:
        return hash((self.id))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "WorkflowStepOutput":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `id`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            id=id,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["id"])


class WorkflowStep(Saveable):
    """
    A workflow step is an executable element of a workflow.  It specifies the
    underlying process implementation (such as `CommandLineTool` or another
    `Workflow`) in the `run` field and connects the input and output parameters
    of the underlying process to workflow parameters.

    # Scatter/gather

    To use scatter/gather,
    [ScatterFeatureRequirement](#ScatterFeatureRequirement) must be specified
    in the workflow or workflow step requirements.

    A "scatter" operation specifies that the associated workflow step or
    subworkflow should execute separately over a list of input elements.  Each
    job making up a scatter operation is independent and may be executed
    concurrently.

    The `scatter` field specifies one or more input parameters which will be
    scattered.  An input parameter may be listed more than once.  The declared
    type of each input parameter is implicitly becomes an array of items of the
    input parameter type.  If a parameter is listed more than once, it becomes
    a nested array.  As a result, upstream parameters which are connected to
    scattered parameters must be arrays.

    All output parameter types are also implicitly wrapped in arrays.  Each job
    in the scatter results in an entry in the output array.

    If any scattered parameter runtime value is an empty array, all outputs are
    set to empty arrays and no work is done for the step, according to
    applicable scattering rules.

    If `scatter` declares more than one input parameter, `scatterMethod`
    describes how to decompose the input into a discrete set of jobs.

      * **dotproduct** specifies that each of the input arrays are aligned and one
          element taken from each array to construct each job.  It is an error
          if all input arrays are not the same length.

      * **nested_crossproduct** specifies the Cartesian product of the inputs,
          producing a job for every combination of the scattered inputs.  The
          output must be nested arrays for each level of scattering, in the
          order that the input arrays are listed in the `scatter` field.

      * **flat_crossproduct** specifies the Cartesian product of the inputs,
          producing a job for every combination of the scattered inputs.  The
          output arrays must be flattened to a single level, but otherwise listed in the
          order that the input arrays are listed in the `scatter` field.

    # Subworkflows

    To specify a nested workflow as part of a workflow step,
    [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) must be
    specified in the workflow or workflow step requirements.

    It is a fatal error if a workflow directly or indirectly invokes itself as
    a subworkflow (recursive workflows are not allowed).

    """

    def __init__(
        self,
        id: Any,
        in_: Any,
        out: Any,
        run: Any,
        requirements: Optional[Any] = None,
        hints: Optional[Any] = None,
        label: Optional[Any] = None,
        doc: Optional[Any] = None,
        scatter: Optional[Any] = None,
        scatterMethod: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.in_ = in_
        self.out = out
        self.requirements = requirements
        self.hints = hints
        self.label = label
        self.doc = doc
        self.run = run
        self.scatter = scatter
        self.scatterMethod = scatterMethod

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, WorkflowStep):
            return bool(
                self.id == other.id
                and self.in_ == other.in_
                and self.out == other.out
                and self.requirements == other.requirements
                and self.hints == other.hints
                and self.label == other.label
                and self.doc == other.doc
                and self.run == other.run
                and self.scatter == other.scatter
                and self.scatterMethod == other.scatterMethod
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.id,
                self.in_,
                self.out,
                self.requirements,
                self.hints,
                self.label,
                self.doc,
                self.run,
                self.scatter,
                self.scatterMethod,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "WorkflowStep":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                _errors__.append(ValidationException("missing id"))
        if not __original_id_is_none:
            baseuri = id
        try:
            if _doc.get("in") is None:
                raise ValidationException("missing required field `in`", None, [])

            in_ = load_field(
                _doc.get("in"),
                idmap_in__array_of_WorkflowStepInputLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("in")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `in`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("in"))))
                    _errors__.append(
                        ValidationException(
                            "the `in` field is not valid because:",
                            SourceLine(_doc, "in", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `in` field is not valid because:",
                            SourceLine(_doc, "in", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("out") is None:
                raise ValidationException("missing required field `out`", None, [])

            out = load_field(
                _doc.get("out"),
                uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("out")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `out`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("out"))))
                    _errors__.append(
                        ValidationException(
                            "the `out` field is not valid because:",
                            SourceLine(_doc, "out", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `out` field is not valid because:",
                            SourceLine(_doc, "out", str),
                            [e],
                        )
                    )
        if "requirements" in _doc:
            try:
                requirements = load_field(
                    _doc.get("requirements"),
                    idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("requirements")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `requirements`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("requirements"))))
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [e],
                            )
                        )
        else:
            requirements = None
        if "hints" in _doc:
            try:
                hints = load_field(
                    _doc.get("hints"),
                    idmap_hints_union_of_None_type_or_array_of_Any_type,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("hints")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `hints`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("hints"))))
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [e],
                            )
                        )
        else:
            hints = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        try:
            if _doc.get("run") is None:
                raise ValidationException("missing required field `run`", None, [])

            run = load_field(
                _doc.get("run"),
                uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_False_False_None_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("run")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `run`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("run"))))
                    _errors__.append(
                        ValidationException(
                            "the `run` field is not valid because:",
                            SourceLine(_doc, "run", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `run` field is not valid because:",
                            SourceLine(_doc, "run", str),
                            [e],
                        )
                    )
        if "scatter" in _doc:
            try:
                scatter = load_field(
                    _doc.get("scatter"),
                    uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("scatter")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `scatter`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("scatter"))))
                        _errors__.append(
                            ValidationException(
                                "the `scatter` field is not valid because:",
                                SourceLine(_doc, "scatter", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `scatter` field is not valid because:",
                                SourceLine(_doc, "scatter", str),
                                [e],
                            )
                        )
        else:
            scatter = None
        if "scatterMethod" in _doc:
            try:
                scatterMethod = load_field(
                    _doc.get("scatterMethod"),
                    uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("scatterMethod")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `scatterMethod`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("scatterMethod"))))
                        _errors__.append(
                            ValidationException(
                                "the `scatterMethod` field is not valid because:",
                                SourceLine(_doc, "scatterMethod", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `scatterMethod` field is not valid because:",
                                SourceLine(_doc, "scatterMethod", str),
                                [e],
                            )
                        )
        else:
            scatterMethod = None
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `id`, `in`, `out`, `requirements`, `hints`, `label`, `doc`, `run`, `scatter`, `scatterMethod`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            id=id,
            in_=in_,
            out=out,
            requirements=requirements,
            hints=hints,
            label=label,
            doc=doc,
            run=run,
            scatter=scatter,
            scatterMethod=scatterMethod,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.in_ is not None:
            r["in"] = save(
                self.in_, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.out is not None:
            u = save_relative_uri(self.out, self.id, True, None, relative_uris)
            r["out"] = u
        if self.requirements is not None:
            r["requirements"] = save(
                self.requirements,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.hints is not None:
            r["hints"] = save(
                self.hints, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.run is not None:
            u = save_relative_uri(self.run, self.id, False, None, relative_uris)
            r["run"] = u
        if self.scatter is not None:
            u = save_relative_uri(self.scatter, self.id, False, 0, relative_uris)
            r["scatter"] = u
        if self.scatterMethod is not None:
            u = save_relative_uri(
                self.scatterMethod, self.id, False, None, relative_uris
            )
            r["scatterMethod"] = u

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "id",
            "in",
            "out",
            "requirements",
            "hints",
            "label",
            "doc",
            "run",
            "scatter",
            "scatterMethod",
        ]
    )


class Workflow(Process):
    """
    A workflow describes a set of **steps** and the **dependencies** between
    those steps.  When a step produces output that will be consumed by a
    second step, the first step is a dependency of the second step.

    When there is a dependency, the workflow engine must execute the preceding
    step and wait for it to successfully produce output before executing the
    dependent step.  If two steps are defined in the workflow graph that
    are not directly or indirectly dependent, these steps are **independent**,
    and may execute in any order or execute concurrently.  A workflow is
    complete when all steps have been executed.

    Dependencies between parameters are expressed using the `source` field on
    [workflow step input parameters](#WorkflowStepInput) and [workflow output
    parameters](#WorkflowOutputParameter).

    The `source` field expresses the dependency of one parameter on another
    such that when a value is associated with the parameter specified by
    `source`, that value is propagated to the destination parameter.  When all
    data links inbound to a given step are fufilled, the step is ready to
    execute.

    ## Workflow success and failure

    A completed step must result in one of `success`, `temporaryFailure` or
    `permanentFailure` states.  An implementation may choose to retry a step
    execution which resulted in `temporaryFailure`.  An implementation may
    choose to either continue running other steps of a workflow, or terminate
    immediately upon `permanentFailure`.

    * If any step of a workflow execution results in `permanentFailure`, then
    the workflow status is `permanentFailure`.

    * If one or more steps result in `temporaryFailure` and all other steps
    complete `success` or are not executed, then the workflow status is
    `temporaryFailure`.

    * If all workflow steps are executed and complete with `success`, then the
    workflow status is `success`.

    # Extensions

    [ScatterFeatureRequirement](#ScatterFeatureRequirement) and
    [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) are
    available as standard [extensions](#Extensions_and_Metadata) to core
    workflow semantics.

    """

    def __init__(
        self,
        inputs: Any,
        outputs: Any,
        steps: Any,
        id: Optional[Any] = None,
        requirements: Optional[Any] = None,
        hints: Optional[Any] = None,
        label: Optional[Any] = None,
        doc: Optional[Any] = None,
        cwlVersion: Optional[Any] = None,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.label = label
        self.doc = doc
        self.cwlVersion = cwlVersion
        self.class_ = "Workflow"
        self.steps = steps

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, Workflow):
            return bool(
                self.id == other.id
                and self.inputs == other.inputs
                and self.outputs == other.outputs
                and self.requirements == other.requirements
                and self.hints == other.hints
                and self.label == other.label
                and self.doc == other.doc
                and self.cwlVersion == other.cwlVersion
                and self.class_ == other.class_
                and self.steps == other.steps
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.id,
                self.inputs,
                self.outputs,
                self.requirements,
                self.hints,
                self.label,
                self.doc,
                self.cwlVersion,
                self.class_,
                self.steps,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "Workflow":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "Workflow":
            raise ValidationException("tried `Workflow` but")

        if "id" in _doc:
            try:
                id = load_field(
                    _doc.get("id"),
                    uri_union_of_None_type_or_strtype_True_False_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("id")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `id`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("id"))))
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `id` field is not valid because:",
                                SourceLine(_doc, "id", str),
                                [e],
                            )
                        )
        else:
            id = None

        __original_id_is_none = id is None
        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        if not __original_id_is_none:
            baseuri = id
        try:
            if _doc.get("inputs") is None:
                raise ValidationException("missing required field `inputs`", None, [])

            inputs = load_field(
                _doc.get("inputs"),
                idmap_inputs_array_of_InputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("inputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `inputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("inputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `inputs` field is not valid because:",
                            SourceLine(_doc, "inputs", str),
                            [e],
                        )
                    )
        try:
            if _doc.get("outputs") is None:
                raise ValidationException("missing required field `outputs`", None, [])

            outputs = load_field(
                _doc.get("outputs"),
                idmap_outputs_array_of_WorkflowOutputParameterLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("outputs")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `outputs`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("outputs"))))
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `outputs` field is not valid because:",
                            SourceLine(_doc, "outputs", str),
                            [e],
                        )
                    )
        if "requirements" in _doc:
            try:
                requirements = load_field(
                    _doc.get("requirements"),
                    idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("requirements")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `requirements`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("requirements"))))
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `requirements` field is not valid because:",
                                SourceLine(_doc, "requirements", str),
                                [e],
                            )
                        )
        else:
            requirements = None
        if "hints" in _doc:
            try:
                hints = load_field(
                    _doc.get("hints"),
                    idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("hints")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `hints`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("hints"))))
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `hints` field is not valid because:",
                                SourceLine(_doc, "hints", str),
                                [e],
                            )
                        )
        else:
            hints = None
        if "label" in _doc:
            try:
                label = load_field(
                    _doc.get("label"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("label")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `label`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("label"))))
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `label` field is not valid because:",
                                SourceLine(_doc, "label", str),
                                [e],
                            )
                        )
        else:
            label = None
        if "doc" in _doc:
            try:
                doc = load_field(
                    _doc.get("doc"),
                    union_of_None_type_or_strtype,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("doc")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `doc`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("doc"))))
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `doc` field is not valid because:",
                                SourceLine(_doc, "doc", str),
                                [e],
                            )
                        )
        else:
            doc = None
        if "cwlVersion" in _doc:
            try:
                cwlVersion = load_field(
                    _doc.get("cwlVersion"),
                    uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None,
                    baseuri,
                    loadingOptions,
                    lc=_doc.get("cwlVersion")
                )

            except ValidationException as e:
                error_message, to_print, verb_tensage = parse_errors(str(e))

                if str(e) == "missing required field `cwlVersion`":
                    _errors__.append(
                        ValidationException(
                            str(e),
                            None
                        )
                    )
                else:
                    if error_message != str(e):
                        val_type = convert_typing(extract_type(type(_doc.get("cwlVersion"))))
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [ValidationException(f"Value is a {val_type}, "
                                                     f"but valid {to_print} for this field "
                                                     f"{verb_tensage} {error_message}")],
                            )
                        )
                    else:
                        _errors__.append(
                            ValidationException(
                                "the `cwlVersion` field is not valid because:",
                                SourceLine(_doc, "cwlVersion", str),
                                [e],
                            )
                        )
        else:
            cwlVersion = None
        try:
            if _doc.get("steps") is None:
                raise ValidationException("missing required field `steps`", None, [])

            steps = load_field(
                _doc.get("steps"),
                idmap_steps_union_of_array_of_WorkflowStepLoader,
                baseuri,
                loadingOptions,
                lc=_doc.get("steps")
            )

        except ValidationException as e:
            error_message, to_print, verb_tensage = parse_errors(str(e))

            if str(e) == "missing required field `steps`":
                _errors__.append(
                    ValidationException(
                        str(e),
                        None
                    )
                )
            else:
                if error_message != str(e):
                    val_type = convert_typing(extract_type(type(_doc.get("steps"))))
                    _errors__.append(
                        ValidationException(
                            "the `steps` field is not valid because:",
                            SourceLine(_doc, "steps", str),
                            [ValidationException(f"Value is a {val_type}, "
                                                 f"but valid {to_print} for this field "
                                                 f"{verb_tensage} {error_message}")],
                        )
                    )
                else:
                    _errors__.append(
                        ValidationException(
                            "the `steps` field is not valid because:",
                            SourceLine(_doc, "steps", str),
                            [e],
                        )
                    )
        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `steps`".format(
                                k
                            ),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            id=id,
            inputs=inputs,
            outputs=outputs,
            requirements=requirements,
            hints=hints,
            label=label,
            doc=doc,
            cwlVersion=cwlVersion,
            steps=steps,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[id] = (_constructed, loadingOptions)
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "Workflow"
        if self.id is not None:
            u = save_relative_uri(self.id, base_url, True, None, relative_uris)
            r["id"] = u
        if self.inputs is not None:
            r["inputs"] = save(
                self.inputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.outputs is not None:
            r["outputs"] = save(
                self.outputs, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.requirements is not None:
            r["requirements"] = save(
                self.requirements,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris,
            )
        if self.hints is not None:
            r["hints"] = save(
                self.hints, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.label is not None:
            r["label"] = save(
                self.label, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.id, relative_uris=relative_uris
            )
        if self.cwlVersion is not None:
            u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris)
            r["cwlVersion"] = u
        if self.steps is not None:
            r["steps"] = save(
                self.steps, top=False, base_url=self.id, relative_uris=relative_uris
            )

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(
        [
            "id",
            "inputs",
            "outputs",
            "requirements",
            "hints",
            "label",
            "doc",
            "cwlVersion",
            "class",
            "steps",
        ]
    )


class SubworkflowFeatureRequirement(ProcessRequirement):
    """
    Indicates that the workflow platform must support nested workflows in
    the `run` field of [WorkflowStep](#WorkflowStep).

    """

    def __init__(
        self,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SubworkflowFeatureRequirement"

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SubworkflowFeatureRequirement):
            return bool(self.class_ == other.class_)
        return False

    def __hash__(self) -> int:
        return hash((self.class_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "SubworkflowFeatureRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "SubworkflowFeatureRequirement":
            raise ValidationException("tried `SubworkflowFeatureRequirement` but")

        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "SubworkflowFeatureRequirement"

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class"])


class ScatterFeatureRequirement(ProcessRequirement):
    """
    Indicates that the workflow platform must support the `scatter` and
    `scatterMethod` fields of [WorkflowStep](#WorkflowStep).

    """

    def __init__(
        self,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ScatterFeatureRequirement"

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, ScatterFeatureRequirement):
            return bool(self.class_ == other.class_)
        return False

    def __hash__(self) -> int:
        return hash((self.class_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "ScatterFeatureRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "ScatterFeatureRequirement":
            raise ValidationException("tried `ScatterFeatureRequirement` but")

        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "ScatterFeatureRequirement"

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class"])


class MultipleInputFeatureRequirement(ProcessRequirement):
    """
    Indicates that the workflow platform must support multiple inbound data links
    listed in the `source` field of [WorkflowStepInput](#WorkflowStepInput).

    """

    def __init__(
        self,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "MultipleInputFeatureRequirement"

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, MultipleInputFeatureRequirement):
            return bool(self.class_ == other.class_)
        return False

    def __hash__(self) -> int:
        return hash((self.class_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "MultipleInputFeatureRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "MultipleInputFeatureRequirement":
            raise ValidationException("tried `MultipleInputFeatureRequirement` but")

        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "MultipleInputFeatureRequirement"

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class"])


class StepInputExpressionRequirement(ProcessRequirement):
    """
    Indicate that the workflow platform must support the `valueFrom` field
    of [WorkflowStepInput](#WorkflowStepInput).

    """

    def __init__(
        self,
        extension_fields: Optional[Dict[str, Any]] = None,
        loadingOptions: Optional[LoadingOptions] = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "StepInputExpressionRequirement"

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, StepInputExpressionRequirement):
            return bool(self.class_ == other.class_)
        return False

    def __hash__(self) -> int:
        return hash((self.class_))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: Optional[str] = None
    ) -> "StepInputExpressionRequirement":
        _doc = copy.copy(doc)

        if hasattr(doc, "lc"):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []

        if "class" not in _doc:
            raise ValidationException("Missing 'class' field")
        if _doc.get("class") != "StepInputExpressionRequirement":
            raise ValidationException("tried `StepInputExpressionRequirement` but")

        extension_fields: Dict[str, Any] = {}
        for k in _doc.keys():
            if k not in cls.attrs:
                if not k:
                    _errors__.append(
                        ValidationException("mapping with implicit null key")
                    )
                elif ":" in k:
                    ex = expand_url(
                        k, "", loadingOptions, scoped_id=False, vocab_term=False
                    )
                    extension_fields[ex] = _doc[k]
                else:
                    _errors__.append(
                        ValidationException(
                            "invalid field `{}`, expected one of: `class`".format(k),
                            SourceLine(_doc, k, str),
                        )
                    )

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

    def save(
        self, top: bool = False, base_url: str = "", relative_uris: bool = True
    ) -> Dict[str, Any]:
        r: Dict[str, Any] = {}

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]

        r["class"] = "StepInputExpressionRequirement"

        # top refers to the directory level
        if top:
            if self.loadingOptions.namespaces:
                r["$namespaces"] = self.loadingOptions.namespaces
            if self.loadingOptions.schemas:
                r["$schemas"] = self.loadingOptions.schemas
        return r

    attrs = frozenset(["class"])


_vocab = {
    "Any": "https://w3id.org/cwl/salad#Any",
    "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema",
    "CWLArraySchema": "https://w3id.org/cwl/cwl#CWLArraySchema",
    "CWLInputFile": "https://w3id.org/cwl/cwl#CWLInputFile",
    "CWLObjectType": "https://w3id.org/cwl/cwl#CWLObjectType",
    "CWLRecordField": "https://w3id.org/cwl/cwl#CWLRecordField",
    "CWLRecordSchema": "https://w3id.org/cwl/cwl#CWLRecordSchema",
    "CWLType": "https://w3id.org/cwl/cwl#CWLType",
    "CWLVersion": "https://w3id.org/cwl/cwl#CWLVersion",
    "CommandInputArraySchema": "https://w3id.org/cwl/cwl#CommandInputArraySchema",
    "CommandInputEnumSchema": "https://w3id.org/cwl/cwl#CommandInputEnumSchema",
    "CommandInputParameter": "https://w3id.org/cwl/cwl#CommandInputParameter",
    "CommandInputRecordField": "https://w3id.org/cwl/cwl#CommandInputRecordField",
    "CommandInputRecordSchema": "https://w3id.org/cwl/cwl#CommandInputRecordSchema",
    "CommandLineBinding": "https://w3id.org/cwl/cwl#CommandLineBinding",
    "CommandLineTool": "https://w3id.org/cwl/cwl#CommandLineTool",
    "CommandOutputArraySchema": "https://w3id.org/cwl/cwl#CommandOutputArraySchema",
    "CommandOutputBinding": "https://w3id.org/cwl/cwl#CommandOutputBinding",
    "CommandOutputEnumSchema": "https://w3id.org/cwl/cwl#CommandOutputEnumSchema",
    "CommandOutputParameter": "https://w3id.org/cwl/cwl#CommandOutputParameter",
    "CommandOutputRecordField": "https://w3id.org/cwl/cwl#CommandOutputRecordField",
    "CommandOutputRecordSchema": "https://w3id.org/cwl/cwl#CommandOutputRecordSchema",
    "Directory": "https://w3id.org/cwl/cwl#Directory",
    "Dirent": "https://w3id.org/cwl/cwl#Dirent",
    "DockerRequirement": "https://w3id.org/cwl/cwl#DockerRequirement",
    "Documented": "https://w3id.org/cwl/salad#Documented",
    "EnumSchema": "https://w3id.org/cwl/salad#EnumSchema",
    "EnvVarRequirement": "https://w3id.org/cwl/cwl#EnvVarRequirement",
    "EnvironmentDef": "https://w3id.org/cwl/cwl#EnvironmentDef",
    "Expression": "https://w3id.org/cwl/cwl#Expression",
    "ExpressionPlaceholder": "https://w3id.org/cwl/cwl#ExpressionPlaceholder",
    "ExpressionTool": "https://w3id.org/cwl/cwl#ExpressionTool",
    "ExpressionToolOutputParameter": "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter",
    "File": "https://w3id.org/cwl/cwl#File",
    "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement",
    "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement",
    "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema",
    "InputBinding": "https://w3id.org/cwl/cwl#InputBinding",
    "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema",
    "InputParameter": "https://w3id.org/cwl/cwl#InputParameter",
    "InputRecordField": "https://w3id.org/cwl/cwl#InputRecordField",
    "InputRecordSchema": "https://w3id.org/cwl/cwl#InputRecordSchema",
    "InputSchema": "https://w3id.org/cwl/cwl#InputSchema",
    "LinkMergeMethod": "https://w3id.org/cwl/cwl#LinkMergeMethod",
    "MapSchema": "https://w3id.org/cwl/salad#MapSchema",
    "MultipleInputFeatureRequirement": "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement",
    "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema",
    "OutputBinding": "https://w3id.org/cwl/cwl#OutputBinding",
    "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema",
    "OutputParameter": "https://w3id.org/cwl/cwl#OutputParameter",
    "OutputRecordField": "https://w3id.org/cwl/cwl#OutputRecordField",
    "OutputRecordSchema": "https://w3id.org/cwl/cwl#OutputRecordSchema",
    "OutputSchema": "https://w3id.org/cwl/cwl#OutputSchema",
    "Parameter": "https://w3id.org/cwl/cwl#Parameter",
    "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType",
    "Process": "https://w3id.org/cwl/cwl#Process",
    "ProcessRequirement": "https://w3id.org/cwl/cwl#ProcessRequirement",
    "RecordField": "https://w3id.org/cwl/salad#RecordField",
    "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema",
    "ResourceRequirement": "https://w3id.org/cwl/cwl#ResourceRequirement",
    "ScatterFeatureRequirement": "https://w3id.org/cwl/cwl#ScatterFeatureRequirement",
    "ScatterMethod": "https://w3id.org/cwl/cwl#ScatterMethod",
    "SchemaBase": "https://w3id.org/cwl/cwl#SchemaBase",
    "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement",
    "ShellCommandRequirement": "https://w3id.org/cwl/cwl#ShellCommandRequirement",
    "Sink": "https://w3id.org/cwl/cwl#Sink",
    "SoftwarePackage": "https://w3id.org/cwl/cwl#SoftwarePackage",
    "SoftwareRequirement": "https://w3id.org/cwl/cwl#SoftwareRequirement",
    "StepInputExpressionRequirement": "https://w3id.org/cwl/cwl#StepInputExpressionRequirement",
    "SubworkflowFeatureRequirement": "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement",
    "UnionSchema": "https://w3id.org/cwl/salad#UnionSchema",
    "Workflow": "https://w3id.org/cwl/cwl#Workflow",
    "WorkflowOutputParameter": "https://w3id.org/cwl/cwl#WorkflowOutputParameter",
    "WorkflowStep": "https://w3id.org/cwl/cwl#WorkflowStep",
    "WorkflowStepInput": "https://w3id.org/cwl/cwl#WorkflowStepInput",
    "WorkflowStepOutput": "https://w3id.org/cwl/cwl#WorkflowStepOutput",
    "array": "https://w3id.org/cwl/salad#array",
    "boolean": "http://www.w3.org/2001/XMLSchema#boolean",
    "dotproduct": "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct",
    "double": "http://www.w3.org/2001/XMLSchema#double",
    "draft-2": "https://w3id.org/cwl/cwl#draft-2",
    "draft-3": "https://w3id.org/cwl/cwl#draft-3",
    "draft-3.dev1": "https://w3id.org/cwl/cwl#draft-3.dev1",
    "draft-3.dev2": "https://w3id.org/cwl/cwl#draft-3.dev2",
    "draft-3.dev3": "https://w3id.org/cwl/cwl#draft-3.dev3",
    "draft-3.dev4": "https://w3id.org/cwl/cwl#draft-3.dev4",
    "draft-3.dev5": "https://w3id.org/cwl/cwl#draft-3.dev5",
    "draft-4.dev1": "https://w3id.org/cwl/cwl#draft-4.dev1",
    "draft-4.dev2": "https://w3id.org/cwl/cwl#draft-4.dev2",
    "draft-4.dev3": "https://w3id.org/cwl/cwl#draft-4.dev3",
    "enum": "https://w3id.org/cwl/salad#enum",
    "flat_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct",
    "float": "http://www.w3.org/2001/XMLSchema#float",
    "int": "http://www.w3.org/2001/XMLSchema#int",
    "long": "http://www.w3.org/2001/XMLSchema#long",
    "map": "https://w3id.org/cwl/salad#map",
    "merge_flattened": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened",
    "merge_nested": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested",
    "nested_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct",
    "null": "https://w3id.org/cwl/salad#null",
    "record": "https://w3id.org/cwl/salad#record",
    "stderr": "https://w3id.org/cwl/cwl#stderr",
    "stdout": "https://w3id.org/cwl/cwl#stdout",
    "string": "http://www.w3.org/2001/XMLSchema#string",
    "union": "https://w3id.org/cwl/salad#union",
    "v1.0": "https://w3id.org/cwl/cwl#v1.0",
    "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4",
}
_rvocab = {
    "https://w3id.org/cwl/salad#Any": "Any",
    "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema",
    "https://w3id.org/cwl/cwl#CWLArraySchema": "CWLArraySchema",
    "https://w3id.org/cwl/cwl#CWLInputFile": "CWLInputFile",
    "https://w3id.org/cwl/cwl#CWLObjectType": "CWLObjectType",
    "https://w3id.org/cwl/cwl#CWLRecordField": "CWLRecordField",
    "https://w3id.org/cwl/cwl#CWLRecordSchema": "CWLRecordSchema",
    "https://w3id.org/cwl/cwl#CWLType": "CWLType",
    "https://w3id.org/cwl/cwl#CWLVersion": "CWLVersion",
    "https://w3id.org/cwl/cwl#CommandInputArraySchema": "CommandInputArraySchema",
    "https://w3id.org/cwl/cwl#CommandInputEnumSchema": "CommandInputEnumSchema",
    "https://w3id.org/cwl/cwl#CommandInputParameter": "CommandInputParameter",
    "https://w3id.org/cwl/cwl#CommandInputRecordField": "CommandInputRecordField",
    "https://w3id.org/cwl/cwl#CommandInputRecordSchema": "CommandInputRecordSchema",
    "https://w3id.org/cwl/cwl#CommandLineBinding": "CommandLineBinding",
    "https://w3id.org/cwl/cwl#CommandLineTool": "CommandLineTool",
    "https://w3id.org/cwl/cwl#CommandOutputArraySchema": "CommandOutputArraySchema",
    "https://w3id.org/cwl/cwl#CommandOutputBinding": "CommandOutputBinding",
    "https://w3id.org/cwl/cwl#CommandOutputEnumSchema": "CommandOutputEnumSchema",
    "https://w3id.org/cwl/cwl#CommandOutputParameter": "CommandOutputParameter",
    "https://w3id.org/cwl/cwl#CommandOutputRecordField": "CommandOutputRecordField",
    "https://w3id.org/cwl/cwl#CommandOutputRecordSchema": "CommandOutputRecordSchema",
    "https://w3id.org/cwl/cwl#Directory": "Directory",
    "https://w3id.org/cwl/cwl#Dirent": "Dirent",
    "https://w3id.org/cwl/cwl#DockerRequirement": "DockerRequirement",
    "https://w3id.org/cwl/salad#Documented": "Documented",
    "https://w3id.org/cwl/salad#EnumSchema": "EnumSchema",
    "https://w3id.org/cwl/cwl#EnvVarRequirement": "EnvVarRequirement",
    "https://w3id.org/cwl/cwl#EnvironmentDef": "EnvironmentDef",
    "https://w3id.org/cwl/cwl#Expression": "Expression",
    "https://w3id.org/cwl/cwl#ExpressionPlaceholder": "ExpressionPlaceholder",
    "https://w3id.org/cwl/cwl#ExpressionTool": "ExpressionTool",
    "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter": "ExpressionToolOutputParameter",
    "https://w3id.org/cwl/cwl#File": "File",
    "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement",
    "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement",
    "https://w3id.org/cwl/cwl#InputArraySchema": "InputArraySchema",
    "https://w3id.org/cwl/cwl#InputBinding": "InputBinding",
    "https://w3id.org/cwl/cwl#InputEnumSchema": "InputEnumSchema",
    "https://w3id.org/cwl/cwl#InputParameter": "InputParameter",
    "https://w3id.org/cwl/cwl#InputRecordField": "InputRecordField",
    "https://w3id.org/cwl/cwl#InputRecordSchema": "InputRecordSchema",
    "https://w3id.org/cwl/cwl#InputSchema": "InputSchema",
    "https://w3id.org/cwl/cwl#LinkMergeMethod": "LinkMergeMethod",
    "https://w3id.org/cwl/salad#MapSchema": "MapSchema",
    "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement": "MultipleInputFeatureRequirement",
    "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema",
    "https://w3id.org/cwl/cwl#OutputBinding": "OutputBinding",
    "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema",
    "https://w3id.org/cwl/cwl#OutputParameter": "OutputParameter",
    "https://w3id.org/cwl/cwl#OutputRecordField": "OutputRecordField",
    "https://w3id.org/cwl/cwl#OutputRecordSchema": "OutputRecordSchema",
    "https://w3id.org/cwl/cwl#OutputSchema": "OutputSchema",
    "https://w3id.org/cwl/cwl#Parameter": "Parameter",
    "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType",
    "https://w3id.org/cwl/cwl#Process": "Process",
    "https://w3id.org/cwl/cwl#ProcessRequirement": "ProcessRequirement",
    "https://w3id.org/cwl/salad#RecordField": "RecordField",
    "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema",
    "https://w3id.org/cwl/cwl#ResourceRequirement": "ResourceRequirement",
    "https://w3id.org/cwl/cwl#ScatterFeatureRequirement": "ScatterFeatureRequirement",
    "https://w3id.org/cwl/cwl#ScatterMethod": "ScatterMethod",
    "https://w3id.org/cwl/cwl#SchemaBase": "SchemaBase",
    "https://w3id.org/cwl/cwl#SchemaDefRequirement": "SchemaDefRequirement",
    "https://w3id.org/cwl/cwl#ShellCommandRequirement": "ShellCommandRequirement",
    "https://w3id.org/cwl/cwl#Sink": "Sink",
    "https://w3id.org/cwl/cwl#SoftwarePackage": "SoftwarePackage",
    "https://w3id.org/cwl/cwl#SoftwareRequirement": "SoftwareRequirement",
    "https://w3id.org/cwl/cwl#StepInputExpressionRequirement": "StepInputExpressionRequirement",
    "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement": "SubworkflowFeatureRequirement",
    "https://w3id.org/cwl/salad#UnionSchema": "UnionSchema",
    "https://w3id.org/cwl/cwl#Workflow": "Workflow",
    "https://w3id.org/cwl/cwl#WorkflowOutputParameter": "WorkflowOutputParameter",
    "https://w3id.org/cwl/cwl#WorkflowStep": "WorkflowStep",
    "https://w3id.org/cwl/cwl#WorkflowStepInput": "WorkflowStepInput",
    "https://w3id.org/cwl/cwl#WorkflowStepOutput": "WorkflowStepOutput",
    "https://w3id.org/cwl/salad#array": "array",
    "http://www.w3.org/2001/XMLSchema#boolean": "boolean",
    "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct": "dotproduct",
    "http://www.w3.org/2001/XMLSchema#double": "double",
    "https://w3id.org/cwl/cwl#draft-2": "draft-2",
    "https://w3id.org/cwl/cwl#draft-3": "draft-3",
    "https://w3id.org/cwl/cwl#draft-3.dev1": "draft-3.dev1",
    "https://w3id.org/cwl/cwl#draft-3.dev2": "draft-3.dev2",
    "https://w3id.org/cwl/cwl#draft-3.dev3": "draft-3.dev3",
    "https://w3id.org/cwl/cwl#draft-3.dev4": "draft-3.dev4",
    "https://w3id.org/cwl/cwl#draft-3.dev5": "draft-3.dev5",
    "https://w3id.org/cwl/cwl#draft-4.dev1": "draft-4.dev1",
    "https://w3id.org/cwl/cwl#draft-4.dev2": "draft-4.dev2",
    "https://w3id.org/cwl/cwl#draft-4.dev3": "draft-4.dev3",
    "https://w3id.org/cwl/salad#enum": "enum",
    "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct": "flat_crossproduct",
    "http://www.w3.org/2001/XMLSchema#float": "float",
    "http://www.w3.org/2001/XMLSchema#int": "int",
    "http://www.w3.org/2001/XMLSchema#long": "long",
    "https://w3id.org/cwl/salad#map": "map",
    "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened": "merge_flattened",
    "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested": "merge_nested",
    "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct": "nested_crossproduct",
    "https://w3id.org/cwl/salad#null": "null",
    "https://w3id.org/cwl/salad#record": "record",
    "https://w3id.org/cwl/cwl#stderr": "stderr",
    "https://w3id.org/cwl/cwl#stdout": "stdout",
    "http://www.w3.org/2001/XMLSchema#string": "string",
    "https://w3id.org/cwl/salad#union": "union",
    "https://w3id.org/cwl/cwl#v1.0": "v1.0",
    "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4",
}

strtype = _PrimitiveLoader(str)
inttype = _PrimitiveLoader(int)
floattype = _PrimitiveLoader(float)
booltype = _PrimitiveLoader(bool)
None_type = _PrimitiveLoader(type(None))
Any_type = _AnyLoader()
PrimitiveTypeLoader = _EnumLoader(
    (
        "null",
        "boolean",
        "int",
        "long",
        "float",
        "double",
        "string",
    ),
    "PrimitiveType",
)
"""
Names of salad data types (based on Avro schema declarations).

Refer to the [Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for
detailed information.

null: no value
boolean: a binary value
int: 32-bit signed integer
long: 64-bit signed integer
float: single precision (32-bit) IEEE 754 floating-point number
double: double precision (64-bit) IEEE 754 floating-point number
string: Unicode character sequence
"""
AnyLoader = _EnumLoader(("Any",), "Any")
"""
The **Any** type validates for any non-null value.
"""
RecordFieldLoader = _RecordLoader(RecordField, None, None)
RecordSchemaLoader = _RecordLoader(RecordSchema, None, None)
EnumSchemaLoader = _RecordLoader(EnumSchema, None, None)
ArraySchemaLoader = _RecordLoader(ArraySchema, None, None)
MapSchemaLoader = _RecordLoader(MapSchema, None, None)
UnionSchemaLoader = _RecordLoader(UnionSchema, None, None)
CWLTypeLoader = _EnumLoader(
    (
        "null",
        "boolean",
        "int",
        "long",
        "float",
        "double",
        "string",
        "File",
        "Directory",
    ),
    "CWLType",
)
"""
Extends primitive types with the concept of a file and directory as a builtin type.
File: A File object
Directory: A Directory object
"""
CWLArraySchemaLoader = _RecordLoader(CWLArraySchema, None, None)
CWLRecordFieldLoader = _RecordLoader(CWLRecordField, None, None)
CWLRecordSchemaLoader = _RecordLoader(CWLRecordSchema, None, None)
FileLoader = _RecordLoader(File, None, None)
DirectoryLoader = _RecordLoader(Directory, None, None)
CWLObjectTypeLoader = _UnionLoader((), "CWLObjectTypeLoader")
union_of_None_type_or_CWLObjectTypeLoader = _UnionLoader(
    (
        None_type,
        CWLObjectTypeLoader,
    )
)
array_of_union_of_None_type_or_CWLObjectTypeLoader = _ArrayLoader(
    union_of_None_type_or_CWLObjectTypeLoader
)
map_of_union_of_None_type_or_CWLObjectTypeLoader = _MapLoader(
    union_of_None_type_or_CWLObjectTypeLoader, "CWLInputFile", "@list", True
)
CWLInputFileLoader = map_of_union_of_None_type_or_CWLObjectTypeLoader
CWLVersionLoader = _EnumLoader(
    (
        "draft-2",
        "draft-3.dev1",
        "draft-3.dev2",
        "draft-3.dev3",
        "draft-3.dev4",
        "draft-3.dev5",
        "draft-3",
        "draft-4.dev1",
        "draft-4.dev2",
        "draft-4.dev3",
        "v1.0.dev4",
        "v1.0",
    ),
    "CWLVersion",
)
"""
Version symbols for published CWL document versions.
"""
ExpressionLoader = _ExpressionLoader(str)
InputRecordFieldLoader = _RecordLoader(InputRecordField, None, None)
InputRecordSchemaLoader = _RecordLoader(InputRecordSchema, None, None)
InputEnumSchemaLoader = _RecordLoader(InputEnumSchema, None, None)
InputArraySchemaLoader = _RecordLoader(InputArraySchema, None, None)
OutputRecordFieldLoader = _RecordLoader(OutputRecordField, None, None)
OutputRecordSchemaLoader = _RecordLoader(OutputRecordSchema, None, None)
OutputEnumSchemaLoader = _RecordLoader(OutputEnumSchema, None, None)
OutputArraySchemaLoader = _RecordLoader(OutputArraySchema, None, None)
InputParameterLoader = _RecordLoader(InputParameter, None, None)
OutputParameterLoader = _RecordLoader(OutputParameter, None, None)
InlineJavascriptRequirementLoader = _RecordLoader(
    InlineJavascriptRequirement, None, None
)
SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement, None, None)
EnvironmentDefLoader = _RecordLoader(EnvironmentDef, None, None)
CommandLineBindingLoader = _RecordLoader(CommandLineBinding, None, None)
CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding, None, None)
CommandInputRecordFieldLoader = _RecordLoader(CommandInputRecordField, None, None)
CommandInputRecordSchemaLoader = _RecordLoader(CommandInputRecordSchema, None, None)
CommandInputEnumSchemaLoader = _RecordLoader(CommandInputEnumSchema, None, None)
CommandInputArraySchemaLoader = _RecordLoader(CommandInputArraySchema, None, None)
CommandOutputRecordFieldLoader = _RecordLoader(CommandOutputRecordField, None, None)
CommandOutputRecordSchemaLoader = _RecordLoader(CommandOutputRecordSchema, None, None)
CommandOutputEnumSchemaLoader = _RecordLoader(CommandOutputEnumSchema, None, None)
CommandOutputArraySchemaLoader = _RecordLoader(CommandOutputArraySchema, None, None)
CommandInputParameterLoader = _RecordLoader(CommandInputParameter, None, None)
CommandOutputParameterLoader = _RecordLoader(CommandOutputParameter, None, None)
stdoutLoader = _EnumLoader(("stdout",), "stdout")
"""
Only valid as a `type` for a `CommandLineTool` output with no
`outputBinding` set.

The following
```
outputs:
  an_output_name:
    type: stdout

stdout: a_stdout_file
```
is equivalent to
```
outputs:
  an_output_name:
    type: File
    streamable: true
    outputBinding:
      glob: a_stdout_file

stdout: a_stdout_file
```

If there is no `stdout` name provided, a random filename will be created.
For example, the following
```
outputs:
  an_output_name:
    type: stdout
```
is equivalent to
```
outputs:
  an_output_name:
    type: File
    streamable: true
    outputBinding:
      glob: random_stdout_filenameABCDEFG

stdout: random_stdout_filenameABCDEFG
```
"""
stderrLoader = _EnumLoader(("stderr",), "stderr")
"""
Only valid as a `type` for a `CommandLineTool` output with no
`outputBinding` set.

The following
```
outputs:
  an_output_name:
  type: stderr

stderr: a_stderr_file
```
is equivalent to
```
outputs:
  an_output_name:
    type: File
    streamable: true
    outputBinding:
      glob: a_stderr_file

stderr: a_stderr_file
```

If there is no `stderr` name provided, a random filename will be created.
For example, the following
```
outputs:
  an_output_name:
    type: stderr
```
is equivalent to
```
outputs:
  an_output_name:
    type: File
    streamable: true
    outputBinding:
      glob: random_stderr_filenameABCDEFG

stderr: random_stderr_filenameABCDEFG
```
"""
CommandLineToolLoader = _RecordLoader(CommandLineTool, None, None)
DockerRequirementLoader = _RecordLoader(DockerRequirement, None, None)
SoftwareRequirementLoader = _RecordLoader(SoftwareRequirement, None, None)
SoftwarePackageLoader = _RecordLoader(SoftwarePackage, None, None)
DirentLoader = _RecordLoader(Dirent, None, None)
InitialWorkDirRequirementLoader = _RecordLoader(InitialWorkDirRequirement, None, None)
EnvVarRequirementLoader = _RecordLoader(EnvVarRequirement, None, None)
ShellCommandRequirementLoader = _RecordLoader(ShellCommandRequirement, None, None)
ResourceRequirementLoader = _RecordLoader(ResourceRequirement, None, None)
ExpressionToolOutputParameterLoader = _RecordLoader(
    ExpressionToolOutputParameter, None, None
)
ExpressionToolLoader = _RecordLoader(ExpressionTool, None, None)
LinkMergeMethodLoader = _EnumLoader(
    (
        "merge_nested",
        "merge_flattened",
    ),
    "LinkMergeMethod",
)
"""
The input link merge method, described in [WorkflowStepInput](#WorkflowStepInput).
"""
WorkflowOutputParameterLoader = _RecordLoader(WorkflowOutputParameter, None, None)
WorkflowStepInputLoader = _RecordLoader(WorkflowStepInput, None, None)
WorkflowStepOutputLoader = _RecordLoader(WorkflowStepOutput, None, None)
ScatterMethodLoader = _EnumLoader(
    (
        "dotproduct",
        "nested_crossproduct",
        "flat_crossproduct",
    ),
    "ScatterMethod",
)
"""
The scatter method, as described in [workflow step scatter](#WorkflowStep).
"""
WorkflowStepLoader = _RecordLoader(WorkflowStep, None, None)
WorkflowLoader = _RecordLoader(Workflow, None, None)
SubworkflowFeatureRequirementLoader = _RecordLoader(
    SubworkflowFeatureRequirement, None, None
)
ScatterFeatureRequirementLoader = _RecordLoader(ScatterFeatureRequirement, None, None)
MultipleInputFeatureRequirementLoader = _RecordLoader(
    MultipleInputFeatureRequirement, None, None
)
StepInputExpressionRequirementLoader = _RecordLoader(
    StepInputExpressionRequirement, None, None
)
array_of_strtype = _ArrayLoader(strtype)
union_of_None_type_or_strtype_or_array_of_strtype = _UnionLoader(
    (
        None_type,
        strtype,
        array_of_strtype,
    )
)
uri_strtype_True_False_None_None = _URILoader(strtype, True, False, None, None)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader(
    (
        PrimitiveTypeLoader,
        RecordSchemaLoader,
        EnumSchemaLoader,
        ArraySchemaLoader,
        MapSchemaLoader,
        UnionSchemaLoader,
        strtype,
    )
)
array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _ArrayLoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype
)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader(
    (
        PrimitiveTypeLoader,
        RecordSchemaLoader,
        EnumSchemaLoader,
        ArraySchemaLoader,
        MapSchemaLoader,
        UnionSchemaLoader,
        strtype,
        array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    )
)
typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    2,
    "v1.1",
)
array_of_RecordFieldLoader = _ArrayLoader(RecordFieldLoader)
union_of_None_type_or_array_of_RecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_RecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader = _IdMapLoader(
    union_of_None_type_or_array_of_RecordFieldLoader, "name", "type"
)
Record_nameLoader = _EnumLoader(("record",), "Record_name")
typedsl_Record_nameLoader_2 = _TypeDSLLoader(Record_nameLoader, 2, "v1.1")
union_of_None_type_or_strtype = _UnionLoader(
    (
        None_type,
        strtype,
    )
)
uri_union_of_None_type_or_strtype_True_False_None_None = _URILoader(
    union_of_None_type_or_strtype, True, False, None, None
)
uri_array_of_strtype_True_False_None_None = _URILoader(
    array_of_strtype, True, False, None, None
)
Enum_nameLoader = _EnumLoader(("enum",), "Enum_name")
typedsl_Enum_nameLoader_2 = _TypeDSLLoader(Enum_nameLoader, 2, "v1.1")
uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
Array_nameLoader = _EnumLoader(("array",), "Array_name")
typedsl_Array_nameLoader_2 = _TypeDSLLoader(Array_nameLoader, 2, "v1.1")
Map_nameLoader = _EnumLoader(("map",), "Map_name")
typedsl_Map_nameLoader_2 = _TypeDSLLoader(Map_nameLoader, 2, "v1.1")
Union_nameLoader = _EnumLoader(("union",), "Union_name")
typedsl_Union_nameLoader_2 = _TypeDSLLoader(Union_nameLoader, 2, "v1.1")
union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader(
    (
        PrimitiveTypeLoader,
        CWLRecordSchemaLoader,
        EnumSchemaLoader,
        CWLArraySchemaLoader,
        strtype,
    )
)
array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _ArrayLoader(
    union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype
)
union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader(
    (
        PrimitiveTypeLoader,
        CWLRecordSchemaLoader,
        EnumSchemaLoader,
        CWLArraySchemaLoader,
        strtype,
        array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype,
    )
)
uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
array_of_CWLRecordFieldLoader = _ArrayLoader(CWLRecordFieldLoader)
union_of_None_type_or_array_of_CWLRecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_CWLRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader = _IdMapLoader(
    union_of_None_type_or_array_of_CWLRecordFieldLoader, "name", "type"
)
File_classLoader = _EnumLoader(("File",), "File_class")
uri_File_classLoader_False_True_None_None = _URILoader(
    File_classLoader, False, True, None, None
)
uri_union_of_None_type_or_strtype_False_False_None_None = _URILoader(
    union_of_None_type_or_strtype, False, False, None, None
)
union_of_None_type_or_inttype = _UnionLoader(
    (
        None_type,
        inttype,
    )
)
union_of_FileLoader_or_DirectoryLoader = _UnionLoader(
    (
        FileLoader,
        DirectoryLoader,
    )
)
array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader(
    union_of_FileLoader_or_DirectoryLoader
)
union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader(
    (
        None_type,
        array_of_union_of_FileLoader_or_DirectoryLoader,
    )
)
uri_union_of_None_type_or_strtype_True_False_None_True = _URILoader(
    union_of_None_type_or_strtype, True, False, None, True
)
Directory_classLoader = _EnumLoader(("Directory",), "Directory_class")
uri_Directory_classLoader_False_True_None_None = _URILoader(
    Directory_classLoader, False, True, None, None
)
union_of_strtype_or_ExpressionLoader = _UnionLoader(
    (
        strtype,
        ExpressionLoader,
    )
)
array_of_union_of_strtype_or_ExpressionLoader = _ArrayLoader(
    union_of_strtype_or_ExpressionLoader
)
union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader = _UnionLoader(
    (
        None_type,
        strtype,
        ExpressionLoader,
        array_of_union_of_strtype_or_ExpressionLoader,
    )
)
union_of_None_type_or_booltype = _UnionLoader(
    (
        None_type,
        booltype,
    )
)
union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        InputRecordSchemaLoader,
        InputEnumSchemaLoader,
        InputArraySchemaLoader,
        strtype,
    )
)
array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _ArrayLoader(
    union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype
)
union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        InputRecordSchemaLoader,
        InputEnumSchemaLoader,
        InputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
union_of_None_type_or_CommandLineBindingLoader = _UnionLoader(
    (
        None_type,
        CommandLineBindingLoader,
    )
)
array_of_InputRecordFieldLoader = _ArrayLoader(InputRecordFieldLoader)
union_of_None_type_or_array_of_InputRecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_InputRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader = _IdMapLoader(
    union_of_None_type_or_array_of_InputRecordFieldLoader, "name", "type"
)
uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        OutputRecordSchemaLoader,
        OutputEnumSchemaLoader,
        OutputArraySchemaLoader,
        strtype,
    )
)
array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _ArrayLoader(
    union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype
)
union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        OutputRecordSchemaLoader,
        OutputEnumSchemaLoader,
        OutputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader(
    (
        None_type,
        CommandOutputBindingLoader,
    )
)
array_of_OutputRecordFieldLoader = _ArrayLoader(OutputRecordFieldLoader)
union_of_None_type_or_array_of_OutputRecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_OutputRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader = _IdMapLoader(
    union_of_None_type_or_array_of_OutputRecordFieldLoader, "name", "type"
)
uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader = _UnionLoader(
    (
        None_type,
        strtype,
        array_of_strtype,
        ExpressionLoader,
    )
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True = _URILoader(
    union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader,
    True,
    False,
    None,
    True,
)
union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        None_type,
        CWLTypeLoader,
        InputRecordSchemaLoader,
        InputEnumSchemaLoader,
        InputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
union_of_None_type_or_strtype_or_ExpressionLoader = _UnionLoader(
    (
        None_type,
        strtype,
        ExpressionLoader,
    )
)
uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True = _URILoader(
    union_of_None_type_or_strtype_or_ExpressionLoader, True, False, None, True
)
array_of_InputParameterLoader = _ArrayLoader(InputParameterLoader)
idmap_inputs_array_of_InputParameterLoader = _IdMapLoader(
    array_of_InputParameterLoader, "id", "type"
)
array_of_OutputParameterLoader = _ArrayLoader(OutputParameterLoader)
idmap_outputs_array_of_OutputParameterLoader = _IdMapLoader(
    array_of_OutputParameterLoader, "id", "type"
)
union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _UnionLoader(
    (
        InlineJavascriptRequirementLoader,
        SchemaDefRequirementLoader,
        DockerRequirementLoader,
        SoftwareRequirementLoader,
        InitialWorkDirRequirementLoader,
        EnvVarRequirementLoader,
        ShellCommandRequirementLoader,
        ResourceRequirementLoader,
        SubworkflowFeatureRequirementLoader,
        ScatterFeatureRequirementLoader,
        MultipleInputFeatureRequirementLoader,
        StepInputExpressionRequirementLoader,
    )
)
array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _ArrayLoader(
    union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader
)
union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _UnionLoader(
    (
        None_type,
        array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
    )
)
idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _IdMapLoader(
    union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,
    "class",
    "None",
)
union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type = _UnionLoader(
    (
        InlineJavascriptRequirementLoader,
        SchemaDefRequirementLoader,
        DockerRequirementLoader,
        SoftwareRequirementLoader,
        InitialWorkDirRequirementLoader,
        EnvVarRequirementLoader,
        ShellCommandRequirementLoader,
        ResourceRequirementLoader,
        SubworkflowFeatureRequirementLoader,
        ScatterFeatureRequirementLoader,
        MultipleInputFeatureRequirementLoader,
        StepInputExpressionRequirementLoader,
        Any_type,
    )
)
array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type = _ArrayLoader(
    union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type
)
union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type = _UnionLoader(
    (
        None_type,
        array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type,
    )
)
idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type = _IdMapLoader(
    union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_Any_type,
    "class",
    "None",
)
union_of_None_type_or_CWLVersionLoader = _UnionLoader(
    (
        None_type,
        CWLVersionLoader,
    )
)
uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None = _URILoader(
    union_of_None_type_or_CWLVersionLoader, False, True, None, None
)
InlineJavascriptRequirement_classLoader = _EnumLoader(
    ("InlineJavascriptRequirement",), "InlineJavascriptRequirement_class"
)
uri_InlineJavascriptRequirement_classLoader_False_True_None_None = _URILoader(
    InlineJavascriptRequirement_classLoader, False, True, None, None
)
union_of_None_type_or_array_of_strtype = _UnionLoader(
    (
        None_type,
        array_of_strtype,
    )
)
SchemaDefRequirement_classLoader = _EnumLoader(
    ("SchemaDefRequirement",), "SchemaDefRequirement_class"
)
uri_SchemaDefRequirement_classLoader_False_True_None_None = _URILoader(
    SchemaDefRequirement_classLoader, False, True, None, None
)
union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = (
    _UnionLoader(
        (
            InputRecordSchemaLoader,
            InputEnumSchemaLoader,
            InputArraySchemaLoader,
        )
    )
)
array_of_union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = _ArrayLoader(
    union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader
)
union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader(
    (
        None_type,
        strtype,
        ExpressionLoader,
        array_of_strtype,
    )
)
union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        CommandInputRecordSchemaLoader,
        CommandInputEnumSchemaLoader,
        CommandInputArraySchemaLoader,
        strtype,
    )
)
array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _ArrayLoader(
    union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype
)
union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        CommandInputRecordSchemaLoader,
        CommandInputEnumSchemaLoader,
        CommandInputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
array_of_CommandInputRecordFieldLoader = _ArrayLoader(CommandInputRecordFieldLoader)
union_of_None_type_or_array_of_CommandInputRecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_CommandInputRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader = (
    _IdMapLoader(
        union_of_None_type_or_array_of_CommandInputRecordFieldLoader, "name", "type"
    )
)
uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        CommandOutputRecordSchemaLoader,
        CommandOutputEnumSchemaLoader,
        CommandOutputArraySchemaLoader,
        strtype,
    )
)
array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _ArrayLoader(
    union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype
)
union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        CWLTypeLoader,
        CommandOutputRecordSchemaLoader,
        CommandOutputEnumSchemaLoader,
        CommandOutputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
array_of_CommandOutputRecordFieldLoader = _ArrayLoader(CommandOutputRecordFieldLoader)
union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = _UnionLoader(
    (
        None_type,
        array_of_CommandOutputRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = (
    _IdMapLoader(
        union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, "name", "type"
    )
)
uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader(
    union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        None_type,
        CWLTypeLoader,
        CommandInputRecordSchemaLoader,
        CommandInputEnumSchemaLoader,
        CommandInputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        None_type,
        CWLTypeLoader,
        stdoutLoader,
        stderrLoader,
        CommandOutputRecordSchemaLoader,
        CommandOutputEnumSchemaLoader,
        CommandOutputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
CommandLineTool_classLoader = _EnumLoader(("CommandLineTool",), "CommandLineTool_class")
uri_CommandLineTool_classLoader_False_True_None_None = _URILoader(
    CommandLineTool_classLoader, False, True, None, None
)
array_of_CommandInputParameterLoader = _ArrayLoader(CommandInputParameterLoader)
idmap_inputs_array_of_CommandInputParameterLoader = _IdMapLoader(
    array_of_CommandInputParameterLoader, "id", "type"
)
array_of_CommandOutputParameterLoader = _ArrayLoader(CommandOutputParameterLoader)
idmap_outputs_array_of_CommandOutputParameterLoader = _IdMapLoader(
    array_of_CommandOutputParameterLoader, "id", "type"
)
union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader(
    (
        strtype,
        ExpressionLoader,
        CommandLineBindingLoader,
    )
)
array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = (
    _ArrayLoader(union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader)
)
union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader(
    (
        None_type,
        array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader,
    )
)
array_of_inttype = _ArrayLoader(inttype)
union_of_None_type_or_array_of_inttype = _UnionLoader(
    (
        None_type,
        array_of_inttype,
    )
)
DockerRequirement_classLoader = _EnumLoader(
    ("DockerRequirement",), "DockerRequirement_class"
)
uri_DockerRequirement_classLoader_False_True_None_None = _URILoader(
    DockerRequirement_classLoader, False, True, None, None
)
SoftwareRequirement_classLoader = _EnumLoader(
    ("SoftwareRequirement",), "SoftwareRequirement_class"
)
uri_SoftwareRequirement_classLoader_False_True_None_None = _URILoader(
    SoftwareRequirement_classLoader, False, True, None, None
)
array_of_SoftwarePackageLoader = _ArrayLoader(SoftwarePackageLoader)
idmap_packages_array_of_SoftwarePackageLoader = _IdMapLoader(
    array_of_SoftwarePackageLoader, "package", "specs"
)
uri_union_of_None_type_or_array_of_strtype_False_False_None_True = _URILoader(
    union_of_None_type_or_array_of_strtype, False, False, None, True
)
InitialWorkDirRequirement_classLoader = _EnumLoader(
    ("InitialWorkDirRequirement",), "InitialWorkDirRequirement_class"
)
uri_InitialWorkDirRequirement_classLoader_False_True_None_None = _URILoader(
    InitialWorkDirRequirement_classLoader, False, True, None, None
)
union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _UnionLoader(
    (
        FileLoader,
        DirectoryLoader,
        DirentLoader,
        strtype,
        ExpressionLoader,
    )
)
array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _ArrayLoader(
    union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader
)
union_of_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader = _UnionLoader(
    (
        array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader,
        strtype,
        ExpressionLoader,
    )
)
EnvVarRequirement_classLoader = _EnumLoader(
    ("EnvVarRequirement",), "EnvVarRequirement_class"
)
uri_EnvVarRequirement_classLoader_False_True_None_None = _URILoader(
    EnvVarRequirement_classLoader, False, True, None, None
)
array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader)
idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader(
    array_of_EnvironmentDefLoader, "envName", "envValue"
)
ShellCommandRequirement_classLoader = _EnumLoader(
    ("ShellCommandRequirement",), "ShellCommandRequirement_class"
)
uri_ShellCommandRequirement_classLoader_False_True_None_None = _URILoader(
    ShellCommandRequirement_classLoader, False, True, None, None
)
ResourceRequirement_classLoader = _EnumLoader(
    ("ResourceRequirement",), "ResourceRequirement_class"
)
uri_ResourceRequirement_classLoader_False_True_None_None = _URILoader(
    ResourceRequirement_classLoader, False, True, None, None
)
union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader = _UnionLoader(
    (
        None_type,
        inttype,
        strtype,
        ExpressionLoader,
    )
)
union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader(
    (
        None_type,
        CWLTypeLoader,
        OutputRecordSchemaLoader,
        OutputEnumSchemaLoader,
        OutputArraySchemaLoader,
        strtype,
        array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype,
    )
)
typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(
    union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype,
    2,
    "v1.1",
)
ExpressionTool_classLoader = _EnumLoader(("ExpressionTool",), "ExpressionTool_class")
uri_ExpressionTool_classLoader_False_True_None_None = _URILoader(
    ExpressionTool_classLoader, False, True, None, None
)
array_of_ExpressionToolOutputParameterLoader = _ArrayLoader(
    ExpressionToolOutputParameterLoader
)
idmap_outputs_array_of_ExpressionToolOutputParameterLoader = _IdMapLoader(
    array_of_ExpressionToolOutputParameterLoader, "id", "type"
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None = _URILoader(
    union_of_None_type_or_strtype_or_array_of_strtype, False, False, 1, None
)
union_of_None_type_or_LinkMergeMethodLoader = _UnionLoader(
    (
        None_type,
        LinkMergeMethodLoader,
    )
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None = _URILoader(
    union_of_None_type_or_strtype_or_array_of_strtype, False, False, 2, None
)
array_of_WorkflowStepInputLoader = _ArrayLoader(WorkflowStepInputLoader)
idmap_in__array_of_WorkflowStepInputLoader = _IdMapLoader(
    array_of_WorkflowStepInputLoader, "id", "source"
)
union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader(
    (
        strtype,
        WorkflowStepOutputLoader,
    )
)
array_of_union_of_strtype_or_WorkflowStepOutputLoader = _ArrayLoader(
    union_of_strtype_or_WorkflowStepOutputLoader
)
union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader(
    (array_of_union_of_strtype_or_WorkflowStepOutputLoader,)
)
uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None = _URILoader(
    union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader,
    True,
    False,
    None,
    None,
)
array_of_Any_type = _ArrayLoader(Any_type)
union_of_None_type_or_array_of_Any_type = _UnionLoader(
    (
        None_type,
        array_of_Any_type,
    )
)
idmap_hints_union_of_None_type_or_array_of_Any_type = _IdMapLoader(
    union_of_None_type_or_array_of_Any_type, "class", "None"
)
union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader = (
    _UnionLoader(
        (
            strtype,
            CommandLineToolLoader,
            ExpressionToolLoader,
            WorkflowLoader,
        )
    )
)
uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_False_False_None_None = _URILoader(
    union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
    False,
    False,
    None,
    None,
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None = _URILoader(
    union_of_None_type_or_strtype_or_array_of_strtype, False, False, 0, None
)
union_of_None_type_or_ScatterMethodLoader = _UnionLoader(
    (
        None_type,
        ScatterMethodLoader,
    )
)
uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None = _URILoader(
    union_of_None_type_or_ScatterMethodLoader, False, True, None, None
)
Workflow_classLoader = _EnumLoader(("Workflow",), "Workflow_class")
uri_Workflow_classLoader_False_True_None_None = _URILoader(
    Workflow_classLoader, False, True, None, None
)
array_of_WorkflowOutputParameterLoader = _ArrayLoader(WorkflowOutputParameterLoader)
idmap_outputs_array_of_WorkflowOutputParameterLoader = _IdMapLoader(
    array_of_WorkflowOutputParameterLoader, "id", "type"
)
array_of_WorkflowStepLoader = _ArrayLoader(WorkflowStepLoader)
union_of_array_of_WorkflowStepLoader = _UnionLoader((array_of_WorkflowStepLoader,))
idmap_steps_union_of_array_of_WorkflowStepLoader = _IdMapLoader(
    union_of_array_of_WorkflowStepLoader, "id", "None"
)
SubworkflowFeatureRequirement_classLoader = _EnumLoader(
    ("SubworkflowFeatureRequirement",), "SubworkflowFeatureRequirement_class"
)
uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None = _URILoader(
    SubworkflowFeatureRequirement_classLoader, False, True, None, None
)
ScatterFeatureRequirement_classLoader = _EnumLoader(
    ("ScatterFeatureRequirement",), "ScatterFeatureRequirement_class"
)
uri_ScatterFeatureRequirement_classLoader_False_True_None_None = _URILoader(
    ScatterFeatureRequirement_classLoader, False, True, None, None
)
MultipleInputFeatureRequirement_classLoader = _EnumLoader(
    ("MultipleInputFeatureRequirement",), "MultipleInputFeatureRequirement_class"
)
uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None = _URILoader(
    MultipleInputFeatureRequirement_classLoader, False, True, None, None
)
StepInputExpressionRequirement_classLoader = _EnumLoader(
    ("StepInputExpressionRequirement",), "StepInputExpressionRequirement_class"
)
uri_StepInputExpressionRequirement_classLoader_False_True_None_None = _URILoader(
    StepInputExpressionRequirement_classLoader, False, True, None, None
)
union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader = _UnionLoader(
    (
        CommandLineToolLoader,
        ExpressionToolLoader,
        WorkflowLoader,
    )
)
array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader = (
    _ArrayLoader(
        union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader
    )
)
union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader = _UnionLoader(
    (
        CommandLineToolLoader,
        ExpressionToolLoader,
        WorkflowLoader,
        array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
    )
)

CWLObjectTypeLoader.add_loaders(
    (
        booltype,
        inttype,
        floattype,
        strtype,
        FileLoader,
        DirectoryLoader,
        array_of_union_of_None_type_or_CWLObjectTypeLoader,
        map_of_union_of_None_type_or_CWLObjectTypeLoader,
    )
)


def load_document(
    doc: Any,
    baseuri: Optional[str] = None,
    loadingOptions: Optional[LoadingOptions] = None,
) -> Any:
    if baseuri is None:
        baseuri = file_uri(os.getcwd()) + "/"
    if loadingOptions is None:
        loadingOptions = LoadingOptions()
    result, metadata = _document_load(
        union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
        doc,
        baseuri,
        loadingOptions,
    )
    return result


def load_document_with_metadata(
    doc: Any,
    baseuri: Optional[str] = None,
    loadingOptions: Optional[LoadingOptions] = None,
    addl_metadata_fields: Optional[MutableSequence[str]] = None,
) -> Any:
    if baseuri is None:
        baseuri = file_uri(os.getcwd()) + "/"
    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=baseuri)
    return _document_load(
        union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
        doc,
        baseuri,
        loadingOptions,
        addl_metadata_fields=addl_metadata_fields,
    )


def load_document_by_string(
    string: Any,
    uri: str,
    loadingOptions: Optional[LoadingOptions] = None,
) -> Any:
    yaml = yaml_no_ts()
    result = yaml.load(string)
    add_lc_filename(result, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)

    result, metadata = _document_load(
        union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
        result,
        uri,
        loadingOptions,
    )
    return result


def load_document_by_yaml(
    yaml: Any,
    uri: str,
    loadingOptions: Optional[LoadingOptions] = None,
) -> Any:
    """
    Shortcut to load via a YAML object.
    yaml: must be from ruamel.yaml.main.YAML.load with preserve_quotes=True
    """
    add_lc_filename(yaml, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)

    result, metadata = _document_load(
        union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader,
        yaml,
        uri,
        loadingOptions,
    )
    return result
