from capanno_utils.classes.cwl.common_workflow_language_mixins import CommandLineToolMixin, \
CommandInputParameterMixin, SchemaDefRequirementMixin, CommandLineBindingMixin, \
CommandOutputParameterMixin, WorkflowMixin, InputParameterMixin, WorkflowOutputParameterMixin, \
WorkflowStepMixin, WorkflowStepInputMixin
#
# 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 os
import re
import uuid as _uuid__  # pylint: disable=unused-import # noqa: F401
from io import StringIO
from typing import (
    Any,
    Dict,
    List,
    MutableMapping,
    MutableSequence,
    Optional,
    Sequence,
    Tuple,
    Type,
    Union,
)
from urllib.parse import quote, urlsplit, urlunsplit
from urllib.request import pathname2url

from ruamel import yaml
from ruamel.yaml.comments import CommentedMap

from schema_salad.exceptions import SchemaSaladException, ValidationException
from schema_salad.fetcher import DefaultFetcher, Fetcher
from schema_salad.sourceline import SourceLine, add_lc_filename

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


class Savable:
    @classmethod
    def fromDoc(cls, _doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Savable
        pass

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, str]
        pass


class LoadingOptions:
    def __init__(
        self,
        fetcher=None,  # type: Optional[Fetcher]
        namespaces=None,  # type: Optional[Dict[str, str]]
        schemas=None,  # type: Optional[Dict[str, str]]
        fileuri=None,  # type: Optional[str]
        copyfrom=None,  # type: Optional[LoadingOptions]
        original_doc=None,  # type: Optional[Any]
    ):  # type: (...) -> None
        self.idx = {}  # type: Dict[str, Dict[str, Any]]
        self.fileuri = fileuri  # type: Optional[str]
        self.namespaces = namespaces
        self.schemas = schemas
        self.original_doc = original_doc
        if copyfrom is not None:
            self.idx = copyfrom.idx
            if fetcher is None:
                fetcher = copyfrom.fetcher
            if fileuri is None:
                self.fileuri = copyfrom.fileuri
            if namespaces is None:
                self.namespaces = copyfrom.namespaces
            if schemas is None:
                self.schemas = copyfrom.schemas

        if fetcher is None:
            import requests
            from cachecontrol.caches import FileCache
            from cachecontrol.wrapper import CacheControl

            if "HOME" in os.environ:
                session = CacheControl(
                    requests.Session(),
                    cache=FileCache(
                        os.path.join(os.environ["HOME"], ".cache", "salad")
                    ),
                )
            elif "TMPDIR" in os.environ:
                session = CacheControl(
                    requests.Session(),
                    cache=FileCache(
                        os.path.join(os.environ["TMPDIR"], ".cache", "salad")
                    ),
                )
            else:
                session = CacheControl(
                    requests.Session(), cache=FileCache("/tmp", ".cache", "salad")
                )
            self.fetcher = DefaultFetcher({}, session)  # type: Fetcher
        else:
            self.fetcher = fetcher

        self.vocab = _vocab
        self.rvocab = _rvocab

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


def load_field(val, fieldtype, baseuri, loadingOptions):
    # type: (Union[str, Dict[str, str]], _Loader, str, LoadingOptions) -> Any
    if isinstance(val, MutableMapping):
        if "$import" in val:
            if loadingOptions.fileuri is None:
                raise SchemaSaladException("Cannot load $import without fileuri")
            return _document_load_by_url(
                fieldtype,
                loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$import"]),
                loadingOptions,
            )
        elif "$include" in val:
            if loadingOptions.fileuri is None:
                raise SchemaSaladException("Cannot load $import without fileuri")
            val = loadingOptions.fetcher.fetch_text(
                loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$include"])
            )
    return fieldtype.load(val, baseuri, loadingOptions)


save_type = Union[Dict[str, str], List[Union[Dict[str, str], List[Any], None]], None]


def save(
    val,  # type: Optional[Union[Savable, MutableSequence[Savable]]]
    top=True,  # type: bool
    base_url="",  # type: str
    relative_uris=True,  # type: bool
):  # type: (...) -> save_type

    if isinstance(val, Savable):
        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
    return val


def expand_url(
    url,  # type: str
    base_url,  # type: str
    loadingOptions,  # type: LoadingOptions
    scoped_id=False,  # type: bool
    vocab_term=False,  # type: bool
    scoped_ref=None,  # type: Optional[int]
):
    # type: (...) -> 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 ["http", "https", "file"])
        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}' not in vocabulary")

    return url


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


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


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

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

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


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

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        if not isinstance(doc, MutableSequence):
            raise ValidationException("Expected a list")
        r = []  # type: List[Any]
        errors = []  # type: List[SchemaSaladException]
        for i in range(0, len(doc)):
            try:
                lf = load_field(
                    doc[i], _UnionLoader((self, self.items)), baseuri, loadingOptions
                )
                if isinstance(lf, MutableSequence):
                    r.extend(lf)
                else:
                    r.append(lf)
            except ValidationException as e:
                errors.append(e.with_sourceline(SourceLine(doc, i, str)))
        if errors:
            raise ValidationException("", None, errors)
        return r

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


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

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


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

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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] = {}
                    if "pattern" in d:
                        new_dict["pattern"] = d.pop("pattern")
                    else:
                        raise ValidationException(
                            "Missing pattern in secondaryFiles specification entry: {}".format(
                                d
                            )
                        )
                    new_dict["required"] = (
                        d.pop("required") if "required" in d else None
                    )

                    if len(d):
                        raise ValidationException(
                            "Unallowed values in secondaryFiles specification entry: {}".format(
                                d
                            )
                        )

                else:
                    raise ValidationException(
                        "Expected a string or sequence of (strings or mappings)."
                    )
        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)


class _RecordLoader(_Loader):
    def __init__(self, classtype):
        # type: (Type[Savable]) -> None
        self.classtype = classtype

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        if not isinstance(doc, MutableMapping):
            raise ValidationException("Expected a dict")
        return self.classtype.fromDoc(doc, baseuri, loadingOptions, docRoot=docRoot)

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


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

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        if not isinstance(doc, str):
            raise ValidationException("Expected a str")
        return doc


class _UnionLoader(_Loader):
    def __init__(self, alternates):
        # type: (Sequence[_Loader]) -> None
        self.alternates = alternates

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        errors = []
        for t in self.alternates:
            try:
                return t.load(doc, baseuri, loadingOptions, docRoot=docRoot)
            except ValidationException as e:
                errors.append(
                    ValidationException(f"tried {t.__class__.__name__} but", None, [e])
                )
        raise ValidationException("", None, errors, "-")

    def __repr__(self):  # type: () -> str
        return " | ".join(str(a) for a in self.alternates)


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

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        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,
            )
        return self.inner.load(doc, baseuri, loadingOptions)


class _TypeDSLLoader(_Loader):
    typeDSLregex = re.compile(r"^([^[?]+)(\[\])?(\?)?$")

    def __init__(self, inner, refScope):
        # type: (_Loader, Union[int, None]) -> None
        self.inner = inner
        self.refScope = refScope

    def resolve(
        self,
        doc,  # type: str
        baseuri,  # type: str
        loadingOptions,  # type: LoadingOptions
    ):
        # type: (...) -> Union[List[Union[Dict[str, str], str]], Dict[str, str], str]
        m = self.typeDSLregex.match(doc)
        if m:
            group1 = m.group(1)
            assert group1 is not None
            first = expand_url(
                group1, baseuri, loadingOptions, False, True, self.refScope
            )
            second = third = None
            if bool(m.group(2)):
                second = {"type": "array", "items": first}
                # second = CommentedMap((("type", "array"),
                #                       ("items", first)))
                # second.lc.add_kv_line_col("type", lc)
                # second.lc.add_kv_line_col("items", lc)
                # second.lc.filename = filename
            if bool(m.group(3)):
                third = ["null", second or first]
                # third = CommentedSeq(["null", second or first])
                # third.lc.add_kv_line_col(0, lc)
                # third.lc.add_kv_line_col(1, lc)
                # third.lc.filename = filename
            return third or second or first
        return doc

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        if isinstance(doc, MutableSequence):
            r = []  # type: 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)


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

    def load(self, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Any
        if isinstance(doc, MutableMapping):
            r = []  # type: 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)


def _document_load(loader, doc, baseuri, loadingOptions):
    # type: (_Loader, Any, str, LoadingOptions) -> Any
    if isinstance(doc, str):
        return _document_load_by_url(
            loader, loadingOptions.fetcher.urljoin(baseuri, doc), loadingOptions
        )

    if isinstance(doc, MutableMapping):
        if "$namespaces" in doc or "$schemas" in doc:
            loadingOptions = LoadingOptions(
                copyfrom=loadingOptions,
                namespaces=doc.get("$namespaces", None),
                schemas=doc.get("$schemas", None),
            )
            doc = {k: v for k, v in doc.items() if k not in ["$namespaces", "$schemas"]}

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

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

    if isinstance(doc, MutableSequence):
        return loader.load(doc, baseuri, loadingOptions)

    raise ValidationException("Oops, we shouldn't be here!")


def _document_load_by_url(loader, url, loadingOptions):
    # type: (_Loader, str, LoadingOptions) -> Any
    if url in loadingOptions.idx:
        return _document_load(loader, loadingOptions.idx[url], url, loadingOptions)

    text = loadingOptions.fetcher.fetch_text(url)
    if isinstance(text, bytes):
        textIO = StringIO(text.decode("utf-8"))
    else:
        textIO = StringIO(text)
    textIO.name = str(url)
    result = yaml.main.round_trip_load(textIO, preserve_quotes=True)
    add_lc_filename(result, url)

    loadingOptions.idx[url] = result

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

    return _document_load(loader, result, url, loadingOptions)


def file_uri(path, split_frag=False):  # type: (str, bool) -> str
    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}"
    else:
        return f"file://{urlpath}{frag}"


def prefix_url(url, namespaces):  # type: (str, Dict[str, str]) -> str
    for k, v in namespaces.items():
        if url.startswith(v):
            return k + ":" + url[len(v) :]
    return url


def save_relative_uri(uri, base_url, scoped_id, ref_scope, relative_uris):
    # type: (str, str, bool, Optional[int], bool) -> Union[str, List[str]]
    if not relative_uris or uri == base_url:
        return uri
    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):
        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) :]
            else:
                return urisplit.fragment
        return uri
    else:
        return save(uri, top=False, base_url=base_url)


class Documented(Savable):
    pass


class RecordField(Documented):
    """
A field of a record.
    """
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                raise ValidationException("Missing name")
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_2, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'RecordField'", None, _errors__)
        return cls(doc=doc, name=name, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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(Savable):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `fields` field is not valid because:",
                        SourceLine(_doc, 'fields', str),
                        [e]
                    )
                )
        else:
            fields = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'RecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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(Savable):
    """
Define an enumerated type.

    """
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.symbols = symbols
        self.type = type

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

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            symbols = load_field(_doc.get(
                'symbols'), uri_array_of_strtype_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `symbols` field is not valid because:",
                    SourceLine(_doc, 'symbols', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `symbols`, `type`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'EnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.symbols is not None:
            u = save_relative_uri(
                self.symbols,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['symbols'] = 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(['symbols', 'type'])


class ArraySchema(Savable):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type = type

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

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            items = load_field(_doc.get(
                'items'), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_False_True_2, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `items` field is not valid because:",
                    SourceLine(_doc, 'items', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ArraySchema'", None, _errors__)
        return cls(items=items, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.items is not None:
            u = save_relative_uri(
                self.items,
                base_url,
                False,
                2,
                relative_uris)
            if u:
                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 File(Savable):
    """
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=None,  # type: Any
        path=None,  # type: Any
        basename=None,  # type: Any
        dirname=None,  # type: Any
        nameroot=None,  # type: Any
        nameext=None,  # type: Any
        checksum=None,  # type: Any
        size=None,  # type: Any
        secondaryFiles=None,  # type: Any
        format=None,  # type: Any
        contents=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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

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

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

        if _doc.get('class') != 'File':
            raise ValidationException("Not a File")

        if 'location' in _doc:
            try:
                location = load_field(_doc.get(
                    'location'), uri_union_of_None_type_or_strtype_False_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `contents` field is not valid because:",
                        SourceLine(_doc, 'contents', str),
                        [e]
                    )
                )
        else:
            contents = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'File'", None, _errors__)
        return 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)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                r['location'] = u

        if self.path is not None:
            u = save_relative_uri(
                self.path,
                base_url,
                False,
                None,
                relative_uris)
            if u:
                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)
            if u:
                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(Savable):
    """
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=None,  # type: Any
        path=None,  # type: Any
        basename=None,  # type: Any
        listing=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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

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

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

        if _doc.get('class') != 'Directory':
            raise ValidationException("Not a Directory")

        if 'location' in _doc:
            try:
                location = load_field(_doc.get(
                    'location'), uri_union_of_None_type_or_strtype_False_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `listing` field is not valid because:",
                        SourceLine(_doc, 'listing', str),
                        [e]
                    )
                )
        else:
            listing = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'Directory'", None, _errors__)
        return cls(location=location, path=path, basename=basename, listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                r['location'] = u

        if self.path is not None:
            u = save_relative_uri(
                self.path,
                base_url,
                False,
                None,
                relative_uris)
            if u:
                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 Labeled(Savable):
    pass


class Identified(Savable):
    pass


class LoadContents(Savable):
    pass


class FieldBase(Labeled):
    pass


class InputFormat(Savable):
    pass


class OutputFormat(Savable):
    pass


class Parameter(FieldBase, Documented, Identified):
    """
Define an input or output parameter to a process.

    """
    pass


class InputBinding(Savable):
    def __init__(
        self,
        loadContents=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.loadContents = loadContents

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> InputBinding

        _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputBinding'", None, _errors__)
        return cls(loadContents=loadContents, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)

        # 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'])


class IOSchema(Labeled, Documented):
    pass


class InputSchema(IOSchema):
    pass


class OutputSchema(IOSchema):
    pass


class InputRecordField(RecordField, FieldBase, InputFormat, LoadContents):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        format=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type = type
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.format = format
        self.loadContents = loadContents
        self.loadListing = loadListing

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                raise ValidationException("Missing name")
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `streamable` field is not valid because:",
                        SourceLine(_doc, 'streamable', str),
                        [e]
                    )
                )
        else:
            streamable = 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputRecordField'", None, _errors__)
        return cls(doc=doc, name=name, type=type, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.label is not None:
            r['label'] = save(
                self.label,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.secondaryFiles is not None:
            r['secondaryFiles'] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.streamable is not None:
            r['streamable'] = save(
                self.streamable,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.format is not None:
            u = save_relative_uri(
                self.format,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                r['format'] = u

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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', 'label', 'secondaryFiles', 'streamable', 'format', 'loadContents', 'loadListing'])


class InputRecordSchema(RecordSchema, InputSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `fields` field is not valid because:",
                        SourceLine(_doc, 'fields', str),
                        [e]
                    )
                )
        else:
            fields = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)

        if self.doc is not None:
            r['doc'] = save(
                self.doc,
                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', 'doc', 'name'])


class InputEnumSchema(EnumSchema, InputSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.symbols = symbols
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            symbols = load_field(_doc.get(
                'symbols'), uri_array_of_strtype_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `symbols` field is not valid because:",
                    SourceLine(_doc, 'symbols', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `symbols`, `type`, `label`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.symbols is not None:
            u = save_relative_uri(
                self.symbols,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['symbols', 'type', 'label', 'doc', 'name'])


class InputArraySchema(ArraySchema, InputSchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

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

        _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            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, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `items` field is not valid because:",
                    SourceLine(_doc, 'items', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.items is not None:
            u = save_relative_uri(
                self.items,
                self.name,
                False,
                2,
                relative_uris)
            if u:
                r['items'] = 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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['items', 'type', 'label', 'doc', 'name'])


class OutputRecordField(RecordField, FieldBase, OutputFormat):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        format=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type = type
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.format = format

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                raise ValidationException("Missing name")
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `streamable` field is not valid because:",
                        SourceLine(_doc, 'streamable', str),
                        [e]
                    )
                )
        else:
            streamable = None
        if 'format' in _doc:
            try:
                format = load_field(_doc.get(
                    'format'), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `secondaryFiles`, `streamable`, `format`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputRecordField'", None, _errors__)
        return cls(doc=doc, name=name, type=type, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.label is not None:
            r['label'] = save(
                self.label,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.secondaryFiles is not None:
            r['secondaryFiles'] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.streamable is not None:
            r['streamable'] = save(
                self.streamable,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.format is not None:
            u = save_relative_uri(
                self.format,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                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(['doc', 'name', 'type', 'label', 'secondaryFiles', 'streamable', 'format'])


class OutputRecordSchema(RecordSchema, OutputSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

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

        _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        if 'fields' in _doc:
            try:
                fields = load_field(_doc.get(
                    'fields'), idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `fields` field is not valid because:",
                        SourceLine(_doc, 'fields', str),
                        [e]
                    )
                )
        else:
            fields = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)

        if self.doc is not None:
            r['doc'] = save(
                self.doc,
                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', 'doc', 'name'])


class OutputEnumSchema(EnumSchema, OutputSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.symbols = symbols
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            symbols = load_field(_doc.get(
                'symbols'), uri_array_of_strtype_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `symbols` field is not valid because:",
                    SourceLine(_doc, 'symbols', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `symbols`, `type`, `label`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.symbols is not None:
            u = save_relative_uri(
                self.symbols,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['symbols', 'type', 'label', 'doc', 'name'])


class OutputArraySchema(ArraySchema, OutputSchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

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

        _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            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, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `items` field is not valid because:",
                    SourceLine(_doc, 'items', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.items is not None:
            u = save_relative_uri(
                self.items,
                self.name,
                False,
                2,
                relative_uris)
            if u:
                r['items'] = 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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['items', 'type', 'label', 'doc', 'name'])


class InputParameter(InputParameterMixin,Parameter, InputFormat, LoadContents):
    pass


class OutputParameter(Parameter, OutputFormat):
    pass


class ProcessRequirement(Savable):
    """
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(Identified, Labeled, Documented):
    """

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=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "InlineJavascriptRequirement"
        self.expressionLib = expressionLib

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

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

        if _doc.get('class') != 'InlineJavascriptRequirement':
            raise ValidationException("Not a InlineJavascriptRequirement")

        if 'expressionLib' in _doc:
            try:
                expressionLib = load_field(_doc.get(
                    'expressionLib'), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `expressionLib` field is not valid because:",
                        SourceLine(_doc, 'expressionLib', str),
                        [e]
                    )
                )
        else:
            expressionLib = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InlineJavascriptRequirement'", None, _errors__)
        return cls(expressionLib=expressionLib, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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 CommandInputSchema(Savable):
    pass


class SchemaDefRequirement(SchemaDefRequirementMixin,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.

- **Type definitions are allowed for `enum` and `record` types only.**
- Type definitions may be shared by defining them in a file and then
  `$include`-ing them in the `types` field.
- A file can contain a list of type definitions

    """
    def __init__(
        self,
        types,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SchemaDefRequirement"
        self.types = types

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

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

        if _doc.get('class') != 'SchemaDefRequirement':
            raise ValidationException("Not a SchemaDefRequirement")

        try:
            types = load_field(_doc.get(
                'types'), array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `types` field is not valid because:",
                    SourceLine(_doc, 'types', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'SchemaDefRequirement'", None, _errors__)
        return cls(types=types, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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 SecondaryFileSchema(Savable):
    """
Secondary files are specified using the following micro-DSL for secondary files:

* If the value is a string, it is transformed to an object with two fields
  `pattern` and `required`
* By default, the value of `required` is `null`
  (this indicates default behavior, which may be based on the context)
* If the value ends with a question mark `?` the question mark is
  stripped off and the value of the field `required` is set to `False`
* The remaining value is assigned to the field `pattern`

For implementation details and examples, please see
[this section](SchemaSalad.html#Domain_Specific_Language_for_secondary_files)
in the Schema Salad specification.

    """
    def __init__(
        self,
        pattern,  # type: Any
        required=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.pattern = pattern
        self.required = required

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> SecondaryFileSchema

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            pattern = load_field(_doc.get(
                'pattern'), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `pattern` field is not valid because:",
                    SourceLine(_doc, 'pattern', str),
                    [e]
                )
            )
        if 'required' in _doc:
            try:
                required = load_field(_doc.get(
                    'required'), union_of_None_type_or_booltype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `required` field is not valid because:",
                        SourceLine(_doc, 'required', str),
                        [e]
                    )
                )
        else:
            required = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `pattern`, `required`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'SecondaryFileSchema'", None, _errors__)
        return cls(pattern=pattern, required=required, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.pattern is not None:
            r['pattern'] = save(
                self.pattern,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris)

        if self.required is not None:
            r['required'] = save(
                self.required,
                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(['pattern', 'required'])


class LoadListingRequirement(ProcessRequirement):
    """
Specify the desired behavior for loading the `listing` field of
a Directory object for use by expressions.

    """
    def __init__(
        self,
        loadListing=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "LoadListingRequirement"
        self.loadListing = loadListing

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> LoadListingRequirement

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

        if _doc.get('class') != 'LoadListingRequirement':
            raise ValidationException("Not a LoadListingRequirement")

        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `loadListing`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'LoadListingRequirement'", None, _errors__)
        return cls(loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'LoadListingRequirement'

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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', 'loadListing'])


class EnvironmentDef(Savable):
    """
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,  # type: Any
        envValue,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.envName = envName
        self.envValue = envValue

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

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            envName = load_field(_doc.get(
                'envName'), strtype, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `envName` field is not valid because:",
                    SourceLine(_doc, 'envName', str),
                    [e]
                )
            )
        try:
            envValue = load_field(_doc.get(
                'envValue'), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `envValue` field is not valid because:",
                    SourceLine(_doc, 'envValue', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'EnvironmentDef'", None, _errors__)
        return cls(envName=envName, envValue=envValue, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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(CommandLineBindingMixin,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=None,  # type: Any
        position=None,  # type: Any
        prefix=None,  # type: Any
        separate=None,  # type: Any
        itemSeparator=None,  # type: Any
        valueFrom=None,  # type: Any
        shellQuote=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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)
            except ValidationException as e:
                _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_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `shellQuote` field is not valid because:",
                        SourceLine(_doc, 'shellQuote', str),
                        [e]
                    )
                )
        else:
            shellQuote = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

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

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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(LoadContents):
    """
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,
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        glob=None,  # type: Any
        outputEval=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.loadContents = loadContents
        self.loadListing = loadListing
        self.glob = glob
        self.outputEval = outputEval

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

        _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `glob` field is not valid because:",
                        SourceLine(_doc, 'glob', str),
                        [e]
                    )
                )
        else:
            glob = None
        if 'outputEval' in _doc:
            try:
                outputEval = load_field(_doc.get(
                    'outputEval'), union_of_None_type_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `outputEval` field is not valid because:",
                        SourceLine(_doc, 'outputEval', str),
                        [e]
                    )
                )
        else:
            outputEval = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `loadListing`, `glob`, `outputEval`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputBinding'", None, _errors__)
        return cls(loadContents=loadContents, loadListing=loadListing, glob=glob, outputEval=outputEval, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris)

        if self.glob is not None:
            r['glob'] = save(
                self.glob,
                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(['loadContents', 'loadListing', 'glob', 'outputEval'])


class CommandLineBindable(Savable):
    def __init__(
        self,
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> CommandLineBindable

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if 'inputBinding' in _doc:
            try:
                inputBinding = load_field(_doc.get(
                    'inputBinding'), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandLineBindable'", None, _errors__)
        return cls(inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        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(['inputBinding'])


class CommandInputRecordField(InputRecordField, CommandLineBindable):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        format=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type = type
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.format = format
        self.loadContents = loadContents
        self.loadListing = loadListing
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                raise ValidationException("Missing name")
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `streamable` field is not valid because:",
                        SourceLine(_doc, 'streamable', str),
                        [e]
                    )
                )
        else:
            streamable = 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        if 'inputBinding' in _doc:
            try:
                inputBinding = load_field(_doc.get(
                    'inputBinding'), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputRecordField'", None, _errors__)
        return cls(doc=doc, name=name, type=type, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.label is not None:
            r['label'] = save(
                self.label,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.secondaryFiles is not None:
            r['secondaryFiles'] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.streamable is not None:
            r['streamable'] = save(
                self.streamable,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.format is not None:
            u = save_relative_uri(
                self.format,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                r['format'] = u

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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(['doc', 'name', 'type', 'label', 'secondaryFiles', 'streamable', 'format', 'loadContents', 'loadListing', 'inputBinding'])


class CommandInputRecordSchema(InputRecordSchema, CommandInputSchema, CommandLineBindable):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `fields` field is not valid because:",
                        SourceLine(_doc, 'fields', str),
                        [e]
                    )
                )
        else:
            fields = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        if 'inputBinding' in _doc:
            try:
                inputBinding = load_field(_doc.get(
                    'inputBinding'), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)

        if self.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['fields', 'type', 'label', 'doc', 'name', 'inputBinding'])


class CommandInputEnumSchema(InputEnumSchema, CommandInputSchema, CommandLineBindable):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.symbols = symbols
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            symbols = load_field(_doc.get(
                'symbols'), uri_array_of_strtype_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `symbols` field is not valid because:",
                    SourceLine(_doc, 'symbols', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        if 'inputBinding' in _doc:
            try:
                inputBinding = load_field(_doc.get(
                    'inputBinding'), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `symbols`, `type`, `label`, `doc`, `name`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.symbols is not None:
            u = save_relative_uri(
                self.symbols,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['symbols', 'type', 'label', 'doc', 'name', 'inputBinding'])


class CommandInputArraySchema(InputArraySchema, CommandInputSchema, CommandLineBindable):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name
        self.inputBinding = inputBinding

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

        _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            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, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `items` field is not valid because:",
                    SourceLine(_doc, 'items', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        if 'inputBinding' in _doc:
            try:
                inputBinding = load_field(_doc.get(
                    'inputBinding'), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.items is not None:
            u = save_relative_uri(
                self.items,
                self.name,
                False,
                2,
                relative_uris)
            if u:
                r['items'] = 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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['items', 'type', 'label', 'doc', 'name', 'inputBinding'])


class CommandOutputRecordField(OutputRecordField):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        format=None,  # type: Any
        outputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name
        self.type = type
        self.label = label
        self.secondaryFiles = secondaryFiles
        self.streamable = streamable
        self.format = format
        self.outputBinding = outputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                raise ValidationException("Missing name")
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `streamable` field is not valid because:",
                        SourceLine(_doc, 'streamable', str),
                        [e]
                    )
                )
        else:
            streamable = None
        if 'format' in _doc:
            try:
                format = load_field(_doc.get(
                    'format'), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'outputBinding' in _doc:
            try:
                outputBinding = load_field(_doc.get(
                    'outputBinding'), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `outputBinding` field is not valid because:",
                        SourceLine(_doc, 'outputBinding', str),
                        [e]
                    )
                )
        else:
            outputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `secondaryFiles`, `streamable`, `format`, `outputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputRecordField'", None, _errors__)
        return cls(doc=doc, name=name, type=type, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.label is not None:
            r['label'] = save(
                self.label,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.secondaryFiles is not None:
            r['secondaryFiles'] = save(
                self.secondaryFiles,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.streamable is not None:
            r['streamable'] = save(
                self.streamable,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

        if self.format is not None:
            u = save_relative_uri(
                self.format,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                r['format'] = u

        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', 'label', 'secondaryFiles', 'streamable', 'format', 'outputBinding'])


class CommandOutputRecordSchema(OutputRecordSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.fields = fields
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `fields` field is not valid because:",
                        SourceLine(_doc, 'fields', str),
                        [e]
                    )
                )
        else:
            fields = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)

        if self.doc is not None:
            r['doc'] = save(
                self.doc,
                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', 'doc', 'name'])


class CommandOutputEnumSchema(OutputEnumSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.symbols = symbols
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            symbols = load_field(_doc.get(
                'symbols'), uri_array_of_strtype_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `symbols` field is not valid because:",
                    SourceLine(_doc, 'symbols', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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: `symbols`, `type`, `label`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.symbols is not None:
            u = save_relative_uri(
                self.symbols,
                self.name,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['symbols', 'type', 'label', 'doc', 'name'])


class CommandOutputArraySchema(OutputArraySchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        name=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.items = items
        self.type = type
        self.label = label
        self.doc = doc
        self.name = name

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> CommandOutputArraySchema

        _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `name` field is not valid because:",
                        SourceLine(_doc, 'name', str),
                        [e]
                    )
                )
        else:
            name = None

        if name is None:
            if docRoot is not None:
                name = docRoot
            else:
                name = "_:" + str(_uuid__.uuid4())
        baseuri = name
        try:
            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, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `items` field is not valid because:",
                    SourceLine(_doc, 'items', str),
                    [e]
                )
            )
        try:
            type = load_field(_doc.get(
                'type'), typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `doc`, `name`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.name is not None:
            u = save_relative_uri(
                self.name,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['name'] = u

        if self.items is not None:
            u = save_relative_uri(
                self.items,
                self.name,
                False,
                2,
                relative_uris)
            if u:
                r['items'] = 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.doc is not None:
            r['doc'] = save(
                self.doc,
                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(['items', 'type', 'label', 'doc', 'name'])


class CommandInputParameter(CommandInputParameterMixin,InputParameter):
    """
An input parameter for a CommandLineTool.
    """
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        default=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.loadContents = loadContents
        self.loadListing = loadListing
        self.default = default
        self.type = type
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        if 'default' in _doc:
            try:
                default = load_field(_doc.get(
                    'default'), union_of_None_type_or_Any_type, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `default` field is not valid because:",
                        SourceLine(_doc, 'default', str),
                        [e]
                    )
                )
        else:
            default = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_union_of_CWLTypeLoader_or_stdinLoader_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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type=type, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                r['format'] = u

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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)

        if self.inputBinding is not None:
            r['inputBinding'] = save(
                self.inputBinding,
                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', 'loadContents', 'loadListing', 'default', 'type', 'inputBinding'])


class CommandOutputParameter(CommandOutputParameterMixin,OutputParameter):
    """
An output parameter for a CommandLineTool.
    """
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        outputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.type = type
        self.outputBinding = outputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        try:
            type = load_field(_doc.get(
                'type'), typedsl_union_of_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)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `outputBinding` field is not valid because:",
                        SourceLine(_doc, 'outputBinding', str),
                        [e]
                    )
                )
        else:
            outputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `type`, `outputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type=type, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                r['format'] = u

        if self.type is not None:
            r['type'] = save(
                self.type,
                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)

        # 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', 'type', 'outputBinding'])


class CommandLineTool(CommandLineToolMixin,Process):
    """
This defines the schema of the CWL Command Line Tool Description document.

    """
    def __init__(
        self,
        inputs,  # type: Any
        outputs,  # type: Any
        id=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        requirements=None,  # type: Any
        hints=None,  # type: Any
        cwlVersion=None,  # type: Any
        intent=None,  # type: Any
        baseCommand=None,  # type: Any
        arguments=None,  # type: Any
        stdin=None,  # type: Any
        stderr=None,  # type: Any
        stdout=None,  # type: Any
        successCodes=None,  # type: Any
        temporaryFailCodes=None,  # type: Any
        permanentFailCodes=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.label = label
        self.doc = doc
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.cwlVersion = cwlVersion
        self.intent = intent
        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

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> CommandLineTool

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

        if _doc.get('class') != 'CommandLineTool':
            raise ValidationException("Not a CommandLineTool")

        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            inputs = load_field(_doc.get(
                'inputs'), idmap_inputs_array_of_CommandInputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `inputs` field is not valid because:",
                    SourceLine(_doc, 'inputs', str),
                    [e]
                )
            )
        try:
            outputs = load_field(_doc.get(
                'outputs'), idmap_outputs_array_of_CommandOutputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _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_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `hints` field is not valid because:",
                        SourceLine(_doc, 'hints', str),
                        [e]
                    )
                )
        else:
            hints = None
        if 'cwlVersion' in _doc:
            try:
                cwlVersion = load_field(_doc.get(
                    'cwlVersion'), uri_union_of_None_type_or_CWLVersionLoader_False_True_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `cwlVersion` field is not valid because:",
                        SourceLine(_doc, 'cwlVersion', str),
                        [e]
                    )
                )
        else:
            cwlVersion = None
        if 'intent' in _doc:
            try:
                intent = load_field(_doc.get(
                    'intent'), uri_union_of_None_type_or_array_of_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `intent` field is not valid because:",
                        SourceLine(_doc, 'intent', str),
                        [e]
                    )
                )
        else:
            intent = None
        if 'baseCommand' in _doc:
            try:
                baseCommand = load_field(_doc.get(
                    'baseCommand'), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `permanentFailCodes` field is not valid because:",
                        SourceLine(_doc, 'permanentFailCodes', str),
                        [e]
                    )
                )
        else:
            permanentFailCodes = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandLineTool'", None, _errors__)
        return cls(id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, baseCommand=baseCommand, arguments=arguments, stdin=stdin, stderr=stderr, stdout=stdout, successCodes=successCodes, temporaryFailCodes=temporaryFailCodes, permanentFailCodes=permanentFailCodes, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        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.cwlVersion is not None:
            u = save_relative_uri(
                self.cwlVersion,
                self.id,
                False,
                None,
                relative_uris)
            if u:
                r['cwlVersion'] = u

        if self.intent is not None:
            u = save_relative_uri(
                self.intent,
                self.id,
                True,
                None,
                relative_uris)
            if u:
                r['intent'] = 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', 'label', 'doc', 'inputs', 'outputs', 'requirements', 'hints', 'cwlVersion', 'intent', '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) or Docker-compatible (such as
[Singularity](https://www.sylabs.io/) and [udocker](https://github.com/indigo-dc/udocker)) container environment 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. The platform must ensure that `runtime.outdir` and
`runtime.tmpdir` are distinct directories.

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.

A container image may specify an
[ENTRYPOINT](https://docs.docker.com/engine/reference/builder/#entrypoint)
and/or
[CMD](https://docs.docker.com/engine/reference/builder/#cmd).
Command line arguments will be appended after all elements of
ENTRYPOINT, and will override all elements specified using CMD (in
other words, CMD is only used when the CommandLineTool definition
produces an empty command line).

Use of implicit ENTRYPOINT or CMD are discouraged due to reproducibility
concerns of the implicit hidden execution point (For further discussion, see
[https://doi.org/10.12688/f1000research.15140.1](https://doi.org/10.12688/f1000research.15140.1)). Portable
CommandLineTool wrappers in which use of a container is optional must not rely on ENTRYPOINT or CMD.
CommandLineTools which do rely on ENTRYPOINT or CMD must list `DockerRequirement` in the
`requirements` section.

## 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=None,  # type: Any
        dockerLoad=None,  # type: Any
        dockerFile=None,  # type: Any
        dockerImport=None,  # type: Any
        dockerImageId=None,  # type: Any
        dockerOutputDirectory=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> DockerRequirement

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

        if _doc.get('class') != 'DockerRequirement':
            raise ValidationException("Not a DockerRequirement")

        if 'dockerPull' in _doc:
            try:
                dockerPull = load_field(_doc.get(
                    'dockerPull'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `dockerOutputDirectory` field is not valid because:",
                        SourceLine(_doc, 'dockerOutputDirectory', str),
                        [e]
                    )
                )
        else:
            dockerOutputDirectory = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'DockerRequirement'", None, _errors__)
        return cls(dockerPull=dockerPull, dockerLoad=dockerLoad, dockerFile=dockerFile, dockerImport=dockerImport, dockerImageId=dockerImageId, dockerOutputDirectory=dockerOutputDirectory, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SoftwareRequirement"
        self.packages = packages

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> SoftwareRequirement

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

        if _doc.get('class') != 'SoftwareRequirement':
            raise ValidationException("Not a SoftwareRequirement")

        try:
            packages = load_field(_doc.get(
                'packages'), idmap_packages_array_of_SoftwarePackageLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `packages` field is not valid because:",
                    SourceLine(_doc, 'packages', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'SoftwareRequirement'", None, _errors__)
        return cls(packages=packages, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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(Savable):
    def __init__(
        self,
        package,  # type: Any
        version=None,  # type: Any
        specs=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.package = package
        self.version = version
        self.specs = specs

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> SoftwarePackage

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        try:
            package = load_field(_doc.get(
                'package'), strtype, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `specs` field is not valid because:",
                        SourceLine(_doc, 'specs', str),
                        [e]
                    )
                )
        else:
            specs = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'SoftwarePackage'", None, _errors__)
        return cls(package=package, version=version, specs=specs, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                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(Savable):
    """
Define a file or subdirectory that must be staged to a particular
place prior to executing the command line tool.  May be the result
of executing an expression, such as building a configuration file
from a template.

Usually files are staged within the [designated output directory](#Runtime_environment).
However, under certain circumstances, files may be staged at
arbitrary locations, see discussion for `entryname`.

    """
    def __init__(
        self,
        entry,  # type: Any
        entryname=None,  # type: Any
        writable=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.entryname = entryname
        self.entry = entry
        self.writable = writable

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `entryname` field is not valid because:",
                        SourceLine(_doc, 'entryname', str),
                        [e]
                    )
                )
        else:
            entryname = None
        try:
            entry = load_field(_doc.get(
                'entry'), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `writable` field is not valid because:",
                        SourceLine(_doc, 'writable', str),
                        [e]
                    )
                )
        else:
            writable = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'Dirent'", None, _errors__)
        return cls(entryname=entryname, entry=entry, writable=writable, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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 staged by the workflow platform prior to executing the command line tool.
Normally files are staged within the designated output directory. However, when running inside containers, files may be staged at arbitrary locations, see discussion for `Dirent.entryname`. Together with `DockerRequirement.dockerOutputDirectory` this it possible to control the locations of both input and output files when running in containers.
    """
    def __init__(
        self,
        listing,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "InitialWorkDirRequirement"
        self.listing = listing

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> InitialWorkDirRequirement

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

        if _doc.get('class') != 'InitialWorkDirRequirement':
            raise ValidationException("Not a InitialWorkDirRequirement")

        try:
            listing = load_field(_doc.get(
                'listing'), union_of_ExpressionLoader_or_array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `listing` field is not valid because:",
                    SourceLine(_doc, 'listing', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InitialWorkDirRequirement'", None, _errors__)
        return cls(listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "EnvVarRequirement"
        self.envDef = envDef

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> EnvVarRequirement

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

        if _doc.get('class') != 'EnvVarRequirement':
            raise ValidationException("Not a EnvVarRequirement")

        try:
            envDef = load_field(_doc.get(
                'envDef'), idmap_envDef_array_of_EnvironmentDefLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `envDef` field is not valid because:",
                    SourceLine(_doc, 'envDef', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'EnvVarRequirement'", None, _errors__)
        return cls(envDef=envDef, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ShellCommandRequirement"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> ShellCommandRequirement

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

        if _doc.get('class') != 'ShellCommandRequirement':
            raise ValidationException("Not a ShellCommandRequirement")


        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ShellCommandRequirement'", None, _errors__)
        return cls(extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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
allocated. 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 resource
allocation, an implementation may deny additional resources, which
may result in job failure.

If both "min" and "max" are specified, an implementation may
choose to allocate any amount between "min" and "max", with the
actual allocation provided in the `runtime` object.

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, use the default values below.

    """
    def __init__(
        self,
        coresMin=None,  # type: Any
        coresMax=None,  # type: Any
        ramMin=None,  # type: Any
        ramMax=None,  # type: Any
        tmpdirMin=None,  # type: Any
        tmpdirMax=None,  # type: Any
        outdirMin=None,  # type: Any
        outdirMax=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> ResourceRequirement

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

        if _doc.get('class') != 'ResourceRequirement':
            raise ValidationException("Not a ResourceRequirement")

        if 'coresMin' in _doc:
            try:
                coresMin = load_field(_doc.get(
                    'coresMin'), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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_floattype_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `outdirMax` field is not valid because:",
                        SourceLine(_doc, 'outdirMax', str),
                        [e]
                    )
                )
        else:
            outdirMax = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ResourceRequirement'", None, _errors__)
        return cls(coresMin=coresMin, coresMax=coresMax, ramMin=ramMin, ramMax=ramMax, tmpdirMin=tmpdirMin, tmpdirMax=tmpdirMax, outdirMin=outdirMin, outdirMax=outdirMax, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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 WorkReuse(ProcessRequirement):
    """
For implementations that support reusing output from past work (on
the assumption that same code and same input produce same
results), control whether to enable or disable the reuse behavior
for a particular tool or step (to accomodate situations where that
assumption is incorrect).  A reused step is not executed but
instead returns the same output as the original execution.

If `WorkReuse` is not specified, correct tools should assume it
is enabled by default.

    """
    def __init__(
        self,
        enableReuse,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "WorkReuse"
        self.enableReuse = enableReuse

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> WorkReuse

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

        if _doc.get('class') != 'WorkReuse':
            raise ValidationException("Not a WorkReuse")

        try:
            enableReuse = load_field(_doc.get(
                'enableReuse'), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `enableReuse` field is not valid because:",
                    SourceLine(_doc, 'enableReuse', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `enableReuse`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkReuse'", None, _errors__)
        return cls(enableReuse=enableReuse, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'WorkReuse'

        if self.enableReuse is not None:
            r['enableReuse'] = save(
                self.enableReuse,
                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', 'enableReuse'])


class NetworkAccess(ProcessRequirement):
    """
Indicate whether a process requires outgoing IPv4/IPv6 network
access.  Choice of IPv4 or IPv6 is implementation and site
specific, correct tools must support both.

If `networkAccess` is false or not specified, tools must not
assume network access, except for localhost (the loopback device).

If `networkAccess` is true, the tool must be able to make outgoing
connections to network resources.  Resources may be on a private
subnet or the public Internet.  However, implementations and sites
may apply their own security policies to restrict what is
accessible by the tool.

Enabling network access does not imply a publically routable IP
address or the ability to accept inbound connections.

    """
    def __init__(
        self,
        networkAccess,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "NetworkAccess"
        self.networkAccess = networkAccess

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> NetworkAccess

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

        if _doc.get('class') != 'NetworkAccess':
            raise ValidationException("Not a NetworkAccess")

        try:
            networkAccess = load_field(_doc.get(
                'networkAccess'), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `networkAccess` field is not valid because:",
                    SourceLine(_doc, 'networkAccess', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `networkAccess`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'NetworkAccess'", None, _errors__)
        return cls(networkAccess=networkAccess, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'NetworkAccess'

        if self.networkAccess is not None:
            r['networkAccess'] = save(
                self.networkAccess,
                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', 'networkAccess'])


class InplaceUpdateRequirement(ProcessRequirement):
    """

If `inplaceUpdate` is true, then an implementation supporting this
feature may permit tools to directly update files with `writable:
true` in InitialWorkDirRequirement.  That is, as an optimization,
files may be destructively modified in place as opposed to copied
and updated.

An implementation must ensure that only one workflow step may
access a writable file at a time.  It is an error if a file which
is writable by one workflow step file is accessed (for reading or
writing) by any other workflow step running independently.
However, a file which has been updated in a previous completed
step may be used as input to multiple steps, provided it is
read-only in every step.

Workflow steps which modify a file must produce the modified file
as output.  Downstream steps which futher process the file must
use the output of previous steps, and not refer to a common input
(this is necessary for both ordering and correctness).

Workflow authors should provide this in the `hints` section.  The
intent of this feature is that workflows produce the same results
whether or not InplaceUpdateRequirement is supported by the
implementation, and this feature is primarily available as an
optimization for particular environments.

Users and implementers should be aware that workflows that
destructively modify inputs may not be repeatable or reproducible.
In particular, enabling this feature implies that WorkReuse should
not be enabled.

    """
    def __init__(
        self,
        inplaceUpdate,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "InplaceUpdateRequirement"
        self.inplaceUpdate = inplaceUpdate

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> InplaceUpdateRequirement

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

        if _doc.get('class') != 'InplaceUpdateRequirement':
            raise ValidationException("Not a InplaceUpdateRequirement")

        try:
            inplaceUpdate = load_field(_doc.get(
                'inplaceUpdate'), booltype, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `inplaceUpdate` field is not valid because:",
                    SourceLine(_doc, 'inplaceUpdate', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `inplaceUpdate`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InplaceUpdateRequirement'", None, _errors__)
        return cls(inplaceUpdate=inplaceUpdate, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'InplaceUpdateRequirement'

        if self.inplaceUpdate is not None:
            r['inplaceUpdate'] = save(
                self.inplaceUpdate,
                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', 'inplaceUpdate'])


class ToolTimeLimit(ProcessRequirement):
    """
Set an upper limit on the execution time of a CommandLineTool.
A CommandLineTool whose execution duration exceeds the time
limit may be preemptively terminated and considered failed.
May also be used by batch systems to make scheduling decisions.
The execution duration excludes external operations, such as
staging of files, pulling a docker image etc, and only counts
wall-time for the execution of the command line itself.

    """
    def __init__(
        self,
        timelimit,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ToolTimeLimit"
        self.timelimit = timelimit

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> ToolTimeLimit

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

        if _doc.get('class') != 'ToolTimeLimit':
            raise ValidationException("Not a ToolTimeLimit")

        try:
            timelimit = load_field(_doc.get(
                'timelimit'), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `timelimit` field is not valid because:",
                    SourceLine(_doc, 'timelimit', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `timelimit`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ToolTimeLimit'", None, _errors__)
        return cls(timelimit=timelimit, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'ToolTimeLimit'

        if self.timelimit is not None:
            r['timelimit'] = save(
                self.timelimit,
                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', 'timelimit'])


class ExpressionToolOutputParameter(OutputParameter):
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        try:
            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)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `type`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ExpressionToolOutputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                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', 'format', 'type'])


class WorkflowInputParameter(InputParameter):
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        default=None,  # type: Any
        inputBinding=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.loadContents = loadContents
        self.loadListing = loadListing
        self.default = default
        self.type = type
        self.inputBinding = inputBinding

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> WorkflowInputParameter

        _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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        if 'default' in _doc:
            try:
                default = load_field(_doc.get(
                    'default'), union_of_None_type_or_Any_type, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `default` field is not valid because:",
                        SourceLine(_doc, 'default', str),
                        [e]
                    )
                )
        else:
            default = None
        try:
            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)
        except ValidationException as e:
            _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_InputBindingLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `inputBinding` field is not valid because:",
                        SourceLine(_doc, 'inputBinding', str),
                        [e]
                    )
                )
        else:
            inputBinding = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkflowInputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type=type, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                r['format'] = u

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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)

        if self.inputBinding is not None:
            r['inputBinding'] = save(
                self.inputBinding,
                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', 'loadContents', 'loadListing', 'default', 'type', 'inputBinding'])


class ExpressionTool(Process):
    """
An ExpressionTool is a type of Process object that can be run by itself
or as a Workflow step. It executes a pure Javascript expression that has
access to the same input parameters as a workflow. It is meant to be used
sparingly as a way to isolate complex Javascript expressions that need to
operate on input data and produce some result; perhaps just a
rearrangement of the inputs. No Docker software container is required
or allowed.

    """
    def __init__(
        self,
        inputs,  # type: Any
        outputs,  # type: Any
        expression,  # type: Any
        id=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        requirements=None,  # type: Any
        hints=None,  # type: Any
        cwlVersion=None,  # type: Any
        intent=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.label = label
        self.doc = doc
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.cwlVersion = cwlVersion
        self.intent = intent
        self.class_ = "ExpressionTool"
        self.expression = expression

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> ExpressionTool

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

        if _doc.get('class') != 'ExpressionTool':
            raise ValidationException("Not a ExpressionTool")

        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            inputs = load_field(_doc.get(
                'inputs'), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `inputs` field is not valid because:",
                    SourceLine(_doc, 'inputs', str),
                    [e]
                )
            )
        try:
            outputs = load_field(_doc.get(
                'outputs'), idmap_outputs_array_of_ExpressionToolOutputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _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_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `hints` field is not valid because:",
                        SourceLine(_doc, 'hints', str),
                        [e]
                    )
                )
        else:
            hints = None
        if 'cwlVersion' in _doc:
            try:
                cwlVersion = load_field(_doc.get(
                    'cwlVersion'), uri_union_of_None_type_or_CWLVersionLoader_False_True_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `cwlVersion` field is not valid because:",
                        SourceLine(_doc, 'cwlVersion', str),
                        [e]
                    )
                )
        else:
            cwlVersion = None
        if 'intent' in _doc:
            try:
                intent = load_field(_doc.get(
                    'intent'), uri_union_of_None_type_or_array_of_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `intent` field is not valid because:",
                        SourceLine(_doc, 'intent', str),
                        [e]
                    )
                )
        else:
            intent = None
        try:
            expression = load_field(_doc.get(
                'expression'), ExpressionLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `expression` field is not valid because:",
                    SourceLine(_doc, 'expression', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `expression`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ExpressionTool'", None, _errors__)
        return cls(id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, expression=expression, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        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.cwlVersion is not None:
            u = save_relative_uri(
                self.cwlVersion,
                self.id,
                False,
                None,
                relative_uris)
            if u:
                r['cwlVersion'] = u

        if self.intent is not None:
            u = save_relative_uri(
                self.intent,
                self.id,
                True,
                None,
                relative_uris)
            if u:
                r['intent'] = 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', 'label', 'doc', 'inputs', 'outputs', 'requirements', 'hints', 'cwlVersion', 'intent', 'class', 'expression'])


class WorkflowOutputParameter(WorkflowOutputParameterMixin,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. It is legal to
connect a WorkflowInputParameter to a WorkflowOutputParameter.

See [WorkflowStepInput](#WorkflowStepInput) for discussion of
`linkMerge` and `pickValue`.

    """
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        outputSource=None,  # type: Any
        linkMerge=None,  # type: Any
        pickValue=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.outputSource = outputSource
        self.linkMerge = linkMerge
        self.pickValue = pickValue
        self.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _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_0, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `linkMerge` field is not valid because:",
                        SourceLine(_doc, 'linkMerge', str),
                        [e]
                    )
                )
        else:
            linkMerge = None
        if 'pickValue' in _doc:
            try:
                pickValue = load_field(_doc.get(
                    'pickValue'), union_of_None_type_or_PickValueMethodLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `pickValue` field is not valid because:",
                        SourceLine(_doc, 'pickValue', str),
                        [e]
                    )
                )
        else:
            pickValue = None
        try:
            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)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `outputSource`, `linkMerge`, `pickValue`, `type`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkflowOutputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, outputSource=outputSource, linkMerge=linkMerge, pickValue=pickValue, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                r['format'] = u

        if self.outputSource is not None:
            u = save_relative_uri(
                self.outputSource,
                self.id,
                False,
                0,
                relative_uris)
            if u:
                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.pickValue is not None:
            r['pickValue'] = save(
                self.pickValue,
                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', 'outputSource', 'linkMerge', 'pickValue', 'type'])


class Sink(Savable):
    pass


class WorkflowStepInput(WorkflowStepInputMixin,Identified, Sink, LoadContents, Labeled):
    """
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 process specified by the `run` field. Only input parameters
declared by the target process will be passed through at runtime to the process
though additonal parameters may be specified (for use within `valueFrom`
expressions for instance) - unconnected or unused parameters do not represent an
error condition.

# 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 multiple inbound data links

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 both `linkMerge` and `pickValue` are null
or not specified, and there is more than one element in the
`source` array, the default method is "merge_nested".

If both `linkMerge` and `pickValue` are null or not specified, and
there is only a single element in the `source`, then the input
parameter takes the scalar value from the single input link (it is
*not* wrapped in a single-list).

* **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.

# Picking non-null values among inbound data links

If present, `pickValue` specifies how to picking non-null values among inbound data links.

`pickValue` is evaluated
  1. Once all source values from upstream step or parameters are available.
  2. After `linkMerge`.
  3. Before `scatter` or `valueFrom`.

This is specifically intended to be useful in combination with
[conditional execution](#WorkflowStep), where several upstream
steps may be connected to a single input (`source` is a list), and
skipped steps produce null values.

Static type checkers should check for type consistency after infering what the type
will be after `pickValue` is applied, just as they do currently for `linkMerge`.

* **first_non_null**

  For the first level of a list input, pick the first non-null element.  The result is a scalar.
  It is an error if there is no non-null element.  Examples:
  * `[null, x, null, y] -> x`
  * `[null, [null], null, y] -> [null]`
  * `[null, null, null] -> Runtime Error`

  *Intended use case*: If-else pattern where the
  value comes either from a conditional step or from a default or
  fallback value. The conditional step(s) should be placed first in
  the list.

* **the_only_non_null**

  For the first level of a list input, pick the single non-null element.  The result is a scalar.
  It is an error if there is more than one non-null element.  Examples:

  * `[null, x, null] -> x`
  * `[null, x, null, y] -> Runtime Error`
  * `[null, [null], null] -> [null]`
  * `[null, null, null] -> Runtime Error`

  *Intended use case*: Switch type patterns where developer considers
  more than one active code path as a workflow error
  (possibly indicating an error in writing `when` condition expressions).

* **all_non_null**

  For the first level of a list input, pick all non-null values.
  The result is a list, which may be empty.  Examples:

  * `[null, x, null] -> [x]`
  * `[x, null, y] -> [x, y]`
  * `[null, [x], [null]] -> [[x], [null]]`
  * `[null, null, null] -> []`

  *Intended use case*: It is valid to have more than one source, but
   sources are conditional, so null sources (from skipped steps)
   should be filtered out.

    """
    def __init__(
        self,
        id=None,  # type: Any
        source=None,  # type: Any
        linkMerge=None,  # type: Any
        pickValue=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        label=None,  # type: Any
        default=None,  # type: Any
        valueFrom=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.source = source
        self.linkMerge = linkMerge
        self.pickValue = pickValue
        self.loadContents = loadContents
        self.loadListing = loadListing
        self.label = label
        self.default = default
        self.valueFrom = valueFrom

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        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, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `linkMerge` field is not valid because:",
                        SourceLine(_doc, 'linkMerge', str),
                        [e]
                    )
                )
        else:
            linkMerge = None
        if 'pickValue' in _doc:
            try:
                pickValue = load_field(_doc.get(
                    'pickValue'), union_of_None_type_or_PickValueMethodLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `pickValue` field is not valid because:",
                        SourceLine(_doc, 'pickValue', str),
                        [e]
                    )
                )
        else:
            pickValue = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `label` field is not valid because:",
                        SourceLine(_doc, 'label', str),
                        [e]
                    )
                )
        else:
            label = None
        if 'default' in _doc:
            try:
                default = load_field(_doc.get(
                    'default'), union_of_None_type_or_Any_type, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `valueFrom` field is not valid because:",
                        SourceLine(_doc, 'valueFrom', str),
                        [e]
                    )
                )
        else:
            valueFrom = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `source`, `linkMerge`, `pickValue`, `loadContents`, `loadListing`, `label`, `default`, `valueFrom`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkflowStepInput'", None, _errors__)
        return cls(id=id, source=source, linkMerge=linkMerge, pickValue=pickValue, loadContents=loadContents, loadListing=loadListing, label=label, default=default, valueFrom=valueFrom, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                r['id'] = u

        if self.source is not None:
            u = save_relative_uri(
                self.source,
                self.id,
                False,
                2,
                relative_uris)
            if u:
                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.pickValue is not None:
            r['pickValue'] = save(
                self.pickValue,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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.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(['id', 'source', 'linkMerge', 'pickValue', 'loadContents', 'loadListing', 'label', 'default', 'valueFrom'])


class WorkflowStepOutput(Identified):
    """
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.

A unique identifier for this workflow output parameter.  This is
the identifier to use in the `source` field of `WorkflowStepInput`
to connect the output value to downstream parameters.

    """
    def __init__(
        self,
        id=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkflowStepOutput'", None, _errors__)
        return cls(id=id, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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(WorkflowStepMixin,Identified, Labeled, Documented):
    """
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.

# Conditional execution (Optional)

Conditional execution makes execution of a step conditional on an
expression.  A step that is not executed is "skipped".  A skipped
step produces `null` for all output parameters.

The condition is evaluated after `scatter`, using the input object
of each individual scatter job.  This means over a set of scatter
jobs, some may be executed and some may be skipped.  When the
results are gathered, skipped steps must be `null` in the output
arrays.

The `when` field controls conditional execution.  This is an
expression that must be evaluated with `inputs` bound to the step
input object (or individual scatter job), and returns a boolean
value.  It is an error if this expression returns a value other
than `true` or `false`.

Conditionals in CWL are an optional feature and are not required
to be implemented by all consumers of CWL documents.  An
implementation that does not support conditionals must return a
fatal error when attempting execute a workflow that uses
conditional constructs the implementation does not support.

# 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,
        in_,  # type: Any
        out,  # type: Any
        run,  # type: Any
        id=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        requirements=None,  # type: Any
        hints=None,  # type: Any
        when=None,  # type: Any
        scatter=None,  # type: Any
        scatterMethod=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.label = label
        self.doc = doc
        self.in_ = in_
        self.out = out
        self.requirements = requirements
        self.hints = hints
        self.run = run
        self.when = when
        self.scatter = scatter
        self.scatterMethod = scatterMethod

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> 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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            in_ = load_field(_doc.get(
                'in'), idmap_in__array_of_WorkflowStepInputLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `in` field is not valid because:",
                    SourceLine(_doc, 'in', str),
                    [e]
                )
            )
        try:
            out = load_field(_doc.get(
                'out'), uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None, baseuri, loadingOptions)
        except ValidationException as e:
            _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_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `hints` field is not valid because:",
                        SourceLine(_doc, 'hints', str),
                        [e]
                    )
                )
        else:
            hints = None
        try:
            run = load_field(_doc.get(
                'run'), union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `run` field is not valid because:",
                    SourceLine(_doc, 'run', str),
                    [e]
                )
            )
        if 'when' in _doc:
            try:
                when = load_field(_doc.get(
                    'when'), union_of_None_type_or_ExpressionLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `when` field is not valid because:",
                        SourceLine(_doc, 'when', str),
                        [e]
                    )
                )
        else:
            when = None
        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, baseuri, loadingOptions)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `scatterMethod` field is not valid because:",
                        SourceLine(_doc, 'scatterMethod', str),
                        [e]
                    )
                )
        else:
            scatterMethod = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `doc`, `in`, `out`, `requirements`, `hints`, `run`, `when`, `scatter`, `scatterMethod`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'WorkflowStep'", None, _errors__)
        return cls(id=id, label=label, doc=doc, in_=in_, out=out, requirements=requirements, hints=hints, run=run, when=when, scatter=scatter, scatterMethod=scatterMethod, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        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)
            if u:
                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.run is not None:
            r['run'] = save(
                self.run,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.when is not None:
            r['when'] = save(
                self.when,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.scatter is not None:
            u = save_relative_uri(
                self.scatter,
                self.id,
                False,
                0,
                relative_uris)
            if u:
                r['scatter'] = u

        if self.scatterMethod is not None:
            u = save_relative_uri(
                self.scatterMethod,
                self.id,
                False,
                None,
                relative_uris)
            if u:
                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', 'label', 'doc', 'in', 'out', 'requirements', 'hints', 'run', 'when', 'scatter', 'scatterMethod'])


class Workflow(WorkflowMixin,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
`outputSource` field on [workflow output
parameters](#WorkflowOutputParameter).

The `source` field on each workflow step input parameter expresses
the data links that contribute to the value of the step input
parameter (the "sink").  A workflow step can only begin execution
when every data link connected to a step has been fulfilled.

The `outputSource` field on each workflow step input parameter
expresses the data links that contribute to the value of the
workflow output parameter (the "sink").  Workflow execution cannot
complete successfully until every data link connected to an output
parameter has been fulfilled.

## 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,  # type: Any
        outputs,  # type: Any
        steps,  # type: Any
        id=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        requirements=None,  # type: Any
        hints=None,  # type: Any
        cwlVersion=None,  # type: Any
        intent=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.label = label
        self.doc = doc
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.cwlVersion = cwlVersion
        self.intent = intent
        self.class_ = "Workflow"
        self.steps = steps

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Workflow

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

        if _doc.get('class') != 'Workflow':
            raise ValidationException("Not a Workflow")

        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            inputs = load_field(_doc.get(
                'inputs'), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `inputs` field is not valid because:",
                    SourceLine(_doc, 'inputs', str),
                    [e]
                )
            )
        try:
            outputs = load_field(_doc.get(
                'outputs'), idmap_outputs_array_of_WorkflowOutputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _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_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `hints` field is not valid because:",
                        SourceLine(_doc, 'hints', str),
                        [e]
                    )
                )
        else:
            hints = None
        if 'cwlVersion' in _doc:
            try:
                cwlVersion = load_field(_doc.get(
                    'cwlVersion'), uri_union_of_None_type_or_CWLVersionLoader_False_True_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `cwlVersion` field is not valid because:",
                        SourceLine(_doc, 'cwlVersion', str),
                        [e]
                    )
                )
        else:
            cwlVersion = None
        if 'intent' in _doc:
            try:
                intent = load_field(_doc.get(
                    'intent'), uri_union_of_None_type_or_array_of_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `intent` field is not valid because:",
                        SourceLine(_doc, 'intent', str),
                        [e]
                    )
                )
        else:
            intent = None
        try:
            steps = load_field(_doc.get(
                'steps'), idmap_steps_union_of_array_of_WorkflowStepLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `steps` field is not valid because:",
                    SourceLine(_doc, 'steps', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `steps`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'Workflow'", None, _errors__)
        return cls(id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, steps=steps, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        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.cwlVersion is not None:
            u = save_relative_uri(
                self.cwlVersion,
                self.id,
                False,
                None,
                relative_uris)
            if u:
                r['cwlVersion'] = u

        if self.intent is not None:
            u = save_relative_uri(
                self.intent,
                self.id,
                True,
                None,
                relative_uris)
            if u:
                r['intent'] = 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', 'label', 'doc', 'inputs', 'outputs', 'requirements', 'hints', 'cwlVersion', 'intent', '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=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "SubworkflowFeatureRequirement"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> SubworkflowFeatureRequirement

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

        if _doc.get('class') != 'SubworkflowFeatureRequirement':
            raise ValidationException("Not a SubworkflowFeatureRequirement")


        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'SubworkflowFeatureRequirement'", None, _errors__)
        return cls(extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "ScatterFeatureRequirement"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> ScatterFeatureRequirement

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

        if _doc.get('class') != 'ScatterFeatureRequirement':
            raise ValidationException("Not a ScatterFeatureRequirement")


        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'ScatterFeatureRequirement'", None, _errors__)
        return cls(extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "MultipleInputFeatureRequirement"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> MultipleInputFeatureRequirement

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

        if _doc.get('class') != 'MultipleInputFeatureRequirement':
            raise ValidationException("Not a MultipleInputFeatureRequirement")


        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'MultipleInputFeatureRequirement'", None, _errors__)
        return cls(extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.class_ = "StepInputExpressionRequirement"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> StepInputExpressionRequirement

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

        if _doc.get('class') != 'StepInputExpressionRequirement':
            raise ValidationException("Not a StepInputExpressionRequirement")


        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'StepInputExpressionRequirement'", None, _errors__)
        return cls(extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = 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'])


class OperationInputParameter(InputParameter):
    """
Describe an input parameter of an operation.

    """
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        loadContents=None,  # type: Any
        loadListing=None,  # type: Any
        default=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.loadContents = loadContents
        self.loadListing = loadListing
        self.default = default
        self.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> OperationInputParameter

        _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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        if 'loadContents' in _doc:
            try:
                loadContents = load_field(_doc.get(
                    'loadContents'), union_of_None_type_or_booltype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadContents` field is not valid because:",
                        SourceLine(_doc, 'loadContents', str),
                        [e]
                    )
                )
        else:
            loadContents = None
        if 'loadListing' in _doc:
            try:
                loadListing = load_field(_doc.get(
                    'loadListing'), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `loadListing` field is not valid because:",
                        SourceLine(_doc, 'loadListing', str),
                        [e]
                    )
                )
        else:
            loadListing = None
        if 'default' in _doc:
            try:
                default = load_field(_doc.get(
                    'default'), union_of_None_type_or_Any_type, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `default` field is not valid because:",
                        SourceLine(_doc, 'default', str),
                        [e]
                    )
                )
        else:
            default = None
        try:
            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)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `loadContents`, `loadListing`, `default`, `type`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OperationInputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                r['format'] = u

        if self.loadContents is not None:
            r['loadContents'] = save(
                self.loadContents,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        if self.loadListing is not None:
            r['loadListing'] = save(
                self.loadListing,
                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', 'loadContents', 'loadListing', 'default', 'type'])


class OperationOutputParameter(OutputParameter):
    """
Describe an output parameter of an operation.

    """
    def __init__(
        self,
        type,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        id=None,  # type: Any
        format=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.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.type = type

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> OperationOutputParameter

        _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_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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'), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _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_ExpressionLoader_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `format` field is not valid because:",
                        SourceLine(_doc, 'format', str),
                        [e]
                    )
                )
        else:
            format = None
        try:
            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)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `type` field is not valid because:",
                    SourceLine(_doc, 'type', str),
                    [e]
                )
            )

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `type`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OperationOutputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type=type, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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)
            if u:
                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', 'format', 'type'])


class Operation(Process):
    """
This record describes an abstract operation.  It is a potential
step of a workflow that has not yet been bound to a concrete
implementation.  It specifies an input and output signature, but
does not provide enough information to be executed.  An
implementation (or other tooling) may provide a means of binding
an Operation to a concrete process (such as Workflow,
CommandLineTool, or ExpressionTool) with a compatible signature.

    """
    def __init__(
        self,
        inputs,  # type: Any
        outputs,  # type: Any
        id=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        requirements=None,  # type: Any
        hints=None,  # type: Any
        cwlVersion=None,  # type: Any
        intent=None,  # type: Any
        extension_fields=None,  # type: Optional[Dict[str, Any]]
        loadingOptions=None  # type: Optional[LoadingOptions]
    ):  # type: (...) -> None

        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = yaml.comments.CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.id = id
        self.label = label
        self.doc = doc
        self.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.cwlVersion = cwlVersion
        self.intent = intent
        self.class_ = "Operation"

    @classmethod
    def fromDoc(cls, doc, baseuri, loadingOptions, docRoot=None):
        # type: (Any, str, LoadingOptions, Optional[str]) -> Operation

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

        if _doc.get('class') != 'Operation':
            raise ValidationException("Not a Operation")

        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_union_of_None_type_or_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `id` field is not valid because:",
                        SourceLine(_doc, 'id', str),
                        [e]
                    )
                )
        else:
            id = None

        if id is None:
            if docRoot is not None:
                id = docRoot
            else:
                id = "_:" + str(_uuid__.uuid4())
        baseuri = id
        if 'label' in _doc:
            try:
                label = load_field(_doc.get(
                    'label'), union_of_None_type_or_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _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_or_array_of_strtype, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `doc` field is not valid because:",
                        SourceLine(_doc, 'doc', str),
                        [e]
                    )
                )
        else:
            doc = None
        try:
            inputs = load_field(_doc.get(
                'inputs'), idmap_inputs_array_of_OperationInputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _errors__.append(
                ValidationException(
                    "the `inputs` field is not valid because:",
                    SourceLine(_doc, 'inputs', str),
                    [e]
                )
            )
        try:
            outputs = load_field(_doc.get(
                'outputs'), idmap_outputs_array_of_OperationOutputParameterLoader, baseuri, loadingOptions)
        except ValidationException as e:
            _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_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, baseuri, loadingOptions)
            except ValidationException as e:
                _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)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `hints` field is not valid because:",
                        SourceLine(_doc, 'hints', str),
                        [e]
                    )
                )
        else:
            hints = None
        if 'cwlVersion' in _doc:
            try:
                cwlVersion = load_field(_doc.get(
                    'cwlVersion'), uri_union_of_None_type_or_CWLVersionLoader_False_True_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `cwlVersion` field is not valid because:",
                        SourceLine(_doc, 'cwlVersion', str),
                        [e]
                    )
                )
        else:
            cwlVersion = None
        if 'intent' in _doc:
            try:
                intent = load_field(_doc.get(
                    'intent'), uri_union_of_None_type_or_array_of_strtype_True_False_None, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `intent` field is not valid because:",
                        SourceLine(_doc, 'intent', str),
                        [e]
                    )
                )
        else:
            intent = None

        extension_fields = yaml.comments.CommentedMap()
        for k in _doc.keys():
            if k not in cls.attrs:
                if ":" 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`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`".format(k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'Operation'", None, _errors__)
        return cls(id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, extension_fields=extension_fields, loadingOptions=loadingOptions)

    def save(self, top=False, base_url="", relative_uris=True):
        # type: (bool, str, bool) -> Dict[str, Any]
        r = yaml.comments.CommentedMap()  # type: Dict[str, Any]
        for ef in self.extension_fields:
            r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]

        r['class'] = 'Operation'

        if self.id is not None:
            u = save_relative_uri(
                self.id,
                base_url,
                True,
                None,
                relative_uris)
            if u:
                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.doc is not None:
            r['doc'] = save(
                self.doc,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

        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.cwlVersion is not None:
            u = save_relative_uri(
                self.cwlVersion,
                self.id,
                False,
                None,
                relative_uris)
            if u:
                r['cwlVersion'] = u

        if self.intent is not None:
            u = save_relative_uri(
                self.intent,
                self.id,
                True,
                None,
                relative_uris)
            if u:
                r['intent'] = 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', 'label', 'doc', 'inputs', 'outputs', 'requirements', 'hints', 'cwlVersion', 'intent', 'class'])


_vocab = {
    "Any": "https://w3id.org/cwl/salad#Any",
    "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema",
    "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",
    "CommandInputSchema": "https://w3id.org/cwl/cwl#CommandInputSchema",
    "CommandLineBindable": "https://w3id.org/cwl/cwl#CommandLineBindable",
    "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",
    "FieldBase": "https://w3id.org/cwl/cwl#FieldBase",
    "File": "https://w3id.org/cwl/cwl#File",
    "IOSchema": "https://w3id.org/cwl/cwl#IOSchema",
    "Identified": "https://w3id.org/cwl/cwl#Identified",
    "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement",
    "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement",
    "InplaceUpdateRequirement": "https://w3id.org/cwl/cwl#InplaceUpdateRequirement",
    "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema",
    "InputBinding": "https://w3id.org/cwl/cwl#InputBinding",
    "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema",
    "InputFormat": "https://w3id.org/cwl/cwl#InputFormat",
    "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",
    "Labeled": "https://w3id.org/cwl/cwl#Labeled",
    "LinkMergeMethod": "https://w3id.org/cwl/cwl#LinkMergeMethod",
    "LoadContents": "https://w3id.org/cwl/cwl#LoadContents",
    "LoadListingEnum": "https://w3id.org/cwl/cwl#LoadListingEnum",
    "LoadListingRequirement": "https://w3id.org/cwl/cwl#LoadListingRequirement",
    "MultipleInputFeatureRequirement": "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement",
    "NetworkAccess": "https://w3id.org/cwl/cwl#NetworkAccess",
    "Operation": "https://w3id.org/cwl/cwl#Operation",
    "OperationInputParameter": "https://w3id.org/cwl/cwl#OperationInputParameter",
    "OperationOutputParameter": "https://w3id.org/cwl/cwl#OperationOutputParameter",
    "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema",
    "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema",
    "OutputFormat": "https://w3id.org/cwl/cwl#OutputFormat",
    "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",
    "PickValueMethod": "https://w3id.org/cwl/cwl#PickValueMethod",
    "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",
    "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement",
    "SecondaryFileSchema": "https://w3id.org/cwl/cwl#SecondaryFileSchema",
    "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",
    "ToolTimeLimit": "https://w3id.org/cwl/cwl#ToolTimeLimit",
    "WorkReuse": "https://w3id.org/cwl/cwl#WorkReuse",
    "Workflow": "https://w3id.org/cwl/cwl#Workflow",
    "WorkflowInputParameter": "https://w3id.org/cwl/cwl#WorkflowInputParameter",
    "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",
    "all_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/all_non_null",
    "array": "https://w3id.org/cwl/salad#array",
    "boolean": "http://www.w3.org/2001/XMLSchema#boolean",
    "deep_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing",
    "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",
    "first_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/first_non_null",
    "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",
    "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",
    "no_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/no_listing",
    "null": "https://w3id.org/cwl/salad#null",
    "record": "https://w3id.org/cwl/salad#record",
    "shallow_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing",
    "stderr": "https://w3id.org/cwl/cwl#stderr",
    "stdin": "https://w3id.org/cwl/cwl#stdin",
    "stdout": "https://w3id.org/cwl/cwl#stdout",
    "string": "http://www.w3.org/2001/XMLSchema#string",
    "the_only_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/the_only_non_null",
    "v1.0": "https://w3id.org/cwl/cwl#v1.0",
    "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4",
    "v1.1": "https://w3id.org/cwl/cwl#v1.1",
    "v1.1.0-dev1": "https://w3id.org/cwl/cwl#v1.1.0-dev1",
    "v1.2": "https://w3id.org/cwl/cwl#v1.2",
    "v1.2.0-dev1": "https://w3id.org/cwl/cwl#v1.2.0-dev1",
    "v1.2.0-dev2": "https://w3id.org/cwl/cwl#v1.2.0-dev2",
    "v1.2.0-dev3": "https://w3id.org/cwl/cwl#v1.2.0-dev3",
    "v1.2.0-dev4": "https://w3id.org/cwl/cwl#v1.2.0-dev4",
    "v1.2.0-dev5": "https://w3id.org/cwl/cwl#v1.2.0-dev5",
}
_rvocab = {
    "https://w3id.org/cwl/salad#Any": "Any",
    "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema",
    "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#CommandInputSchema": "CommandInputSchema",
    "https://w3id.org/cwl/cwl#CommandLineBindable": "CommandLineBindable",
    "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#FieldBase": "FieldBase",
    "https://w3id.org/cwl/cwl#File": "File",
    "https://w3id.org/cwl/cwl#IOSchema": "IOSchema",
    "https://w3id.org/cwl/cwl#Identified": "Identified",
    "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement",
    "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement",
    "https://w3id.org/cwl/cwl#InplaceUpdateRequirement": "InplaceUpdateRequirement",
    "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#InputFormat": "InputFormat",
    "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#Labeled": "Labeled",
    "https://w3id.org/cwl/cwl#LinkMergeMethod": "LinkMergeMethod",
    "https://w3id.org/cwl/cwl#LoadContents": "LoadContents",
    "https://w3id.org/cwl/cwl#LoadListingEnum": "LoadListingEnum",
    "https://w3id.org/cwl/cwl#LoadListingRequirement": "LoadListingRequirement",
    "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement": "MultipleInputFeatureRequirement",
    "https://w3id.org/cwl/cwl#NetworkAccess": "NetworkAccess",
    "https://w3id.org/cwl/cwl#Operation": "Operation",
    "https://w3id.org/cwl/cwl#OperationInputParameter": "OperationInputParameter",
    "https://w3id.org/cwl/cwl#OperationOutputParameter": "OperationOutputParameter",
    "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema",
    "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema",
    "https://w3id.org/cwl/cwl#OutputFormat": "OutputFormat",
    "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/cwl#PickValueMethod": "PickValueMethod",
    "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#SchemaDefRequirement": "SchemaDefRequirement",
    "https://w3id.org/cwl/cwl#SecondaryFileSchema": "SecondaryFileSchema",
    "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/cwl#ToolTimeLimit": "ToolTimeLimit",
    "https://w3id.org/cwl/cwl#WorkReuse": "WorkReuse",
    "https://w3id.org/cwl/cwl#Workflow": "Workflow",
    "https://w3id.org/cwl/cwl#WorkflowInputParameter": "WorkflowInputParameter",
    "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/cwl#PickValueMethod/all_non_null": "all_non_null",
    "https://w3id.org/cwl/salad#array": "array",
    "http://www.w3.org/2001/XMLSchema#boolean": "boolean",
    "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing": "deep_listing",
    "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#PickValueMethod/first_non_null": "first_non_null",
    "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/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/cwl#LoadListingEnum/no_listing": "no_listing",
    "https://w3id.org/cwl/salad#null": "null",
    "https://w3id.org/cwl/salad#record": "record",
    "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing": "shallow_listing",
    "https://w3id.org/cwl/cwl#stderr": "stderr",
    "https://w3id.org/cwl/cwl#stdin": "stdin",
    "https://w3id.org/cwl/cwl#stdout": "stdout",
    "http://www.w3.org/2001/XMLSchema#string": "string",
    "https://w3id.org/cwl/cwl#PickValueMethod/the_only_non_null": "the_only_non_null",
    "https://w3id.org/cwl/cwl#v1.0": "v1.0",
    "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4",
    "https://w3id.org/cwl/cwl#v1.1": "v1.1",
    "https://w3id.org/cwl/cwl#v1.1.0-dev1": "v1.1.0-dev1",
    "https://w3id.org/cwl/cwl#v1.2": "v1.2",
    "https://w3id.org/cwl/cwl#v1.2.0-dev1": "v1.2.0-dev1",
    "https://w3id.org/cwl/cwl#v1.2.0-dev2": "v1.2.0-dev2",
    "https://w3id.org/cwl/cwl#v1.2.0-dev3": "v1.2.0-dev3",
    "https://w3id.org/cwl/cwl#v1.2.0-dev4": "v1.2.0-dev4",
    "https://w3id.org/cwl/cwl#v1.2.0-dev5": "v1.2.0-dev5",
}

strtype = _PrimitiveLoader((str, str))
inttype = _PrimitiveLoader(int)
floattype = _PrimitiveLoader(float)
booltype = _PrimitiveLoader(bool)
None_type = _PrimitiveLoader(type(None))
Any_type = _AnyLoader()
DocumentedLoader = _RecordLoader(Documented)
PrimitiveTypeLoader = _EnumLoader(("null", "boolean", "int", "long", "float", "double", "string",))
AnyLoader = _EnumLoader(("Any",))
RecordFieldLoader = _RecordLoader(RecordField)
RecordSchemaLoader = _RecordLoader(RecordSchema)
EnumSchemaLoader = _RecordLoader(EnumSchema)
ArraySchemaLoader = _RecordLoader(ArraySchema)
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", "v1.1.0-dev1", "v1.1", "v1.2.0-dev1", "v1.2.0-dev2", "v1.2.0-dev3", "v1.2.0-dev4", "v1.2.0-dev5", "v1.2",))
CWLTypeLoader = _EnumLoader(("File", "Directory",))
FileLoader = _RecordLoader(File)
DirectoryLoader = _RecordLoader(Directory)
LabeledLoader = _RecordLoader(Labeled)
IdentifiedLoader = _RecordLoader(Identified)
LoadListingEnumLoader = _EnumLoader(("no_listing", "shallow_listing", "deep_listing",))
LoadContentsLoader = _RecordLoader(LoadContents)
FieldBaseLoader = _RecordLoader(FieldBase)
InputFormatLoader = _RecordLoader(InputFormat)
OutputFormatLoader = _RecordLoader(OutputFormat)
ParameterLoader = _RecordLoader(Parameter)
ExpressionLoader = _ExpressionLoader(str)
InputBindingLoader = _RecordLoader(InputBinding)
IOSchemaLoader = _RecordLoader(IOSchema)
InputSchemaLoader = _RecordLoader(InputSchema)
OutputSchemaLoader = _RecordLoader(OutputSchema)
InputRecordFieldLoader = _RecordLoader(InputRecordField)
InputRecordSchemaLoader = _RecordLoader(InputRecordSchema)
InputEnumSchemaLoader = _RecordLoader(InputEnumSchema)
InputArraySchemaLoader = _RecordLoader(InputArraySchema)
OutputRecordFieldLoader = _RecordLoader(OutputRecordField)
OutputRecordSchemaLoader = _RecordLoader(OutputRecordSchema)
OutputEnumSchemaLoader = _RecordLoader(OutputEnumSchema)
OutputArraySchemaLoader = _RecordLoader(OutputArraySchema)
InputParameterLoader = _RecordLoader(InputParameter)
OutputParameterLoader = _RecordLoader(OutputParameter)
ProcessRequirementLoader = _RecordLoader(ProcessRequirement)
ProcessLoader = _RecordLoader(Process)
InlineJavascriptRequirementLoader = _RecordLoader(InlineJavascriptRequirement)
CommandInputSchemaLoader = _RecordLoader(CommandInputSchema)
SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement)
SecondaryFileSchemaLoader = _RecordLoader(SecondaryFileSchema)
LoadListingRequirementLoader = _RecordLoader(LoadListingRequirement)
EnvironmentDefLoader = _RecordLoader(EnvironmentDef)
CommandLineBindingLoader = _RecordLoader(CommandLineBinding)
CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding)
CommandLineBindableLoader = _RecordLoader(CommandLineBindable)
CommandInputRecordFieldLoader = _RecordLoader(CommandInputRecordField)
CommandInputRecordSchemaLoader = _RecordLoader(CommandInputRecordSchema)
CommandInputEnumSchemaLoader = _RecordLoader(CommandInputEnumSchema)
CommandInputArraySchemaLoader = _RecordLoader(CommandInputArraySchema)
CommandOutputRecordFieldLoader = _RecordLoader(CommandOutputRecordField)
CommandOutputRecordSchemaLoader = _RecordLoader(CommandOutputRecordSchema)
CommandOutputEnumSchemaLoader = _RecordLoader(CommandOutputEnumSchema)
CommandOutputArraySchemaLoader = _RecordLoader(CommandOutputArraySchema)
CommandInputParameterLoader = _RecordLoader(CommandInputParameter)
CommandOutputParameterLoader = _RecordLoader(CommandOutputParameter)
stdinLoader = _EnumLoader(("stdin",))
stdoutLoader = _EnumLoader(("stdout",))
stderrLoader = _EnumLoader(("stderr",))
CommandLineToolLoader = _RecordLoader(CommandLineTool)
DockerRequirementLoader = _RecordLoader(DockerRequirement)
SoftwareRequirementLoader = _RecordLoader(SoftwareRequirement)
SoftwarePackageLoader = _RecordLoader(SoftwarePackage)
DirentLoader = _RecordLoader(Dirent)
InitialWorkDirRequirementLoader = _RecordLoader(InitialWorkDirRequirement)
EnvVarRequirementLoader = _RecordLoader(EnvVarRequirement)
ShellCommandRequirementLoader = _RecordLoader(ShellCommandRequirement)
ResourceRequirementLoader = _RecordLoader(ResourceRequirement)
WorkReuseLoader = _RecordLoader(WorkReuse)
NetworkAccessLoader = _RecordLoader(NetworkAccess)
InplaceUpdateRequirementLoader = _RecordLoader(InplaceUpdateRequirement)
ToolTimeLimitLoader = _RecordLoader(ToolTimeLimit)
ExpressionToolOutputParameterLoader = _RecordLoader(ExpressionToolOutputParameter)
WorkflowInputParameterLoader = _RecordLoader(WorkflowInputParameter)
ExpressionToolLoader = _RecordLoader(ExpressionTool)
LinkMergeMethodLoader = _EnumLoader(("merge_nested", "merge_flattened",))
PickValueMethodLoader = _EnumLoader(("first_non_null", "the_only_non_null", "all_non_null",))
WorkflowOutputParameterLoader = _RecordLoader(WorkflowOutputParameter)
SinkLoader = _RecordLoader(Sink)
WorkflowStepInputLoader = _RecordLoader(WorkflowStepInput)
WorkflowStepOutputLoader = _RecordLoader(WorkflowStepOutput)
ScatterMethodLoader = _EnumLoader(("dotproduct", "nested_crossproduct", "flat_crossproduct",))
WorkflowStepLoader = _RecordLoader(WorkflowStep)
WorkflowLoader = _RecordLoader(Workflow)
SubworkflowFeatureRequirementLoader = _RecordLoader(SubworkflowFeatureRequirement)
ScatterFeatureRequirementLoader = _RecordLoader(ScatterFeatureRequirement)
MultipleInputFeatureRequirementLoader = _RecordLoader(MultipleInputFeatureRequirement)
StepInputExpressionRequirementLoader = _RecordLoader(StepInputExpressionRequirement)
OperationInputParameterLoader = _RecordLoader(OperationInputParameter)
OperationOutputParameterLoader = _RecordLoader(OperationOutputParameter)
OperationLoader = _RecordLoader(Operation)
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 = _URILoader(strtype, True, False, None)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype = _UnionLoader((PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, strtype,))
array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype = _ArrayLoader(union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype = _UnionLoader((PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype,))
typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype, 2)
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')
enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader = _EnumLoader(("record",))
typedsl_enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader_2 = _TypeDSLLoader(enum_d9cba076fca539106791a4f46d198c7fcfbdb779Loader, 2)
uri_array_of_strtype_True_False_None = _URILoader(array_of_strtype, True, False, None)
enum_d961d79c225752b9fadb617367615ab176b47d77Loader = _EnumLoader(("enum",))
typedsl_enum_d961d79c225752b9fadb617367615ab176b47d77Loader_2 = _TypeDSLLoader(enum_d961d79c225752b9fadb617367615ab176b47d77Loader, 2)
uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_False_True_2 = _URILoader(union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_strtype, False, True, 2)
enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader = _EnumLoader(("array",))
typedsl_enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader_2 = _TypeDSLLoader(enum_d062602be0b4b8fd33e69e29a841317b6ab665bcLoader, 2)
File_classLoader = _EnumLoader(("File",))
uri_File_classLoader_False_True_None = _URILoader(File_classLoader, False, True, None)
union_of_None_type_or_strtype = _UnionLoader((None_type, strtype,))
uri_union_of_None_type_or_strtype_False_False_None = _URILoader(union_of_None_type_or_strtype, False, False, 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,))
secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _SecondaryDSLLoader(union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader)
uri_union_of_None_type_or_strtype_True_False_None = _URILoader(union_of_None_type_or_strtype, True, False, None)
Directory_classLoader = _EnumLoader(("Directory",))
uri_Directory_classLoader_False_True_None = _URILoader(Directory_classLoader, False, True, None)
union_of_None_type_or_booltype = _UnionLoader((None_type, booltype,))
union_of_None_type_or_LoadListingEnumLoader = _UnionLoader((None_type, LoadListingEnumLoader,))
array_of_SecondaryFileSchemaLoader = _ArrayLoader(SecondaryFileSchemaLoader)
union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _UnionLoader((None_type, SecondaryFileSchemaLoader, array_of_SecondaryFileSchemaLoader,))
secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _SecondaryDSLLoader(union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader)
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 = _URILoader(union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader, True, False, None)
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 = _URILoader(union_of_None_type_or_strtype_or_ExpressionLoader, True, False, None)
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)
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 = _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)
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)
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 = _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)
union_of_None_type_or_Any_type = _UnionLoader((None_type, Any_type,))
union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _UnionLoader((CommandInputParameterLoader, WorkflowInputParameterLoader, OperationInputParameterLoader,))
array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _ArrayLoader(union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader)
idmap_inputs_array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _IdMapLoader(array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader, 'id', 'type')
union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _UnionLoader((CommandOutputParameterLoader, ExpressionToolOutputParameterLoader, WorkflowOutputParameterLoader, OperationOutputParameterLoader,))
array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _ArrayLoader(union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader)
idmap_outputs_array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _IdMapLoader(array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader, 'id', 'type')
union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _UnionLoader((InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, LoadListingRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, WorkReuseLoader, NetworkAccessLoader, InplaceUpdateRequirementLoader, ToolTimeLimitLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader,))
array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _ArrayLoader(union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader)
union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _UnionLoader((None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader,))
idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader = _IdMapLoader(union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader, 'class', '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_None_type_or_CWLVersionLoader = _UnionLoader((None_type, CWLVersionLoader,))
uri_union_of_None_type_or_CWLVersionLoader_False_True_None = _URILoader(union_of_None_type_or_CWLVersionLoader, False, True, None)
union_of_None_type_or_array_of_strtype = _UnionLoader((None_type, array_of_strtype,))
uri_union_of_None_type_or_array_of_strtype_True_False_None = _URILoader(union_of_None_type_or_array_of_strtype, True, False, None)
uri_strtype_False_True_None = _URILoader(strtype, False, True, None)
union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _UnionLoader((CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader,))
array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _ArrayLoader(union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader)
union_of_strtype_or_ExpressionLoader = _UnionLoader((strtype, ExpressionLoader,))
union_of_None_type_or_booltype_or_ExpressionLoader = _UnionLoader((None_type, booltype, ExpressionLoader,))
union_of_None_type_or_inttype_or_ExpressionLoader = _UnionLoader((None_type, inttype, ExpressionLoader,))
union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader((None_type, strtype, ExpressionLoader, array_of_strtype,))
union_of_None_type_or_ExpressionLoader = _UnionLoader((None_type, ExpressionLoader,))
union_of_None_type_or_CommandLineBindingLoader = _UnionLoader((None_type, CommandLineBindingLoader,))
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)
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 = _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)
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)
union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader((None_type, CommandOutputBindingLoader,))
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 = _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)
union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader((CWLTypeLoader, stdinLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,))
typedsl_union_of_CWLTypeLoader_or_stdinLoader_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_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2)
union_of_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((CWLTypeLoader, stdoutLoader, stderrLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,))
typedsl_union_of_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_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)
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,))
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 = _URILoader(union_of_None_type_or_array_of_strtype, False, False, None)
union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader((None_type, DirentLoader, ExpressionLoader, FileLoader, DirectoryLoader, array_of_union_of_FileLoader_or_DirectoryLoader,))
array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader(union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader)
union_of_ExpressionLoader_or_array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader((ExpressionLoader, array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader,))
array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader)
idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader(array_of_EnvironmentDefLoader, 'envName', 'envValue')
union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader = _UnionLoader((None_type, inttype, floattype, ExpressionLoader,))
union_of_booltype_or_ExpressionLoader = _UnionLoader((booltype, ExpressionLoader,))
union_of_inttype_or_ExpressionLoader = _UnionLoader((inttype, ExpressionLoader,))
union_of_None_type_or_InputBindingLoader = _UnionLoader((None_type, InputBindingLoader,))
array_of_WorkflowInputParameterLoader = _ArrayLoader(WorkflowInputParameterLoader)
idmap_inputs_array_of_WorkflowInputParameterLoader = _IdMapLoader(array_of_WorkflowInputParameterLoader, 'id', 'type')
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_0 = _URILoader(union_of_None_type_or_strtype_or_array_of_strtype, False, False, 0)
union_of_None_type_or_LinkMergeMethodLoader = _UnionLoader((None_type, LinkMergeMethodLoader,))
union_of_None_type_or_PickValueMethodLoader = _UnionLoader((None_type, PickValueMethodLoader,))
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2 = _URILoader(union_of_None_type_or_strtype_or_array_of_strtype, False, False, 2)
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 = _URILoader(union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader, True, False, None)
union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader = _UnionLoader((strtype, CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader,))
union_of_None_type_or_ScatterMethodLoader = _UnionLoader((None_type, ScatterMethodLoader,))
uri_union_of_None_type_or_ScatterMethodLoader_False_True_None = _URILoader(union_of_None_type_or_ScatterMethodLoader, False, True, 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')
array_of_OperationInputParameterLoader = _ArrayLoader(OperationInputParameterLoader)
idmap_inputs_array_of_OperationInputParameterLoader = _IdMapLoader(array_of_OperationInputParameterLoader, 'id', 'type')
array_of_OperationOutputParameterLoader = _ArrayLoader(OperationOutputParameterLoader)
idmap_outputs_array_of_OperationOutputParameterLoader = _IdMapLoader(array_of_OperationOutputParameterLoader, 'id', 'type')
union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader = _UnionLoader((CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader,))
array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader = _ArrayLoader(union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader)
union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader = _UnionLoader((CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader, array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader,))


def load_document(doc, baseuri=None, loadingOptions=None):
    # type: (Any, Optional[str], Optional[LoadingOptions]) -> Any
    if baseuri is None:
        baseuri = file_uri(os.getcwd()) + "/"
    if loadingOptions is None:
        loadingOptions = LoadingOptions()
    return _document_load(union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader, doc, baseuri, loadingOptions)


def load_document_by_string(string, uri, loadingOptions=None):
    # type: (Any, str, Optional[LoadingOptions]) -> Any
    result = yaml.main.round_trip_load(string, preserve_quotes=True)
    add_lc_filename(result, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)
    loadingOptions.idx[uri] = result

    return _document_load(union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader, result, uri, loadingOptions)


def load_document_by_yaml(yaml, uri, loadingOptions=None):
    # type: (Any, str, Optional[LoadingOptions]) -> Any
    '''Shortcut to load via a YAML object.
    yaml: must be from ruamel.yaml.main.round_trip_load with preserve_quotes=True
    '''
    add_lc_filename(yaml, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)
    loadingOptions.idx[uri] = yaml

    return _document_load(union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader, yaml, uri, loadingOptions)
