@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix oslc_auto: <http://open-services.net/ns/auto#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix prov-ext: <https://secorolab.github.io/metamodels/prov#> .
@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rec: <https://secorolab.github.io/metamodels/rec#> .
@prefix schema: <https://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix spdx: <http://spdx.org/rdf/terms#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

rec:Metric a rdfs:Class ; rdfs:subClassOf qudt:Quantity, prov:Entity .
rec:Host a rdfs:Class ; rdfs:subClassOf prov:Location .

# A run is an execution and an OSLC Automation result, its verdict unavailable until
# complete. Its archive directory and its host are both locations; the directory is
# a file IRI, the host a rec:Host node.
rec:RunExecutionShape
    a sh:NodeShape ;
    sh:targetClass oslc_auto:AutomationResult ;
    sh:targetSubjectsOf oslc_auto:state ;
    sh:class prov-ext:Execution, oslc_auto:AutomationResult ;
    sh:property [
        sh:path oslc_auto:state ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:in ( oslc_auto:new oslc_auto:queued oslc_auto:inProgress
                oslc_auto:canceling oslc_auto:canceled oslc_auto:complete ) ;
    ] ;
    sh:property [
        sh:path oslc_auto:verdict ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:in ( oslc_auto:unavailable oslc_auto:passed oslc_auto:warning
                oslc_auto:failed oslc_auto:error ) ;
    ] ;
    # A verdict other than unavailable is only reached by a complete run.
    sh:or (
        [ sh:property [ sh:path oslc_auto:state ; sh:hasValue oslc_auto:complete ] ]
        [ sh:property [ sh:path oslc_auto:verdict ; sh:hasValue oslc_auto:unavailable ] ]
    ) ;
    sh:property [
        sh:path prov:atLocation ;
        sh:maxCount 2 ;
        sh:nodeKind sh:IRI ;
    ] ;
    sh:property [
        sh:path prov:atLocation ;
        sh:qualifiedValueShape [ sh:class rec:Host ] ;
        sh:qualifiedMaxCount 1 ;
    ] ;
    sh:node prov:ActivityShape ;
    # A run that has not left the queue carries no start time.
    sh:or (
        [ sh:not [ sh:property [
            sh:path oslc_auto:state ;
            sh:in ( oslc_auto:new oslc_auto:queued )
        ] ] ]
        [ sh:property [ sh:path time:hasBeginning ; sh:maxCount 0 ] ]
    ) ;
    # A run in progress or complete has started.
    sh:or (
        [ sh:property [
            sh:path oslc_auto:state ;
            sh:in ( oslc_auto:new oslc_auto:queued oslc_auto:canceling oslc_auto:canceled )
        ] ]
        [ sh:property [ sh:path time:hasBeginning ; sh:minCount 1 ] ]
    ) ;
    # When the run was queued, and the last time it reported itself alive.
    sh:property [
        sh:path rec:queued-time ;
        sh:maxCount 1 ;
        sh:datatype xsd:dateTime ;
    ] ;
    sh:property [
        sh:path rec:heartbeat-time ;
        sh:maxCount 1 ;
        sh:datatype xsd:dateTime ;
    ] ;
    # Whatever the run's main() returned so far; the writer promises no datatype.
    sh:property [
        sh:path rec:result ;
        sh:maxCount 1 ;
        sh:nodeKind sh:Literal ;
    ] ;
    # Stacktrace of the exception that ended a run with a failed or error verdict.
    sh:property [
        sh:path rec:fail-trace ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:or (
        [ sh:property [ sh:path oslc_auto:verdict ; sh:hasValue oslc_auto:failed ] ]
        [ sh:property [ sh:path oslc_auto:verdict ; sh:hasValue oslc_auto:error ] ]
        [ sh:property [ sh:path rec:fail-trace ; sh:maxCount 0 ] ]
    ) .

# An input entity is consumed by the activity that used it, not by the run that
# contains that activity. The software that ran is a prov:SoftwareAgent the run
# prov:wasAssociatedWith, described with the prov-ext package terms.
rec:ResourceUsageShape
    a sh:NodeShape ;
    sh:targetSubjectsOf prov:qualifiedUsage ;
    sh:class prov:Activity ;
    sh:property [
        sh:path prov:used ;
        sh:minCount 1 ;
    ] .

# An output entity the run produced, linked to its generating activity by a
# qualified generation, and pinned by checksum and size as DCAT describes a
# distribution.
rec:ArtefactShape
    a sh:NodeShape ;
    sh:targetSubjectsOf prov:qualifiedGeneration ;
    sh:class prov:Entity ;
    sh:property [
        sh:path prov:wasGeneratedBy ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path prov:qualifiedGeneration ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path spdx:checksum ;
        sh:maxCount 1 ;
        sh:node rec:ChecksumShape ;
    ] ;
    sh:property [
        sh:path dcat:byteSize ;
        sh:maxCount 1 ;
        sh:datatype xsd:nonNegativeInteger ;
    ] .

rec:ChecksumShape
    a sh:NodeShape ;
    sh:class spdx:Checksum ;
    sh:property [
        sh:path spdx:algorithm ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:IRI ;
    ] ;
    sh:property [
        sh:path spdx:checksumValue ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:datatype xsd:hexBinary ;
    ] .

# A metric is a quantity the run generated.
rec:MetricShape
    a sh:NodeShape ;
    sh:targetClass rec:Metric ;
    sh:node prov:EntityShape ;
    sh:property [
        sh:path prov:wasGeneratedBy ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path qudt:hasQuantityKind ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:IRI ;
    ] ;
    sh:property [
        sh:path qudt:value ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:or (
            [ sh:datatype xsd:integer ]
            [ sh:datatype xsd:decimal ]
            [ sh:datatype xsd:double ]
        ) ;
    ] ;
    sh:property [
        sh:path qudt:unit ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:IRI ;
    ] ;
    sh:property [
        sh:path rec:step ;
        sh:maxCount 1 ;
        sh:datatype xsd:integer ;
    ] ;
    # Metric name, since the IRI mangles characters that are illegal in a path.
    sh:property [
        sh:path rdfs:label ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] .

rec:HostShape
    a sh:NodeShape ;
    sh:targetClass rec:Host ;
    sh:property [
        sh:path schema:identifier ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path rec:os ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path rec:runtime ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path rec:cpu ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
    ] .
