# SPDX-License-Identifier:  MPL-2.0
# Author: Minh Nguyen (minh@mail.minhnh.com)
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix qudt-quant: <http://qudt.org/vocab/quantitykind/> .
@prefix schema: <https://schema.org/> .
@prefix exec: <https://secorolab.github.io/metamodels/execution-context#> .
@prefix sosa: <http://www.w3.org/ns/sosa/> .
@prefix ssn: <http://www.w3.org/ns/ssn/> .
@prefix agent: <https://secorolab.github.io/metamodels/agent#> .
@prefix geom-struct: <https://comp-rob2b.github.io/metamodels/geometry/structural-entities#> .

exec:NamedSoftwareResourceShape
  a sh:NodeShape ;
  sh:targetClass exec:Package, exec:Library ;
  sh:property [
    sh:path schema:name ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path schema:description ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] .

exec:ResourceWithPathShape
  a sh:NodeShape ;
  sh:targetClass exec:ResourceWithPath ;
  sh:property [
    sh:path exec:path ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

# The execution context is itself typed RealWorld or Simulation; a simulator is the platform it
# is deployed on, and real-world hardware is named per device, on the system realizing it.
exec:ExecutionContextShape
  a sh:NodeShape ;
  sh:targetClass exec:ExecutionContext ;
  sh:or ( [ sh:class exec:RealWorld ] [ sh:class exec:Simulation ] ) ;
  sh:class ssn:Deployment ;
  sh:property [
    sh:path exec:runs-scene ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path exec:timestep ;
    sh:node exec:TimeQuantityShape ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  # A file the run reads rather than carries -- device addresses and credentials change
  # nothing the controller computes and must not travel in an archived run graph.
  sh:property [
    sh:path exec:has-resource ;
    sh:nodeKind sh:IRI ;
    sh:class exec:SystemResource ;
  ] .

# A simulator's name is required — the parser dispatches the backend off it.
exec:SimulationShape
  a sh:NodeShape ;
  sh:targetClass exec:Simulation ;
  sh:property [
    sh:path ssn:deployedOnPlatform ;
    sh:class sosa:Platform ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path ( ssn:deployedOnPlatform schema:name ) ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

exec:TimeQuantityShape
  a sh:NodeShape ;
  sh:class qudt:Quantity ;
  sh:property [
    sh:path qudt:hasQuantityKind ;
    sh:hasValue qudt-quant:Time ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path qudt:unit ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path qudt:value ;
    sh:nodeKind sh:Literal ;
    sh:datatype xsd:double ;
    sh:minExclusive 0.0 ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .



# The hardware standing in for a modelled element. Model-to-reality correspondence is
# outside SSN's scope, so the relation is local; its ends are not. The subject is the
# deployed System, the object the scene element it realizes -- an agent, a kinematic tree,
# or a sensor. Anything else is not an addressable target for a device.
exec:RealizesShape
  a sh:NodeShape ;
  sh:targetSubjectsOf exec:realizes ;
  sh:message "A device realizes an agent, a kinematic tree, or a sensor, and one of them." ;
  sh:class ssn:System ;
  sh:property [
    sh:path exec:realizes ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
    sh:or (
      [ sh:class agent:Agent ]
      [ sh:class geom-struct:KinematicTree ]
      [ sh:class sosa:Sensor ]
    ) ;
  ] .

# One element, one device: two Systems realizing the same element would leave the run with
# no way to say which hardware it is talking to.
exec:RealizedOnceShape
  a sh:NodeShape ;
  sh:targetObjectsOf exec:realizes ;
  sh:message "An element is realized by one device." ;
  sh:property [
    sh:path [ sh:inversePath exec:realizes ] ;
    sh:maxCount 1 ;
  ] .



# A device has to say which hardware it is: without the product, a run has no way to pick
# the driver that talks to it. What the config calls the device is the element it realizes.
exec:DeviceShape
  a sh:NodeShape ;
  sh:targetSubjectsOf exec:realizes ;
  sh:message "A device states the product it is." ;
  sh:property [
    sh:path schema:model ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .
