#
# 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

from .common_workflow_language_mixins import CommandLineToolMixin, CommandInputParameterMixin, SchemaDefRequirementMixin, CommandLineBindingMixin, CommandOutputParameterMixin


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


class Savable(object):
    @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(object):
    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.wrapper import CacheControl
            from cachecontrol.caches import FileCache

            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("Term '{}' not in vocabulary".format(url))

    return url


class _Loader(object):
    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 "array<{}>".format(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("Expected one of {}".format(self.symbols))


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 _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(
                        "tried {} but".format(t.__class__.__name__), 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):
            doc = [
                expand_url(
                    i,
                    baseuri,
                    loadingOptions,
                    self.scoped_id,
                    self.vocab_term,
                    self.scoped_ref,
                )
                for i in doc
            ]
        if 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 "file:{}{}".format(urlpath, frag)
    else:
        return "file://{}{}".format(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 RecordField(Savable):
    """
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.name = name
        self.doc = doc
        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, 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 `%s`, expected one of: `name`, `doc`, `type`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'RecordField'", None, _errors__)
        return cls(name=name, doc=doc, 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(['name', 'doc', '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_Record_symbolLoader_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 `%s`, expected one of: `fields`, `type`" % (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_symbolLoader_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 `%s`, expected one of: `symbols`, `type`" % (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_Array_symbolLoader_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 `%s`, expected one of: `items`, `type`" % (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'), 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 `%s`, expected one of: `class`, `location`, `path`, `basename`, `dirname`, `nameroot`, `nameext`, `checksum`, `size`, `secondaryFiles`, `format`, `contents`" % (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 `%s`, expected one of: `class`, `location`, `path`, `basename`, `listing`" % (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 SchemaBase(Savable):
    pass


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

    """
    pass


class InputBinding(Savable):
    pass


class OutputBinding(Savable):
    pass


class InputSchema(SchemaBase):
    pass


class OutputSchema(SchemaBase):
    pass


class InputRecordField(RecordField):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        inputBinding=None,  # type: Any
        label=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.name = name
        self.doc = doc
        self.type = type
        self.inputBinding = inputBinding
        self.label = label

    @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, 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 '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
        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

        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 `%s`, expected one of: `name`, `doc`, `type`, `inputBinding`, `label`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputRecordField'", None, _errors__)
        return cls(name=name, doc=doc, type=type, inputBinding=inputBinding, label=label, 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.inputBinding is not None:
            r['inputBinding'] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

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

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

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


class InputRecordSchema(RecordSchema, InputSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=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.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_Record_symbolLoader_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

        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 `%s`, expected one of: `fields`, `type`, `label`, `name`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, 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)

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

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


class InputEnumSchema(EnumSchema, InputSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=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.name = name
        self.inputBinding = inputBinding

    @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_symbolLoader_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 '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 `%s`, expected one of: `symbols`, `type`, `label`, `name`, `inputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, 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.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', 'name', 'inputBinding'])


class InputArraySchema(ArraySchema, InputSchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=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.inputBinding = inputBinding

    @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__ = []
        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_Array_symbolLoader_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 '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 `%s`, expected one of: `items`, `type`, `label`, `inputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'InputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, 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.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)

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

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

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

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


class OutputRecordField(RecordField):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=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.name = name
        self.doc = doc
        self.type = type
        self.outputBinding = outputBinding

    @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, 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 '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 `%s`, expected one of: `name`, `doc`, `type`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputRecordField'", None, _errors__)
        return cls(name=name, doc=doc, 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.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.outputBinding is not None:
            r['outputBinding'] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

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

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


class OutputRecordSchema(RecordSchema, OutputSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=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

    @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 '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_Record_symbolLoader_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

        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 `%s`, expected one of: `fields`, `type`, `label`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, 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)

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

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

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


class OutputEnumSchema(EnumSchema, OutputSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=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.symbols = symbols
        self.type = type
        self.label = label
        self.outputBinding = outputBinding

    @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__ = []
        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_symbolLoader_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 '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 `%s`, expected one of: `symbols`, `type`, `label`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, 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.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)

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

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

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

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


class OutputArraySchema(ArraySchema, OutputSchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=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.items = items
        self.type = type
        self.label = label
        self.outputBinding = outputBinding

    @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__ = []
        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_Array_symbolLoader_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 '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 `%s`, expected one of: `items`, `type`, `label`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, 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.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)

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

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

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

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


class InputParameter(Parameter):
    def __init__(
        self,
        id,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        format=None,  # type: Any
        inputBinding=None,  # type: Any
        default=None,  # type: Any
        type=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.inputBinding = inputBinding
        self.default = default
        self.type = type

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

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_strtype_True_False_None, 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:
                raise ValidationException("Missing id")
        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'), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, 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 '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
        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 'type' in _doc:
            try:
                type = load_field(_doc.get(
                    'type'), typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `type` field is not valid because:",
                        SourceLine(_doc, 'type', str),
                        [e]
                    )
                )
        else:
            type = 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 `%s`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

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

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

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

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

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

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


class OutputParameter(Parameter):
    def __init__(
        self,
        id,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        outputBinding=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.outputBinding = outputBinding
        self.format = format

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

        _doc = copy.copy(doc)
        if hasattr(doc, 'lc'):
            _doc.lc.data = doc.lc.data
            _doc.lc.filename = doc.lc.filename
        _errors__ = []
        if 'id' in _doc:
            try:
                id = load_field(_doc.get(
                    'id'), uri_strtype_True_False_None, 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:
                raise ValidationException("Missing id")
        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'), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, 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 '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
        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 `%s`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'OutputParameter'", None, _errors__)
        return cls(label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, outputBinding=outputBinding, 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.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.outputBinding is not None:
            r['outputBinding'] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

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


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(Savable):
    """

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 `%s`, expected one of: `class`, `expressionLib`" % (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 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.

    """
    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_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader, 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 `%s`, expected one of: `class`, `types`" % (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 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 `%s`, expected one of: `envName`, `envValue`" % (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, 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 `%s`, expected one of: `loadContents`, `position`, `prefix`, `separate`, `itemSeparator`, `valueFrom`, `shellQuote`" % (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(OutputBinding):
    """
Describes how to generate an output parameter based on the files produced
by a CommandLineTool.

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

  - glob
  - loadContents
  - outputEval
  - secondaryFiles

    """
    def __init__(
        self,
        glob=None,  # type: Any
        loadContents=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.glob = glob
        self.loadContents = loadContents
        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 '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 '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 'outputEval' in _doc:
            try:
                outputEval = load_field(_doc.get(
                    'outputEval'), union_of_None_type_or_strtype_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 `%s`, expected one of: `glob`, `loadContents`, `outputEval`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputBinding'", None, _errors__)
        return cls(glob=glob, loadContents=loadContents, 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.glob is not None:
            r['glob'] = save(
                self.glob,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris)

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

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

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

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


class CommandInputRecordField(InputRecordField):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=None,  # type: Any
        inputBinding=None,  # type: Any
        label=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.name = name
        self.doc = doc
        self.type = type
        self.inputBinding = inputBinding
        self.label = label

    @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, 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 '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
        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

        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 `%s`, expected one of: `name`, `doc`, `type`, `inputBinding`, `label`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputRecordField'", None, _errors__)
        return cls(name=name, doc=doc, type=type, inputBinding=inputBinding, label=label, 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.inputBinding is not None:
            r['inputBinding'] = save(
                self.inputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

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

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

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


class CommandInputRecordSchema(InputRecordSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=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.name = name

    @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_Record_symbolLoader_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

        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 `%s`, expected one of: `fields`, `type`, `label`, `name`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, 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)

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

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


class CommandInputEnumSchema(InputEnumSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=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.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_symbolLoader_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 '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 `%s`, expected one of: `symbols`, `type`, `label`, `name`, `inputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, 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.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', 'name', 'inputBinding'])


class CommandInputArraySchema(InputArraySchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=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.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__ = []
        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_Array_symbolLoader_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 '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 `%s`, expected one of: `items`, `type`, `label`, `inputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandInputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, 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.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)

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

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

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

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


class CommandOutputRecordField(OutputRecordField):
    def __init__(
        self,
        name,  # type: Any
        type,  # type: Any
        doc=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.name = name
        self.doc = doc
        self.type = type
        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, 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 '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 `%s`, expected one of: `name`, `doc`, `type`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputRecordField'", None, _errors__)
        return cls(name=name, doc=doc, 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.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.outputBinding is not None:
            r['outputBinding'] = save(
                self.outputBinding,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris)

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

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


class CommandOutputRecordSchema(OutputRecordSchema):
    def __init__(
        self,
        type,  # type: Any
        fields=None,  # type: Any
        label=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.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_Record_symbolLoader_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

        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 `%s`, expected one of: `fields`, `type`, `label`, `name`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputRecordSchema'", None, _errors__)
        return cls(fields=fields, type=type, label=label, 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)

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

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


class CommandOutputEnumSchema(OutputEnumSchema):
    def __init__(
        self,
        symbols,  # type: Any
        type,  # type: Any
        label=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.symbols = symbols
        self.type = type
        self.label = label
        self.outputBinding = outputBinding

    @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__ = []
        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_symbolLoader_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 '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 `%s`, expected one of: `symbols`, `type`, `label`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputEnumSchema'", None, _errors__)
        return cls(symbols=symbols, type=type, label=label, 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.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)

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

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

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

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


class CommandOutputArraySchema(OutputArraySchema):
    def __init__(
        self,
        items,  # type: Any
        type,  # type: Any
        label=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.items = items
        self.type = type
        self.label = label
        self.outputBinding = outputBinding

    @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__ = []
        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_Array_symbolLoader_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 '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 `%s`, expected one of: `items`, `type`, `label`, `outputBinding`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

        if _errors__:
            raise ValidationException("Trying 'CommandOutputArraySchema'", None, _errors__)
        return cls(items=items, type=type, label=label, 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.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)

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

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

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

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


class CommandInputParameter(CommandInputParameterMixin, InputParameter):
    """
An input parameter for a CommandLineTool.
    """
    def __init__(
        self,
        id,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        format=None,  # type: Any
        inputBinding=None,  # type: Any
        default=None,  # type: Any
        type=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.inputBinding = inputBinding
        self.default = default
        self.type = type

    @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_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:
                raise ValidationException("Missing id")
        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'), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, 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 '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
        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 'type' in _doc:
            try:
                type = load_field(_doc.get(
                    'type'), typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `type` field is not valid because:",
                        SourceLine(_doc, 'type', str),
                        [e]
                    )
                )
        else:
            type = 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 `%s`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`" % (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, inputBinding=inputBinding, 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.inputBinding is not None:
            r['inputBinding'] = save(
                self.inputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

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

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

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

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


class CommandOutputParameter(CommandOutputParameterMixin, OutputParameter):
    """
An output parameter for a CommandLineTool.
    """
    def __init__(
        self,
        id,  # type: Any
        label=None,  # type: Any
        secondaryFiles=None,  # type: Any
        streamable=None,  # type: Any
        doc=None,  # type: Any
        outputBinding=None,  # type: Any
        format=None,  # type: Any
        type=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.outputBinding = outputBinding
        self.format = format
        self.type = type

    @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_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:
                raise ValidationException("Missing id")
        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'), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, 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 '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
        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 'type' in _doc:
            try:
                type = load_field(_doc.get(
                    'type'), typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions)
            except ValidationException as e:
                _errors__.append(
                    ValidationException(
                        "the `type` field is not valid because:",
                        SourceLine(_doc, 'type', str),
                        [e]
                    )
                )
        else:
            type = 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 `%s`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `type`" % (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, outputBinding=outputBinding, 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.outputBinding is not None:
            r['outputBinding'] = save(
                self.outputBinding,
                top=False,
                base_url=self.id,
                relative_uris=relative_uris)

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


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
        requirements=None,  # type: Any
        hints=None,  # type: Any
        label=None,  # type: Any
        doc=None,  # type: Any
        cwlVersion=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.inputs = inputs
        self.outputs = outputs
        self.requirements = requirements
        self.hints = hints
        self.label = label
        self.doc = doc
        self.cwlVersion = cwlVersion
        self.class_ = "CommandLineTool"
        self.baseCommand = baseCommand
        self.arguments = arguments
        self.stdin = stdin
        self.stderr = stderr
        self.stdout = stdout
        self.successCodes = successCodes
        self.temporaryFailCodes = temporaryFailCodes
        self.permanentFailCodes = permanentFailCodes

    @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
        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_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader, 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 '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, 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 '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 '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 `%s`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`" % (k),
                            SourceLine(_doc, k, str)
                        )
                    )
                    break

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    attrs = frozenset(['id', 'inputs', 'outputs', 'requirements', 'hints', 'label', 'doc', 'cwlVersion', 'class', 'baseCommand', 'arguments', 'stdin', 'stderr', 'stdout', 'successCodes', 'temporaryFailCodes', 'permanentFailCodes'])


class DockerRequirement(ProcessRequirement):
    """
Indicates that a workflow component should be run in a
[Docker](http://docker.com) container, and specifies how to fetch or build
the image.

If a CommandLineTool lists `DockerRequirement` under
`hints` (or `requirements`), it may (or must) be run in the specified Docker
container.

The platform must first acquire or install the correct Docker image as
specified by `dockerPull`, `dockerImport`, `dockerLoad` or `dockerFile`.

The platform must execute the tool in the container using `docker run` with
the appropriate Docker image and tool command line.

The workflow platform may provide input files and the designated output
directory through the use of volume bind mounts.  The platform should rewrite
file paths in the input object to correspond to the Docker bind mounted
locations. That is, the platform should rewrite values in the parameter context
such as `runtime.outdir`, `runtime.tmpdir` and others to be valid paths
within the container.

When running a tool contained in Docker, the workflow platform must not
assume anything about the contents of the Docker container, such as the
presence or absence of specific software, except to assume that the
generated command line represents a valid command within the runtime
environment of the container.

## Interaction with other requirements

If [EnvVarRequirement](#EnvVarRequirement) is specified alongside a
DockerRequirement, the environment variables must be provided to Docker
using `--env` or `--env-file` and interact with the container's preexisting
environment as defined by Docker.

    """
    def __init__(
        self,
        dockerPull=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 `%s`, expected one of: `class`, `dockerPull`, `dockerLoad`, `dockerFile`, `dockerImport`, `dockerImageId`, `dockerOutputDirectory`" % (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 `%s`, expected one of: `class`, `packages`" % (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'), union_of_None_type_or_array_of_strtype, 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 `%s`, expected one of: `package`, `version`, `specs`" % (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:
            r['specs'] = save(
                self.specs,
                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(['package', 'version', 'specs'])


class Dirent(Savable):
    """
Define a file or subdirectory that must be placed in the designated output
directory prior to executing the command line tool.  May be the result of
executing an expression, such as building a configuration file from a
template.

    """
    def __init__(
        self,
        entry,  # 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 `%s`, expected one of: `entryname`, `entry`, `writable`" % (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 created by the workflow platform in the designated output directory prior to executing the command line tool.
    """
    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_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader, 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 `%s`, expected one of: `class`, `listing`" % (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 `%s`, expected one of: `class`, `envDef`" % (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 `%s`, expected one of: `class`" % (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 permitted
to use. If a node has sufficient resources, multiple jobs may be scheduled
on a single node provided each job's "max" resource requirements are
met. If a job attempts to exceed its "max" resource allocation, an
implementation may deny additional resources, which may result in job
failure.

If "min" is specified but "max" is not, then "max" == "min"
If "max" is specified by "min" is not, then "min" == "max".

It is an error if max < min.

It is an error if the value of any of these fields is negative.

If neither "min" nor "max" is specified for a resource, an implementation may provide a default.

    """
    def __init__(
        self,
        coresMin=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_strtype_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_strtype_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_strtype_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_strtype_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_strtype_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_strtype_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_strtype_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_strtype_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 `%s`, expected one of: `class`, `coresMin`, `coresMax`, `ramMin`, `ramMax`, `tmpdirMin`, `tmpdirMax`, `outdirMin`, `outdirMax`" % (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'])


_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",
    "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",
    "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",
    "File": "https://w3id.org/cwl/cwl#File",
    "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement",
    "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement",
    "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema",
    "InputBinding": "https://w3id.org/cwl/cwl#InputBinding",
    "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema",
    "InputParameter": "https://w3id.org/cwl/cwl#InputParameter",
    "InputRecordField": "https://w3id.org/cwl/cwl#InputRecordField",
    "InputRecordSchema": "https://w3id.org/cwl/cwl#InputRecordSchema",
    "InputSchema": "https://w3id.org/cwl/cwl#InputSchema",
    "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema",
    "OutputBinding": "https://w3id.org/cwl/cwl#OutputBinding",
    "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema",
    "OutputParameter": "https://w3id.org/cwl/cwl#OutputParameter",
    "OutputRecordField": "https://w3id.org/cwl/cwl#OutputRecordField",
    "OutputRecordSchema": "https://w3id.org/cwl/cwl#OutputRecordSchema",
    "OutputSchema": "https://w3id.org/cwl/cwl#OutputSchema",
    "Parameter": "https://w3id.org/cwl/cwl#Parameter",
    "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType",
    "Process": "https://w3id.org/cwl/cwl#Process",
    "ProcessRequirement": "https://w3id.org/cwl/cwl#ProcessRequirement",
    "RecordField": "https://w3id.org/cwl/salad#RecordField",
    "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema",
    "ResourceRequirement": "https://w3id.org/cwl/cwl#ResourceRequirement",
    "SchemaBase": "https://w3id.org/cwl/cwl#SchemaBase",
    "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement",
    "ShellCommandRequirement": "https://w3id.org/cwl/cwl#ShellCommandRequirement",
    "SoftwarePackage": "https://w3id.org/cwl/cwl#SoftwarePackage",
    "SoftwareRequirement": "https://w3id.org/cwl/cwl#SoftwareRequirement",
    "array": "https://w3id.org/cwl/salad#array",
    "boolean": "http://www.w3.org/2001/XMLSchema#boolean",
    "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",
    "float": "http://www.w3.org/2001/XMLSchema#float",
    "int": "http://www.w3.org/2001/XMLSchema#int",
    "long": "http://www.w3.org/2001/XMLSchema#long",
    "null": "https://w3id.org/cwl/salad#null",
    "record": "https://w3id.org/cwl/salad#record",
    "stderr": "https://w3id.org/cwl/cwl#stderr",
    "stdout": "https://w3id.org/cwl/cwl#stdout",
    "string": "http://www.w3.org/2001/XMLSchema#string",
    "v1.0": "https://w3id.org/cwl/cwl#v1.0",
    "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4",
}
_rvocab = {
    "https://w3id.org/cwl/salad#Any": "Any",
    "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema",
    "https://w3id.org/cwl/cwl#CWLType": "CWLType",
    "https://w3id.org/cwl/cwl#CWLVersion": "CWLVersion",
    "https://w3id.org/cwl/cwl#CommandInputArraySchema": "CommandInputArraySchema",
    "https://w3id.org/cwl/cwl#CommandInputEnumSchema": "CommandInputEnumSchema",
    "https://w3id.org/cwl/cwl#CommandInputParameter": "CommandInputParameter",
    "https://w3id.org/cwl/cwl#CommandInputRecordField": "CommandInputRecordField",
    "https://w3id.org/cwl/cwl#CommandInputRecordSchema": "CommandInputRecordSchema",
    "https://w3id.org/cwl/cwl#CommandLineBinding": "CommandLineBinding",
    "https://w3id.org/cwl/cwl#CommandLineTool": "CommandLineTool",
    "https://w3id.org/cwl/cwl#CommandOutputArraySchema": "CommandOutputArraySchema",
    "https://w3id.org/cwl/cwl#CommandOutputBinding": "CommandOutputBinding",
    "https://w3id.org/cwl/cwl#CommandOutputEnumSchema": "CommandOutputEnumSchema",
    "https://w3id.org/cwl/cwl#CommandOutputParameter": "CommandOutputParameter",
    "https://w3id.org/cwl/cwl#CommandOutputRecordField": "CommandOutputRecordField",
    "https://w3id.org/cwl/cwl#CommandOutputRecordSchema": "CommandOutputRecordSchema",
    "https://w3id.org/cwl/cwl#Directory": "Directory",
    "https://w3id.org/cwl/cwl#Dirent": "Dirent",
    "https://w3id.org/cwl/cwl#DockerRequirement": "DockerRequirement",
    "https://w3id.org/cwl/salad#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#File": "File",
    "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement",
    "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement",
    "https://w3id.org/cwl/cwl#InputArraySchema": "InputArraySchema",
    "https://w3id.org/cwl/cwl#InputBinding": "InputBinding",
    "https://w3id.org/cwl/cwl#InputEnumSchema": "InputEnumSchema",
    "https://w3id.org/cwl/cwl#InputParameter": "InputParameter",
    "https://w3id.org/cwl/cwl#InputRecordField": "InputRecordField",
    "https://w3id.org/cwl/cwl#InputRecordSchema": "InputRecordSchema",
    "https://w3id.org/cwl/cwl#InputSchema": "InputSchema",
    "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema",
    "https://w3id.org/cwl/cwl#OutputBinding": "OutputBinding",
    "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema",
    "https://w3id.org/cwl/cwl#OutputParameter": "OutputParameter",
    "https://w3id.org/cwl/cwl#OutputRecordField": "OutputRecordField",
    "https://w3id.org/cwl/cwl#OutputRecordSchema": "OutputRecordSchema",
    "https://w3id.org/cwl/cwl#OutputSchema": "OutputSchema",
    "https://w3id.org/cwl/cwl#Parameter": "Parameter",
    "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType",
    "https://w3id.org/cwl/cwl#Process": "Process",
    "https://w3id.org/cwl/cwl#ProcessRequirement": "ProcessRequirement",
    "https://w3id.org/cwl/salad#RecordField": "RecordField",
    "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema",
    "https://w3id.org/cwl/cwl#ResourceRequirement": "ResourceRequirement",
    "https://w3id.org/cwl/cwl#SchemaBase": "SchemaBase",
    "https://w3id.org/cwl/cwl#SchemaDefRequirement": "SchemaDefRequirement",
    "https://w3id.org/cwl/cwl#ShellCommandRequirement": "ShellCommandRequirement",
    "https://w3id.org/cwl/cwl#SoftwarePackage": "SoftwarePackage",
    "https://w3id.org/cwl/cwl#SoftwareRequirement": "SoftwareRequirement",
    "https://w3id.org/cwl/salad#array": "array",
    "http://www.w3.org/2001/XMLSchema#boolean": "boolean",
    "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",
    "http://www.w3.org/2001/XMLSchema#float": "float",
    "http://www.w3.org/2001/XMLSchema#int": "int",
    "http://www.w3.org/2001/XMLSchema#long": "long",
    "https://w3id.org/cwl/salad#null": "null",
    "https://w3id.org/cwl/salad#record": "record",
    "https://w3id.org/cwl/cwl#stderr": "stderr",
    "https://w3id.org/cwl/cwl#stdout": "stdout",
    "http://www.w3.org/2001/XMLSchema#string": "string",
    "https://w3id.org/cwl/cwl#v1.0": "v1.0",
    "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4",
}

strtype = _PrimitiveLoader((str, str))
inttype = _PrimitiveLoader(int)
floattype = _PrimitiveLoader(float)
booltype = _PrimitiveLoader(bool)
None_type = _PrimitiveLoader(type(None))
Any_type = _AnyLoader()
PrimitiveTypeLoader = _EnumLoader(("null", "boolean", "int", "long", "float", "double", "string",))
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",))
CWLTypeLoader = _EnumLoader(("File", "Directory",))
FileLoader = _RecordLoader(File)
DirectoryLoader = _RecordLoader(Directory)
SchemaBaseLoader = _RecordLoader(SchemaBase)
ParameterLoader = _RecordLoader(Parameter)
ExpressionLoader = _EnumLoader(("ExpressionPlaceholder",))
InputBindingLoader = _RecordLoader(InputBinding)
OutputBindingLoader = _RecordLoader(OutputBinding)
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)
SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement)
EnvironmentDefLoader = _RecordLoader(EnvironmentDef)
CommandLineBindingLoader = _RecordLoader(CommandLineBinding)
CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding)
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)
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)
uri_strtype_True_False_None = _URILoader(strtype, True, False, None)
union_of_None_type_or_strtype = _UnionLoader((None_type, strtype,))
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')
Record_symbolLoader = _EnumLoader(("record",))
typedsl_Record_symbolLoader_2 = _TypeDSLLoader(Record_symbolLoader, 2)
array_of_strtype = _ArrayLoader(strtype)
uri_array_of_strtype_True_False_None = _URILoader(array_of_strtype, True, False, None)
Enum_symbolLoader = _EnumLoader(("enum",))
typedsl_Enum_symbolLoader_2 = _TypeDSLLoader(Enum_symbolLoader, 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)
Array_symbolLoader = _EnumLoader(("array",))
typedsl_Array_symbolLoader_2 = _TypeDSLLoader(Array_symbolLoader, 2)
File_classLoader = _EnumLoader(("File",))
uri_File_classLoader_False_True_None = _URILoader(File_classLoader, False, True, None)
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,))
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_strtype_or_ExpressionLoader = _UnionLoader((strtype, ExpressionLoader,))
array_of_union_of_strtype_or_ExpressionLoader = _ArrayLoader(union_of_strtype_or_ExpressionLoader)
union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader = _UnionLoader((None_type, strtype, ExpressionLoader, array_of_union_of_strtype_or_ExpressionLoader,))
union_of_None_type_or_booltype = _UnionLoader((None_type, booltype,))
union_of_None_type_or_strtype_or_array_of_strtype = _UnionLoader((None_type, strtype, array_of_strtype,))
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)
union_of_None_type_or_CommandLineBindingLoader = _UnionLoader((None_type, CommandLineBindingLoader,))
array_of_InputRecordFieldLoader = _ArrayLoader(InputRecordFieldLoader)
union_of_None_type_or_array_of_InputRecordFieldLoader = _UnionLoader((None_type, array_of_InputRecordFieldLoader,))
idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader = _IdMapLoader(union_of_None_type_or_array_of_InputRecordFieldLoader, 'name', 'type')
uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2 = _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)
union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader((None_type, CommandOutputBindingLoader,))
array_of_OutputRecordFieldLoader = _ArrayLoader(OutputRecordFieldLoader)
union_of_None_type_or_array_of_OutputRecordFieldLoader = _UnionLoader((None_type, array_of_OutputRecordFieldLoader,))
idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader = _IdMapLoader(union_of_None_type_or_array_of_OutputRecordFieldLoader, 'name', 'type')
uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2 = _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_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_Any_type = _UnionLoader((None_type, Any_type,))
union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader((None_type, CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype,))
typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, 2)
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)
array_of_InputParameterLoader = _ArrayLoader(InputParameterLoader)
idmap_inputs_array_of_InputParameterLoader = _IdMapLoader(array_of_InputParameterLoader, 'id', 'type')
array_of_OutputParameterLoader = _ArrayLoader(OutputParameterLoader)
idmap_outputs_array_of_OutputParameterLoader = _IdMapLoader(array_of_OutputParameterLoader, 'id', 'type')
union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader = _UnionLoader((InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader,))
array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader = _ArrayLoader(union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader)
union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader = _UnionLoader((None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader,))
idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader = _IdMapLoader(union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader, '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)
uri_strtype_False_True_None = _URILoader(strtype, False, True, None)
union_of_None_type_or_array_of_strtype = _UnionLoader((None_type, array_of_strtype,))
union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = _UnionLoader((InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader,))
array_of_union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = _ArrayLoader(union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader)
union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader((None_type, strtype, ExpressionLoader, array_of_strtype,))
union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader((CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype,))
array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _ArrayLoader(union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype)
union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader((CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,))
typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2)
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)
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_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader((None_type, CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype,))
typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2)
union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader((None_type, CWLTypeLoader, stdoutLoader, stderrLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype,))
typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader(union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2)
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')
union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _UnionLoader((FileLoader, DirectoryLoader, DirentLoader, strtype, ExpressionLoader,))
array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _ArrayLoader(union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader)
union_of_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader = _UnionLoader((array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader, strtype, ExpressionLoader,))
array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader)
idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader(array_of_EnvironmentDefLoader, 'envName', 'envValue')
union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader = _UnionLoader((None_type, inttype, strtype, ExpressionLoader,))
union_of_CommandLineToolLoader = _UnionLoader((CommandLineToolLoader,))
array_of_union_of_CommandLineToolLoader = _ArrayLoader(union_of_CommandLineToolLoader)
union_of_CommandLineToolLoader_or_array_of_union_of_CommandLineToolLoader = _UnionLoader((CommandLineToolLoader, array_of_union_of_CommandLineToolLoader,))


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_array_of_union_of_CommandLineToolLoader, 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_array_of_union_of_CommandLineToolLoader, result, uri, loadingOptions)
