{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://hamk-uas.github.io/stac-semantics/v0.1.0/schema.json#",
  "title": "Semantics Extension",
  "description": "STAC Semantics Extension: concepts from published vocabularies that describe what a band, data cube variable or dimension, table column or single-variable asset measures. Applies to STAC Items and Collections.",
  "type": "object",
  "required": [
    "stac_extensions",
    "type"
  ],
  "properties": {
    "stac_extensions": {
      "type": "array",
      "contains": {
        "const": "https://hamk-uas.github.io/stac-semantics/v0.1.0/schema.json"
      }
    },
    "type": {
      "$comment": "Catalogs are not in scope: they describe no variables.",
      "type": "string",
      "enum": [
        "Collection",
        "Feature"
      ]
    },
    "assets": {
      "$comment": "Assets of Items and Collections.",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/asset"
      }
    },
    "assetTemplates": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/asset"
      }
    },
    "links": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/noFields"
      }
    },
    "linkTemplates": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/noFields"
      }
    }
  },
  "allOf": [
    {
      "$comment": "No fields at the top level of Items and Collections: dataset-level classification belongs to the Themes extension.",
      "allOf": [
        {
          "$ref": "#/definitions/noFields"
        }
      ]
    }
  ],
  "oneOf": [
    {
      "$comment": "STAC Items. Item properties may contain bands, data cube variables and dimensions and table columns, but no fields of their own.",
      "type": "object",
      "required": [
        "type",
        "properties"
      ],
      "properties": {
        "type": {
          "const": "Feature"
        },
        "properties": {
          "$ref": "#/definitions/container"
        }
      }
    },
    {
      "$comment": "STAC Collections. The top level may contain bands, data cube variables and dimensions and table columns, but no fields of its own.",
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "const": "Collection"
        },
        "item_assets": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/asset"
          }
        },
        "summaries": {
          "$comment": "Summaries describe Item properties, which cannot have fields of this extension.",
          "allOf": [
            {
              "$ref": "#/definitions/noFields"
            }
          ]
        }
      },
      "allOf": [
        {
          "$ref": "#/definitions/container"
        }
      ]
    }
  ],
  "definitions": {
    "sem:concepts": {
      "title": "Concepts",
      "description": "Concepts that describe the variable, band, column, dimension or asset.",
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "$ref": "#/definitions/concept"
      }
    },
    "concept": {
      "title": "Concept Reference",
      "type": "object",
      "required": [
        "uri"
      ],
      "properties": {
        "uri": {
          "description": "Identifier of the concept, as published by its vocabulary. Compared as an exact string.",
          "allOf": [
            {
              "$ref": "#/definitions/iri"
            }
          ]
        },
        "role": {
          "description": "What part of the variable the concept describes. Roles other than variable and unit follow the I-ADOPT framework.",
          "type": "string",
          "enum": [
            "variable",
            "property",
            "object_of_interest",
            "matrix",
            "context_object",
            "constraint",
            "statistical_modifier",
            "unit"
          ],
          "default": "variable"
        },
        "match": {
          "description": "How closely the concept fits what the data represent, following the SKOS mapping properties.",
          "type": "string",
          "enum": [
            "exact",
            "close",
            "broad",
            "narrow",
            "related"
          ],
          "default": "exact"
        },
        "scheme": {
          "description": "The vocabulary (concept scheme) the concept belongs to.",
          "allOf": [
            {
              "$ref": "#/definitions/iri"
            }
          ]
        },
        "id": {
          "description": "The concept's notation or code within the scheme.",
          "type": "string",
          "minLength": 1
        },
        "title": {
          "description": "Human-readable label.",
          "type": "string",
          "minLength": 1
        },
        "description": {
          "description": "Human-readable explanation.",
          "type": "string",
          "minLength": 1
        }
      },
      "patternProperties": {
        "^[a-z0-9_-]+:": {
          "$comment": "Fields that other extensions add to Concept References carry their prefix."
        }
      },
      "additionalProperties": false
    },
    "iri": {
      "$comment": "The pattern requires a scheme for validators that do not check formats.",
      "type": "string",
      "format": "iri",
      "pattern": "^[A-Za-z][A-Za-z0-9+.-]*:[^\\s]+$"
    },
    "fields": {
      "$comment": "Places where the fields are allowed. Unknown fields with the prefix of this extension are rejected.",
      "type": "object",
      "properties": {
        "sem:concepts": {
          "$ref": "#/definitions/sem:concepts"
        }
      },
      "patternProperties": {
        "^(?!sem:)": {}
      },
      "additionalProperties": false
    },
    "noFields": {
      "$comment": "Places where no fields of this extension are allowed.",
      "type": "object",
      "patternProperties": {
        "^sem:": false
      }
    },
    "variables": {
      "$comment": "Objects that each describe one variable: Band Objects, data cube variables and dimensions, and table columns.",
      "type": "object",
      "properties": {
        "bands": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/fields"
          }
        },
        "cube:variables": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/fields"
          }
        },
        "cube:dimensions": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/fields"
          }
        },
        "table:columns": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/fields"
          }
        }
      }
    },
    "asset": {
      "$comment": "Assets, Item Asset Definitions and asset templates: the fields are allowed on the asset and on the variables it contains.",
      "allOf": [
        {
          "$ref": "#/definitions/fields"
        },
        {
          "$ref": "#/definitions/variables"
        }
      ]
    },
    "container": {
      "$comment": "Item properties and Collection top level: the fields are allowed on the variables they contain, not on the object itself.",
      "allOf": [
        {
          "$ref": "#/definitions/noFields"
        },
        {
          "$ref": "#/definitions/variables"
        }
      ]
    }
  }
}
