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

from __future__ import annotations

import copy
import logging
import os
import pathlib
import sys
import tempfile
import uuid as _uuid__  # pylint: disable=unused-import # noqa: F401
import xml.sax  # nosec
from abc import ABCMeta, abstractmethod
from collections.abc import Collection  # pylint: disable=unused-import # noqa: F401
from collections.abc import MutableMapping, MutableSequence, Sequence
from io import StringIO
from itertools import chain
from typing import ClassVar  # pylint: disable=unused-import # noqa: F401
from typing import Any, Final, Generic, TypeAlias, TypeVar, cast
from urllib.parse import quote, urldefrag, urlparse, urlsplit, urlunsplit
from urllib.request import pathname2url

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

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

if sys.version_info >= (3, 11):
    from typing import Self
else:
    from typing_extensions import Self

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

_logger: Final = logging.getLogger("salad")


IdxType: TypeAlias = MutableMapping[str, tuple[Any, "LoadingOptions"]]
S = TypeVar("S", bound="Saveable")


class LoadingOptions:
    idx: Final[IdxType]
    fileuri: Final[str | None]
    baseuri: Final[str]
    namespaces: Final[MutableMapping[str, str]]
    schemas: Final[MutableSequence[str]]
    original_doc: Final[Any | None]
    addl_metadata: Final[MutableMapping[str, Any]]
    fetcher: Final[Fetcher]
    vocab: Final[dict[str, str]]
    rvocab: Final[dict[str, str]]
    cache: Final[CacheType]
    imports: Final[list[str]]
    includes: Final[list[str]]
    no_link_check: Final[bool | None]
    container: Final[str | None]

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

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

        if fileuri is not None:
            temp_fileuri: str | None = fileuri
        else:
            temp_fileuri = copyfrom.fileuri if copyfrom is not None else None
        self.fileuri = temp_fileuri

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

        if namespaces is not None:
            temp_namespaces: MutableMapping[str, str] = namespaces
        else:
            temp_namespaces = copyfrom.namespaces if copyfrom is not None else {}
        self.namespaces = temp_namespaces

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

        if addl_metadata is not None:
            temp_addl_metadata: MutableMapping[str, Any] = addl_metadata
        else:
            temp_addl_metadata = copyfrom.addl_metadata if copyfrom is not None else {}
        self.addl_metadata = temp_addl_metadata

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

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

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

        if container is not None:
            temp_container: str | None = container
        else:
            temp_container = copyfrom.container if copyfrom is not None else None
        self.container = temp_container

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

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

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

        if self.namespaces != {}:
            temp_vocab = _vocab.copy()
            temp_rvocab = _rvocab.copy()
            for k, v in self.namespaces.items():
                temp_vocab[k] = v
                temp_rvocab[v] = k
        else:
            temp_vocab = _vocab
            temp_rvocab = _rvocab
        self.vocab = temp_vocab
        self.rvocab = temp_rvocab

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


@trait
class Saveable(metaclass=ABCMeta):
    """Mark classes than have a save() and fromDoc() function."""

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

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


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


save_type: TypeAlias = (
    None | MutableMapping[str, Any] | MutableSequence[Any] | int | float | bool | str
)


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


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


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

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

    verb_tensage: Final = "is" if len(types3) == 1 else "are"

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


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


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

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

    return newdict


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

    if vocab_term and url in loadingOptions.vocab:
        return url

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

    split1: Final = urlsplit(url)

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

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

    return url


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


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


class _PrimitiveLoader(_Loader):
    def __init__(self, tp: type | tuple[type[str], type[str]]) -> None:
        self.tp: Final = tp

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

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


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

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

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

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

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


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

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

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


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

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

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


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

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

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

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

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

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


class _RecordLoader(_Loader, Generic[S]):
    def __init__(
        self,
        classtype: type[S],
        container: str | None = None,
        no_link_check: bool | None = None,
    ) -> None:
        self.classtype: Final = classtype
        self.container: Final = container
        self.no_link_check: Final = no_link_check

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

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


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

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


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

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

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

        if lc is None:
            lc = []

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

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

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


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

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


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

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

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

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

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

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


class _IdMapLoader(_Loader):
    def __init__(self, inner: _Loader, mapSubject: str, mapPredicate: str | None) -> None:
        self.inner: Final = inner
        self.mapSubject: Final = mapSubject
        self.mapPredicate: Final = mapPredicate

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


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

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

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

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

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

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

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

        return loadingOptions.idx[baseuri]

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

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


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

    doc_url, frg = urldefrag(url)

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

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

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

    return loadingOptions.idx[url]


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


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


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

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

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


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

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


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


@trait
class Documented(Saveable):
    pass


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

    name: str

    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.type_ = type_

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["doc", "name", "type"])


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

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["fields", "type"])


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

    """

    name: str

    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.symbols = symbols
        self.type_ = type_

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["name", "symbols", "type"])


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

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["items", "type"])


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

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["type", "values"])


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

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(["names", "type"])


class JsonldPredicate(Saveable):
    """
    Attached to a record field to define how the parent record field is handled for
    URI resolution and JSON-LD context generation.

    """

    def __init__(
        self,
        _id: Any | None = None,
        _type: Any | None = None,
        _container: Any | None = None,
        identity: Any | None = None,
        noLinkCheck: Any | None = None,
        mapSubject: Any | None = None,
        mapPredicate: Any | None = None,
        refScope: Any | None = None,
        typeDSL: Any | None = None,
        secondaryFilesDSL: Any | None = None,
        subscope: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self._id = _id
        self._type = _type
        self._container = _container
        self.identity = identity
        self.noLinkCheck = noLinkCheck
        self.mapSubject = mapSubject
        self.mapPredicate = mapPredicate
        self.refScope = refScope
        self.typeDSL = typeDSL
        self.secondaryFilesDSL = secondaryFilesDSL
        self.subscope = subscope

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, JsonldPredicate):
            return bool(
                self._id == other._id
                and self._type == other._type
                and self._container == other._container
                and self.identity == other.identity
                and self.noLinkCheck == other.noLinkCheck
                and self.mapSubject == other.mapSubject
                and self.mapPredicate == other.mapPredicate
                and self.refScope == other.refScope
                and self.typeDSL == other.typeDSL
                and self.secondaryFilesDSL == other.secondaryFilesDSL
                and self.subscope == other.subscope
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self._id,
                self._type,
                self._container,
                self.identity,
                self.noLinkCheck,
                self.mapSubject,
                self.mapPredicate,
                self.refScope,
                self.typeDSL,
                self.secondaryFilesDSL,
                self.subscope,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            _id=_id,
            _type=_type,
            _container=_container,
            identity=identity,
            noLinkCheck=noLinkCheck,
            mapSubject=mapSubject,
            mapPredicate=mapPredicate,
            refScope=refScope,
            typeDSL=typeDSL,
            secondaryFilesDSL=secondaryFilesDSL,
            subscope=subscope,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        return _constructed

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self._id is not None:
            u = save_relative_uri(self._id, base_url, True, None, relative_uris)
            r["_id"] = u
        if self._type is not None:
            r["_type"] = save(
                self._type, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self._container is not None:
            r["_container"] = save(
                self._container,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.identity is not None:
            r["identity"] = save(
                self.identity, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.noLinkCheck is not None:
            r["noLinkCheck"] = save(
                self.noLinkCheck,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.mapSubject is not None:
            r["mapSubject"] = save(
                self.mapSubject,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.mapPredicate is not None:
            r["mapPredicate"] = save(
                self.mapPredicate,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.refScope is not None:
            r["refScope"] = save(
                self.refScope, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.typeDSL is not None:
            r["typeDSL"] = save(
                self.typeDSL, top=False, base_url=base_url, relative_uris=relative_uris
            )
        if self.secondaryFilesDSL is not None:
            r["secondaryFilesDSL"] = save(
                self.secondaryFilesDSL,
                top=False,
                base_url=base_url,
                relative_uris=relative_uris,
            )
        if self.subscope is not None:
            r["subscope"] = save(
                self.subscope, 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: ClassVar[Collection[str]] = frozenset(
        [
            "_id",
            "_type",
            "_container",
            "identity",
            "noLinkCheck",
            "mapSubject",
            "mapPredicate",
            "refScope",
            "typeDSL",
            "secondaryFilesDSL",
            "subscope",
        ]
    )


class SpecializeDef(Saveable):
    def __init__(
        self,
        specializeFrom: Any,
        specializeTo: Any,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.specializeFrom = specializeFrom
        self.specializeTo = specializeTo

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SpecializeDef):
            return bool(
                self.specializeFrom == other.specializeFrom
                and self.specializeTo == other.specializeTo
            )
        return False

    def __hash__(self) -> int:
        return hash((self.specializeFrom, self.specializeTo))

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

            specializeFrom = load_field(
                _doc.get("specializeFrom"),
                uri_strtype_False_False_1_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("specializeFrom")
            )

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

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

            specializeTo = load_field(
                _doc.get("specializeTo"),
                uri_strtype_False_False_1_None,
                baseuri,
                loadingOptions,
                lc=_doc.get("specializeTo")
            )

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

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

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

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.specializeFrom is not None:
            u = save_relative_uri(
                self.specializeFrom, base_url, False, 1, relative_uris
            )
            r["specializeFrom"] = u
        if self.specializeTo is not None:
            u = save_relative_uri(self.specializeTo, base_url, False, 1, relative_uris)
            r["specializeTo"] = 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: ClassVar[Collection[str]] = frozenset(["specializeFrom", "specializeTo"])


@trait
class NamedType(Saveable):
    pass


@trait
class DocType(Documented):
    pass


@trait
class SchemaDefinedType(DocType):
    """
    Abstract base for schema-defined types.

    """

    pass


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

    name: str

    def __init__(
        self,
        name: Any,
        type_: Any,
        doc: Any | None = None,
        jsonldPredicate: Any | None = None,
        default: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.doc = doc
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.type_ = type_
        self.jsonldPredicate = jsonldPredicate
        self.default = default

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

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.jsonldPredicate is not None:
            r["jsonldPredicate"] = save(
                self.jsonldPredicate,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.default is not None:
            r["default"] = save(
                self.default, 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: ClassVar[Collection[str]] = frozenset(
        ["doc", "name", "type", "jsonldPredicate", "default"]
    )


class SaladRecordSchema(NamedType, RecordSchema, SchemaDefinedType):
    name: str

    def __init__(
        self,
        name: Any,
        type_: Any,
        inVocab: Any | None = None,
        fields: Any | None = None,
        doc: Any | None = None,
        docParent: Any | None = None,
        docChild: Any | None = None,
        docAfter: Any | None = None,
        jsonldPredicate: Any | None = None,
        documentRoot: Any | None = None,
        abstract: Any | None = None,
        extends: Any | None = None,
        specialize: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.inVocab = inVocab
        self.fields = fields
        self.type_ = type_
        self.doc = doc
        self.docParent = docParent
        self.docChild = docChild
        self.docAfter = docAfter
        self.jsonldPredicate = jsonldPredicate
        self.documentRoot = documentRoot
        self.abstract = abstract
        self.extends = extends
        self.specialize = specialize

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SaladRecordSchema):
            return bool(
                self.name == other.name
                and self.inVocab == other.inVocab
                and self.fields == other.fields
                and self.type_ == other.type_
                and self.doc == other.doc
                and self.docParent == other.docParent
                and self.docChild == other.docChild
                and self.docAfter == other.docAfter
                and self.jsonldPredicate == other.jsonldPredicate
                and self.documentRoot == other.documentRoot
                and self.abstract == other.abstract
                and self.extends == other.extends
                and self.specialize == other.specialize
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.name,
                self.inVocab,
                self.fields,
                self.type_,
                self.doc,
                self.docParent,
                self.docChild,
                self.docAfter,
                self.jsonldPredicate,
                self.documentRoot,
                self.abstract,
                self.extends,
                self.specialize,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            inVocab=inVocab,
            fields=fields,
            type_=type_,
            doc=doc,
            docParent=docParent,
            docChild=docChild,
            docAfter=docAfter,
            jsonldPredicate=jsonldPredicate,
            documentRoot=documentRoot,
            abstract=abstract,
            extends=extends,
            specialize=specialize,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions)
        return _constructed

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.inVocab is not None:
            r["inVocab"] = save(
                self.inVocab, top=False, base_url=self.name, relative_uris=relative_uris
            )
        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.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.docParent is not None:
            u = save_relative_uri(self.docParent, self.name, False, None, relative_uris)
            r["docParent"] = u
        if self.docChild is not None:
            u = save_relative_uri(self.docChild, self.name, False, None, relative_uris)
            r["docChild"] = u
        if self.docAfter is not None:
            u = save_relative_uri(self.docAfter, self.name, False, None, relative_uris)
            r["docAfter"] = u
        if self.jsonldPredicate is not None:
            r["jsonldPredicate"] = save(
                self.jsonldPredicate,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.documentRoot is not None:
            r["documentRoot"] = save(
                self.documentRoot,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.abstract is not None:
            r["abstract"] = save(
                self.abstract,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.extends is not None:
            u = save_relative_uri(self.extends, self.name, False, 1, relative_uris)
            r["extends"] = u
        if self.specialize is not None:
            r["specialize"] = save(
                self.specialize,
                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: ClassVar[Collection[str]] = frozenset(
        [
            "name",
            "inVocab",
            "fields",
            "type",
            "doc",
            "docParent",
            "docChild",
            "docAfter",
            "jsonldPredicate",
            "documentRoot",
            "abstract",
            "extends",
            "specialize",
        ]
    )


class SaladEnumSchema(NamedType, EnumSchema, SchemaDefinedType):
    """
    Define an enumerated type.

    """

    name: str

    def __init__(
        self,
        symbols: Any,
        type_: Any,
        name: Any | None = None,
        inVocab: Any | None = None,
        doc: Any | None = None,
        docParent: Any | None = None,
        docChild: Any | None = None,
        docAfter: Any | None = None,
        jsonldPredicate: Any | None = None,
        documentRoot: Any | None = None,
        extends: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.inVocab = inVocab
        self.symbols = symbols
        self.type_ = type_
        self.doc = doc
        self.docParent = docParent
        self.docChild = docChild
        self.docAfter = docAfter
        self.jsonldPredicate = jsonldPredicate
        self.documentRoot = documentRoot
        self.extends = extends

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SaladEnumSchema):
            return bool(
                self.name == other.name
                and self.inVocab == other.inVocab
                and self.symbols == other.symbols
                and self.type_ == other.type_
                and self.doc == other.doc
                and self.docParent == other.docParent
                and self.docChild == other.docChild
                and self.docAfter == other.docAfter
                and self.jsonldPredicate == other.jsonldPredicate
                and self.documentRoot == other.documentRoot
                and self.extends == other.extends
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.name,
                self.inVocab,
                self.symbols,
                self.type_,
                self.doc,
                self.docParent,
                self.docChild,
                self.docAfter,
                self.jsonldPredicate,
                self.documentRoot,
                self.extends,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            inVocab=inVocab,
            symbols=symbols,
            type_=type_,
            doc=doc,
            docParent=docParent,
            docChild=docChild,
            docAfter=docAfter,
            jsonldPredicate=jsonldPredicate,
            documentRoot=documentRoot,
            extends=extends,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions)
        return _constructed

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.inVocab is not None:
            r["inVocab"] = save(
                self.inVocab, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.symbols is not None:
            u = save_relative_uri(self.symbols, self.name, True, None, relative_uris)
            r["symbols"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.docParent is not None:
            u = save_relative_uri(self.docParent, self.name, False, None, relative_uris)
            r["docParent"] = u
        if self.docChild is not None:
            u = save_relative_uri(self.docChild, self.name, False, None, relative_uris)
            r["docChild"] = u
        if self.docAfter is not None:
            u = save_relative_uri(self.docAfter, self.name, False, None, relative_uris)
            r["docAfter"] = u
        if self.jsonldPredicate is not None:
            r["jsonldPredicate"] = save(
                self.jsonldPredicate,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.documentRoot is not None:
            r["documentRoot"] = save(
                self.documentRoot,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.extends is not None:
            u = save_relative_uri(self.extends, self.name, False, 1, relative_uris)
            r["extends"] = 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: ClassVar[Collection[str]] = frozenset(
        [
            "name",
            "inVocab",
            "symbols",
            "type",
            "doc",
            "docParent",
            "docChild",
            "docAfter",
            "jsonldPredicate",
            "documentRoot",
            "extends",
        ]
    )


class SaladMapSchema(NamedType, MapSchema, SchemaDefinedType):
    """
    Define a map type.

    """

    name: str

    def __init__(
        self,
        name: Any,
        type_: Any,
        values: Any,
        inVocab: Any | None = None,
        doc: Any | None = None,
        docParent: Any | None = None,
        docChild: Any | None = None,
        docAfter: Any | None = None,
        jsonldPredicate: Any | None = None,
        documentRoot: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.inVocab = inVocab
        self.type_ = type_
        self.values = values
        self.doc = doc
        self.docParent = docParent
        self.docChild = docChild
        self.docAfter = docAfter
        self.jsonldPredicate = jsonldPredicate
        self.documentRoot = documentRoot

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SaladMapSchema):
            return bool(
                self.name == other.name
                and self.inVocab == other.inVocab
                and self.type_ == other.type_
                and self.values == other.values
                and self.doc == other.doc
                and self.docParent == other.docParent
                and self.docChild == other.docChild
                and self.docAfter == other.docAfter
                and self.jsonldPredicate == other.jsonldPredicate
                and self.documentRoot == other.documentRoot
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.name,
                self.inVocab,
                self.type_,
                self.values,
                self.doc,
                self.docParent,
                self.docChild,
                self.docAfter,
                self.jsonldPredicate,
                self.documentRoot,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            inVocab=inVocab,
            type_=type_,
            values=values,
            doc=doc,
            docParent=docParent,
            docChild=docChild,
            docAfter=docAfter,
            jsonldPredicate=jsonldPredicate,
            documentRoot=documentRoot,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions)
        return _constructed

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.inVocab is not None:
            r["inVocab"] = save(
                self.inVocab, 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.values is not None:
            u = save_relative_uri(self.values, self.name, False, 2, relative_uris)
            r["values"] = u
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.docParent is not None:
            u = save_relative_uri(self.docParent, self.name, False, None, relative_uris)
            r["docParent"] = u
        if self.docChild is not None:
            u = save_relative_uri(self.docChild, self.name, False, None, relative_uris)
            r["docChild"] = u
        if self.docAfter is not None:
            u = save_relative_uri(self.docAfter, self.name, False, None, relative_uris)
            r["docAfter"] = u
        if self.jsonldPredicate is not None:
            r["jsonldPredicate"] = save(
                self.jsonldPredicate,
                top=False,
                base_url=self.name,
                relative_uris=relative_uris,
            )
        if self.documentRoot is not None:
            r["documentRoot"] = save(
                self.documentRoot,
                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: ClassVar[Collection[str]] = frozenset(
        [
            "name",
            "inVocab",
            "type",
            "values",
            "doc",
            "docParent",
            "docChild",
            "docAfter",
            "jsonldPredicate",
            "documentRoot",
        ]
    )


class SaladUnionSchema(NamedType, UnionSchema, DocType):
    """
    Define a union type.

    """

    name: str

    def __init__(
        self,
        name: Any,
        names: Any,
        type_: Any,
        inVocab: Any | None = None,
        doc: Any | None = None,
        docParent: Any | None = None,
        docChild: Any | None = None,
        docAfter: Any | None = None,
        documentRoot: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.inVocab = inVocab
        self.names = names
        self.type_ = type_
        self.doc = doc
        self.docParent = docParent
        self.docChild = docChild
        self.docAfter = docAfter
        self.documentRoot = documentRoot

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, SaladUnionSchema):
            return bool(
                self.name == other.name
                and self.inVocab == other.inVocab
                and self.names == other.names
                and self.type_ == other.type_
                and self.doc == other.doc
                and self.docParent == other.docParent
                and self.docChild == other.docChild
                and self.docAfter == other.docAfter
                and self.documentRoot == other.documentRoot
            )
        return False

    def __hash__(self) -> int:
        return hash(
            (
                self.name,
                self.inVocab,
                self.names,
                self.type_,
                self.doc,
                self.docParent,
                self.docChild,
                self.docAfter,
                self.documentRoot,
            )
        )

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if _errors__:
            raise ValidationException("", None, _errors__, "*")
        _constructed = cls(
            name=name,
            inVocab=inVocab,
            names=names,
            type_=type_,
            doc=doc,
            docParent=docParent,
            docChild=docChild,
            docAfter=docAfter,
            documentRoot=documentRoot,
            extension_fields=extension_fields,
            loadingOptions=loadingOptions,
        )
        loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions)
        return _constructed

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

        if relative_uris:
            for ef in self.extension_fields:
                r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef]
        else:
            for ef in self.extension_fields:
                r[ef] = self.extension_fields[ef]
        if self.name is not None:
            u = save_relative_uri(self.name, base_url, True, None, relative_uris)
            r["name"] = u
        if self.inVocab is not None:
            r["inVocab"] = save(
                self.inVocab, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.names is not None:
            u = save_relative_uri(self.names, self.name, False, 2, relative_uris)
            r["names"] = u
        if self.type_ is not None:
            r["type"] = save(
                self.type_, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.doc is not None:
            r["doc"] = save(
                self.doc, top=False, base_url=self.name, relative_uris=relative_uris
            )
        if self.docParent is not None:
            u = save_relative_uri(self.docParent, self.name, False, None, relative_uris)
            r["docParent"] = u
        if self.docChild is not None:
            u = save_relative_uri(self.docChild, self.name, False, None, relative_uris)
            r["docChild"] = u
        if self.docAfter is not None:
            u = save_relative_uri(self.docAfter, self.name, False, None, relative_uris)
            r["docAfter"] = u
        if self.documentRoot is not None:
            r["documentRoot"] = save(
                self.documentRoot,
                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: ClassVar[Collection[str]] = frozenset(
        [
            "name",
            "inVocab",
            "names",
            "type",
            "doc",
            "docParent",
            "docChild",
            "docAfter",
            "documentRoot",
        ]
    )


class Documentation(NamedType, DocType):
    """
    A documentation section.  This type exists to facilitate self-documenting
    schemas but has no role in formal validation.

    """

    name: str

    def __init__(
        self,
        name: Any,
        type_: Any,
        inVocab: Any | None = None,
        doc: Any | None = None,
        docParent: Any | None = None,
        docChild: Any | None = None,
        docAfter: Any | None = None,
        extension_fields: MutableMapping[str, Any] | None = None,
        loadingOptions: LoadingOptions | None = None,
    ) -> None:
        if extension_fields:
            self.extension_fields = extension_fields
        else:
            self.extension_fields = CommentedMap()
        if loadingOptions:
            self.loadingOptions = loadingOptions
        else:
            self.loadingOptions = LoadingOptions()
        self.name = name if name is not None else "_:" + str(_uuid__.uuid4())
        self.inVocab = inVocab
        self.doc = doc
        self.docParent = docParent
        self.docChild = docChild
        self.docAfter = docAfter
        self.type_ = type_

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, Documentation):
            return bool(
                self.name == other.name
                and self.inVocab == other.inVocab
                and self.doc == other.doc
                and self.docParent == other.docParent
                and self.docChild == other.docChild
                and self.docAfter == other.docAfter
                and self.type_ == other.type_
            )
        return False

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

    @classmethod
    def fromDoc(
        cls,
        doc: Any,
        baseuri: str,
        loadingOptions: LoadingOptions,
        docRoot: str | None = None
    ) -> Self:
        _doc = copy.copy(doc)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    attrs: ClassVar[Collection[str]] = frozenset(
        ["name", "inVocab", "doc", "docParent", "docChild", "docAfter", "type"]
    )


_vocab = {
    "Any": "https://w3id.org/cwl/salad#Any",
    "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema",
    "DocType": "https://w3id.org/cwl/salad#DocType",
    "Documentation": "https://w3id.org/cwl/salad#Documentation",
    "Documented": "https://w3id.org/cwl/salad#Documented",
    "EnumSchema": "https://w3id.org/cwl/salad#EnumSchema",
    "JsonldPredicate": "https://w3id.org/cwl/salad#JsonldPredicate",
    "MapSchema": "https://w3id.org/cwl/salad#MapSchema",
    "NamedType": "https://w3id.org/cwl/salad#NamedType",
    "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType",
    "RecordField": "https://w3id.org/cwl/salad#RecordField",
    "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema",
    "SaladEnumSchema": "https://w3id.org/cwl/salad#SaladEnumSchema",
    "SaladMapSchema": "https://w3id.org/cwl/salad#SaladMapSchema",
    "SaladRecordField": "https://w3id.org/cwl/salad#SaladRecordField",
    "SaladRecordSchema": "https://w3id.org/cwl/salad#SaladRecordSchema",
    "SaladUnionSchema": "https://w3id.org/cwl/salad#SaladUnionSchema",
    "SchemaDefinedType": "https://w3id.org/cwl/salad#SchemaDefinedType",
    "SpecializeDef": "https://w3id.org/cwl/salad#SpecializeDef",
    "UnionSchema": "https://w3id.org/cwl/salad#UnionSchema",
    "array": "https://w3id.org/cwl/salad#array",
    "boolean": "http://www.w3.org/2001/XMLSchema#boolean",
    "documentation": "https://w3id.org/cwl/salad#documentation",
    "double": "http://www.w3.org/2001/XMLSchema#double",
    "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",
    "map": "https://w3id.org/cwl/salad#map",
    "null": "https://w3id.org/cwl/salad#null",
    "record": "https://w3id.org/cwl/salad#record",
    "string": "http://www.w3.org/2001/XMLSchema#string",
    "union": "https://w3id.org/cwl/salad#union",
}
_rvocab = {
    "https://w3id.org/cwl/salad#Any": "Any",
    "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema",
    "https://w3id.org/cwl/salad#DocType": "DocType",
    "https://w3id.org/cwl/salad#Documentation": "Documentation",
    "https://w3id.org/cwl/salad#Documented": "Documented",
    "https://w3id.org/cwl/salad#EnumSchema": "EnumSchema",
    "https://w3id.org/cwl/salad#JsonldPredicate": "JsonldPredicate",
    "https://w3id.org/cwl/salad#MapSchema": "MapSchema",
    "https://w3id.org/cwl/salad#NamedType": "NamedType",
    "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType",
    "https://w3id.org/cwl/salad#RecordField": "RecordField",
    "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema",
    "https://w3id.org/cwl/salad#SaladEnumSchema": "SaladEnumSchema",
    "https://w3id.org/cwl/salad#SaladMapSchema": "SaladMapSchema",
    "https://w3id.org/cwl/salad#SaladRecordField": "SaladRecordField",
    "https://w3id.org/cwl/salad#SaladRecordSchema": "SaladRecordSchema",
    "https://w3id.org/cwl/salad#SaladUnionSchema": "SaladUnionSchema",
    "https://w3id.org/cwl/salad#SchemaDefinedType": "SchemaDefinedType",
    "https://w3id.org/cwl/salad#SpecializeDef": "SpecializeDef",
    "https://w3id.org/cwl/salad#UnionSchema": "UnionSchema",
    "https://w3id.org/cwl/salad#array": "array",
    "http://www.w3.org/2001/XMLSchema#boolean": "boolean",
    "https://w3id.org/cwl/salad#documentation": "documentation",
    "http://www.w3.org/2001/XMLSchema#double": "double",
    "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#map": "map",
    "https://w3id.org/cwl/salad#null": "null",
    "https://w3id.org/cwl/salad#record": "record",
    "http://www.w3.org/2001/XMLSchema#string": "string",
    "https://w3id.org/cwl/salad#union": "union",
}

strtype: Final = _PrimitiveLoader(str)
inttype: Final = _PrimitiveLoader(int)
floattype: Final = _PrimitiveLoader(float)
booltype: Final = _PrimitiveLoader(bool)
None_type: Final = _PrimitiveLoader(type(None))
Any_type: Final = _AnyLoader()
PrimitiveTypeLoader: Final = _EnumLoader(
    (
        "null",
        "boolean",
        "int",
        "long",
        "float",
        "double",
        "string",
    ),
    "PrimitiveType",
)
"""
Names of salad data types (based on Avro schema declarations).

Refer to the [Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for
detailed information.

null: no value
boolean: a binary value
int: 32-bit signed integer
long: 64-bit signed integer
float: single precision (32-bit) IEEE 754 floating-point number
double: double precision (64-bit) IEEE 754 floating-point number
string: Unicode character sequence
"""
AnyLoader: Final = _EnumLoader(("Any",), "Any")
"""
The **Any** type validates for any non-null value.
"""
RecordFieldLoader: Final = _RecordLoader(RecordField, None, None)
RecordSchemaLoader: Final = _RecordLoader(RecordSchema, None, None)
EnumSchemaLoader: Final = _RecordLoader(EnumSchema, None, None)
ArraySchemaLoader: Final = _RecordLoader(ArraySchema, None, None)
MapSchemaLoader: Final = _RecordLoader(MapSchema, None, None)
UnionSchemaLoader: Final = _RecordLoader(UnionSchema, None, None)
JsonldPredicateLoader: Final = _RecordLoader(JsonldPredicate, None, None)
SpecializeDefLoader: Final = _RecordLoader(SpecializeDef, None, None)
SaladRecordFieldLoader: Final = _RecordLoader(SaladRecordField, None, None)
SaladRecordSchemaLoader: Final = _RecordLoader(SaladRecordSchema, None, None)
SaladEnumSchemaLoader: Final = _RecordLoader(SaladEnumSchema, None, None)
SaladMapSchemaLoader: Final = _RecordLoader(SaladMapSchema, None, None)
SaladUnionSchemaLoader: Final = _RecordLoader(SaladUnionSchema, None, None)
DocumentationLoader: Final = _RecordLoader(Documentation, None, None)
array_of_strtype: Final = _ArrayLoader(strtype)
union_of_None_type_or_strtype_or_array_of_strtype: Final = _UnionLoader(
    (
        None_type,
        strtype,
        array_of_strtype,
    )
)
uri_strtype_True_False_None_None: Final = _URILoader(strtype, True, False, None, None)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype: (
    Final
) = _UnionLoader(
    (
        PrimitiveTypeLoader,
        RecordSchemaLoader,
        EnumSchemaLoader,
        ArraySchemaLoader,
        MapSchemaLoader,
        UnionSchemaLoader,
        strtype,
    )
)
array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype: (
    Final
) = _ArrayLoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype
)
union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype: (
    Final
) = _UnionLoader(
    (
        PrimitiveTypeLoader,
        RecordSchemaLoader,
        EnumSchemaLoader,
        ArraySchemaLoader,
        MapSchemaLoader,
        UnionSchemaLoader,
        strtype,
        array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    )
)
typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2: (
    Final
) = _TypeDSLLoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    2,
    "v1.1",
)
array_of_RecordFieldLoader: Final = _ArrayLoader(RecordFieldLoader)
union_of_None_type_or_array_of_RecordFieldLoader: Final = _UnionLoader(
    (
        None_type,
        array_of_RecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader: Final = _IdMapLoader(
    union_of_None_type_or_array_of_RecordFieldLoader, "name", "type"
)
Record_nameLoader: Final = _EnumLoader(("record",), "Record_name")
typedsl_Record_nameLoader_2: Final = _TypeDSLLoader(Record_nameLoader, 2, "v1.1")
union_of_None_type_or_strtype: Final = _UnionLoader(
    (
        None_type,
        strtype,
    )
)
uri_union_of_None_type_or_strtype_True_False_None_None: Final = _URILoader(
    union_of_None_type_or_strtype, True, False, None, None
)
uri_array_of_strtype_True_False_None_None: Final = _URILoader(
    array_of_strtype, True, False, None, None
)
Enum_nameLoader: Final = _EnumLoader(("enum",), "Enum_name")
typedsl_Enum_nameLoader_2: Final = _TypeDSLLoader(Enum_nameLoader, 2, "v1.1")
uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None: (
    Final
) = _URILoader(
    union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype,
    False,
    True,
    2,
    None,
)
Array_nameLoader: Final = _EnumLoader(("array",), "Array_name")
typedsl_Array_nameLoader_2: Final = _TypeDSLLoader(Array_nameLoader, 2, "v1.1")
Map_nameLoader: Final = _EnumLoader(("map",), "Map_name")
typedsl_Map_nameLoader_2: Final = _TypeDSLLoader(Map_nameLoader, 2, "v1.1")
Union_nameLoader: Final = _EnumLoader(("union",), "Union_name")
typedsl_Union_nameLoader_2: Final = _TypeDSLLoader(Union_nameLoader, 2, "v1.1")
union_of_None_type_or_booltype: Final = _UnionLoader(
    (
        None_type,
        booltype,
    )
)
union_of_None_type_or_inttype: Final = _UnionLoader(
    (
        None_type,
        inttype,
    )
)
uri_strtype_False_False_1_None: Final = _URILoader(strtype, False, False, 1, None)
uri_union_of_None_type_or_strtype_False_False_None_None: Final = _URILoader(
    union_of_None_type_or_strtype, False, False, None, None
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_None_None: Final = (
    _URILoader(
        union_of_None_type_or_strtype_or_array_of_strtype, False, False, None, None
    )
)
union_of_None_type_or_strtype_or_JsonldPredicateLoader: Final = _UnionLoader(
    (
        None_type,
        strtype,
        JsonldPredicateLoader,
    )
)
union_of_None_type_or_Any_type: Final = _UnionLoader(
    (
        None_type,
        Any_type,
    )
)
array_of_SaladRecordFieldLoader: Final = _ArrayLoader(SaladRecordFieldLoader)
union_of_None_type_or_array_of_SaladRecordFieldLoader: Final = _UnionLoader(
    (
        None_type,
        array_of_SaladRecordFieldLoader,
    )
)
idmap_fields_union_of_None_type_or_array_of_SaladRecordFieldLoader: Final = (
    _IdMapLoader(union_of_None_type_or_array_of_SaladRecordFieldLoader, "name", "type")
)
uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None: Final = (
    _URILoader(union_of_None_type_or_strtype_or_array_of_strtype, False, False, 1, None)
)
array_of_SpecializeDefLoader: Final = _ArrayLoader(SpecializeDefLoader)
union_of_None_type_or_array_of_SpecializeDefLoader: Final = _UnionLoader(
    (
        None_type,
        array_of_SpecializeDefLoader,
    )
)
idmap_specialize_union_of_None_type_or_array_of_SpecializeDefLoader: Final = (
    _IdMapLoader(
        union_of_None_type_or_array_of_SpecializeDefLoader,
        "specializeFrom",
        "specializeTo",
    )
)
Documentation_nameLoader: Final = _EnumLoader(("documentation",), "Documentation_name")
typedsl_Documentation_nameLoader_2: Final = _TypeDSLLoader(
    Documentation_nameLoader, 2, "v1.1"
)
union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader: (
    Final
) = _UnionLoader(
    (
        SaladRecordSchemaLoader,
        SaladEnumSchemaLoader,
        SaladMapSchemaLoader,
        SaladUnionSchemaLoader,
        DocumentationLoader,
    )
)
array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader: (
    Final
) = _ArrayLoader(
    union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader
)
union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader_or_array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader: (
    Final
) = _UnionLoader(
    (
        SaladRecordSchemaLoader,
        SaladEnumSchemaLoader,
        SaladMapSchemaLoader,
        SaladUnionSchemaLoader,
        DocumentationLoader,
        array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader,
    )
)


def load_document(
    doc: Any,
    baseuri: str | None = None,
    loadingOptions: LoadingOptions | None = None,
) -> Any:
    if baseuri is None:
        baseuri = file_uri(os.getcwd()) + "/"
    if loadingOptions is None:
        loadingOptions = LoadingOptions()
    result, metadata = _document_load(
        union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader_or_array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader,
        doc,
        baseuri,
        loadingOptions,
    )
    return result


def load_document_with_metadata(
    doc: Any,
    baseuri: str | None = None,
    loadingOptions: LoadingOptions | None = None,
    addl_metadata_fields: MutableSequence[str] | None = None,
) -> Any:
    if baseuri is None:
        baseuri = file_uri(os.getcwd()) + "/"
    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=baseuri)
    return _document_load(
        union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader_or_array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader,
        doc,
        baseuri,
        loadingOptions,
        addl_metadata_fields=addl_metadata_fields,
    )


def load_document_by_string(
    string: Any,
    uri: str,
    loadingOptions: LoadingOptions | None = None,
) -> Any:
    yaml = yaml_no_ts()
    result = yaml.load(string)
    add_lc_filename(result, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)

    result, metadata = _document_load(
        union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader_or_array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader,
        result,
        uri,
        loadingOptions,
    )
    return result


def load_document_by_yaml(
    yaml: Any,
    uri: str,
    loadingOptions: LoadingOptions | None = None,
) -> Any:
    """
    Shortcut to load via a YAML object.
    yaml: must be from ruamel.yaml.main.YAML.load with preserve_quotes=True
    """
    add_lc_filename(yaml, uri)

    if loadingOptions is None:
        loadingOptions = LoadingOptions(fileuri=uri)

    result, metadata = _document_load(
        union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader_or_array_of_union_of_SaladRecordSchemaLoader_or_SaladEnumSchemaLoader_or_SaladMapSchemaLoader_or_SaladUnionSchemaLoader_or_DocumentationLoader,
        yaml,
        uri,
        loadingOptions,
    )
    return result
