$base: "https://w3id.org/cwl/salad#"

$namespaces:
  sld:  "https://w3id.org/cwl/salad#"
  dct:  "http://purl.org/dc/terms/"
  rdf:  "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  rdfs: "http://www.w3.org/2000/01/rdf-schema#"
  xsd:  "http://www.w3.org/2001/XMLSchema#"

$graph:

- name: "Semantic_Annotations_for_Linked_Avro_Data"
  type: documentation
  doc:
    - $include: salad.md
    - $import: field_name.yml
    - $import: ident_res.yml
    - $import: link_res.yml
    - $import: vocab_res.yml
    - $include: import_include.md
    - $import: map_res.yml
    - $import: typedsl_res.yml

- name: "Link_Validation"
  type: documentation
  doc: |
    # Link validation

    Once a document has been preprocessed, an implementation may validate
    links.  The link validation traversal may visit fields which the schema
    designates as link fields and check that each URI references an existing
    object in the current document, an imported document, file system, or
    network resource.  Failure to validate links may be a fatal error.  Link
    validation behavior for individual fields may be modified by `identity` and
    `noLinkCheck` in the `jsonldPredicate` section of the field schema.


- name: "Schema_validation"
  type: documentation
  doc: ""


# - name: "JSON_LD_Context"
#   type: documentation
#   doc: |
#     # Generating JSON-LD Context

#     How to generate the json-ld context...


- $import: metaschema_base.yml

- name: JsonldPredicate
  type: record
  doc: |
    Attached to a record field to define how the parent record field is handled for
    URI resolution and JSON-LD context generation.
  fields:
    - name: _id
      type: string?
      jsonldPredicate:
        _id: sld:_id
        _type: "@id"
        identity: true
      doc: |
        The predicate URI that this field corresponds to.
        Corresponds to JSON-LD `@id` directive.
    - name: _type
      type: string?
      doc: |
        The context type hint, corresponds to JSON-LD `@type` directive.

        * If the value of this field is `@id` and `identity` is false or
        unspecified, the parent field must be resolved using the link
        resolution rules.  If `identity` is true, the parent field must be
        resolved using the identifier expansion rules.

        * If the value of this field is `@vocab`, the parent field must be
          resolved using the vocabulary resolution rules.

    - name: _container
      type: string?
      doc: |
        Structure hint, corresponds to JSON-LD `@container` directive.
    - name: identity
      type: boolean?
      doc: |
        If true and `_type` is `@id` this indicates that the parent field must
        be resolved according to identity resolution rules instead of link
        resolution rules.  In addition, the field value is considered an
        assertion that the linked value exists; absence of an object in the loaded document
        with the URI is not an error.
    - name: noLinkCheck
      type: boolean?
      doc: |
        If true, this indicates that link validation traversal must stop at
        this field.  This field (it is is a URI) or any fields under it (if it
        is an object or array) are not subject to link checking.
    - name: mapSubject
      type: string?
      doc: |
        If the value of the field is a JSON object, it must be transformed
        into an array of JSON objects, where each key-value pair from the
        source JSON object is a list item, the list items must be JSON objects,
        and the key is assigned to the field specified by `mapSubject`.
    - name: mapPredicate
      type: string?
      doc: |
        Only applies if `mapSubject` is also provided.  If the value of the
        field is a JSON object, it is transformed as described in `mapSubject`,
        with the addition that when the value of a map item is not an object,
        the item is transformed to a JSON object with the key assigned to the
        field specified by `mapSubject` and the value assigned to the field
        specified by `mapPredicate`.
    - name: refScope
      type: int?
      doc: |
        If the field contains a relative reference, it must be resolved by
        searching for valid document references in each successive parent scope
        in the document fragment.  For example, a reference of `foo` in the
        context `#foo/bar/baz` will first check for the existence of
        `#foo/bar/baz/foo`, followed by `#foo/bar/foo`, then `#foo/foo` and
        then finally `#foo`.  The first valid URI in the search order shall be
        used as the fully resolved value of the identifier.  The value of the
        refScope field is the specified number of levels from the containing
        identifer scope before starting the search, so if `refScope: 2` then
        "baz" and "bar" must be stripped to get the base `#foo` and search
        `#foo/foo` and the `#foo`.  The last scope searched must be the top
        level scope before determining if the identifier cannot be resolved.
    - name: typeDSL
      type: boolean?
      doc: |
        Field must be expanded based on the the Schema Salad type DSL.
    - name: subscope
      type: string?
      doc: |
        Append the subscope to the current scope when performing
        identifier resolution to objects under this field.

- name: SpecializeDef
  type: record
  fields:
    - name: specializeFrom
      type: string
      doc: "The data type to be replaced"
      jsonldPredicate:
        _id: "sld:specializeFrom"
        _type: "@id"
        refScope: 1

    - name: specializeTo
      type: string
      doc: "The new data type to replace with"
      jsonldPredicate:
        _id: "sld:specializeTo"
        _type: "@id"
        refScope: 1


- name: NamedType
  type: record
  abstract: true
  docParent: "#Schema"
  fields:
    - name: name
      type: string
      jsonldPredicate: "@id"
      doc: "The identifier for this type"
    - name: inVocab
      type: boolean?
      doc: |
        By default or if "true", include the short name of this type in the
        vocabulary (the keys of the JSON-LD context).  If false, do not include
        the short name in the vocabulary.


- name: DocType
  type: record
  extends: Documented
  abstract: true
  docParent: "#Schema"
  fields:
    - name: docParent
      type: string?
      doc: |
        Hint to indicate that during documentation generation, documentation
        for this type should appear in a subsection under `docParent`.
      jsonldPredicate:
        _id: "sld:docParent"
        _type: "@id"

    - name: docChild
      type:
        - string?
        - string[]?
      doc: |
        Hint to indicate that during documentation generation, documentation
        for `docChild` should appear in a subsection under this type.
      jsonldPredicate:
        _id: "sld:docChild"
        _type: "@id"

    - name: docAfter
      type: string?
      doc: |
        Hint to indicate that during documentation generation, documentation
        for this type should appear after the `docAfter` section at the same
        level.
      jsonldPredicate:
        _id: "sld:docAfter"
        _type: "@id"


- name: SchemaDefinedType
  type: record
  extends: DocType
  doc: |
    Abstract base for schema-defined types.
  abstract: true
  fields:
    - name: jsonldPredicate
      type:
        - string?
        - JsonldPredicate?
      doc: |
        Annotate this type with linked data context.
      jsonldPredicate: sld:jsonldPredicate

    - name: documentRoot
      type: boolean?
      doc: |
        If true, indicates that the type is a valid at the document root.  At
        least one type in a schema must be tagged with `documentRoot: true`.


- name: SaladRecordField
  type: record
  extends: RecordField
  doc: "A field of a record."
  fields:
    - name: jsonldPredicate
      type:
        - string?
        - JsonldPredicate?
      doc: |
        Annotate this type with linked data context.
      jsonldPredicate: "sld:jsonldPredicate"
    - name: default
      type: Any?
      jsonldPredicate:
        _id: sld:default
        noLinkCheck: true
      doc: |
        The default value to use for this field if the field is missing or "null".


- name: SaladRecordSchema
  docParent: "#Schema"
  type: record
  extends: [NamedType, RecordSchema, SchemaDefinedType]
  documentRoot: true
  specialize:
    RecordField: SaladRecordField
  fields:
    - name: abstract
      type: boolean?
      doc: |
        If true, this record is abstract and may be used as a base for other
        records, but is not valid on its own.

    - name: extends
      type:
        - string?
        - string[]?
      jsonldPredicate:
        _id: "sld:extends"
        _type: "@id"
        refScope: 1
      doc: |
        Indicates that this record inherits fields from one or more base records.

    - name: specialize
      type:
        - SpecializeDef[]?
      doc: |
        Only applies if `extends` is declared.  Apply type specialization using the
        base record as a template.  For each field inherited from the base
        record, replace any instance of the type `specializeFrom` with
        `specializeTo`.
      jsonldPredicate:
        _id: "sld:specialize"
        mapSubject: specializeFrom
        mapPredicate: specializeTo

- name: SaladEnumSchema
  docParent: "#Schema"
  type: record
  extends: [NamedType, EnumSchema, SchemaDefinedType]
  documentRoot: true
  doc: |
    Define an enumerated type.
  fields:
    - name: extends
      type:
        - string?
        - string[]?
      jsonldPredicate:
        _id: "sld:extends"
        _type: "@id"
        refScope: 1
      doc: |
        Indicates that this enum inherits symbols from a base enum.


- name: Documentation
  type: record
  docParent: "#Schema"
  extends: [NamedType, DocType]
  documentRoot: true
  doc: |
    A documentation section.  This type exists to facilitate self-documenting
    schemas but has no role in formal validation.
  fields:
    - name: type
      doc: "Must be `documentation`"
      type:
        type: enum
        symbols:
          - "sld:documentation"
      jsonldPredicate:
        _id: "sld:type"
        _type: "@vocab"
        typeDSL: true
        refScope: 2
