@prefix convo: <https://ontology.inferal.com/modules/conversation/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix prof: <http://www.w3.org/ns/dx/prof/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix role: <http://www.w3.org/ns/dx/prof/role/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

convo:ConversationCoreProfile
    a prof:Profile ;
    prof:isProfileOf convo: ;
    prof:hasResource <https://ontology.inferal.com/modules/conversation/profiles/core#constraints> .

<https://ontology.inferal.com/modules/conversation/profiles/core#constraints>
    a prof:ResourceDescriptor ;
    rdfs:label "Conversation Core constraints descriptor"@en ;
    rdfs:comment "Describes the SHACL artifact that validates Conversation Core data."@en ;
    prof:hasArtifact <https://ontology.inferal.com/modules/conversation/profiles/core.ttl> ;
    prof:hasRole role:constraints, role:validation ;
    dcterms:conformsTo <http://www.w3.org/ns/shacl#> ;
    dcterms:format <https://www.iana.org/assignments/media-types/text/turtle> .

convo:CoreContributionShape
    a sh:NodeShape ;
    rdfs:label "core contribution shape"@en ;
    rdfs:comment "Requires each Core contribution to belong to at least one conversation while permitting reuse across conversations."@en ;
    sh:targetClass convo:Contribution ;
    sh:property [
        sh:path [ sh:alternativePath ( convo:contributionOf [ sh:inversePath convo:hasContribution ] ) ] ;
        sh:class convo:Conversation ;
        sh:minCount 1 ;
    ] .

convo:MissingContributionContentWarningShape
    a sh:NodeShape ;
    rdfs:label "missing contribution content warning shape"@en ;
    rdfs:comment "Warns when a Core contribution has neither local content nor text and is not represented as unavailable by a tombstone."@en ;
    sh:targetClass convo:Contribution ;
    sh:severity sh:Warning ;
    sh:sparql [
        sh:message "A Core contribution should carry convo:hasContent or convo:text unless a tombstone records that it is unavailable."@en ;
        sh:select """
            PREFIX convo: <https://ontology.inferal.com/modules/conversation/>
            SELECT $this WHERE {
                FILTER NOT EXISTS { $this convo:hasContent ?content . }
                FILTER NOT EXISTS { $this convo:text ?text . }
                FILTER NOT EXISTS { ?tombstone convo:tombstoneFor $this . }
            }
        """ ;
    ] .

convo:MissingContributionAttributionWarningShape
    a sh:NodeShape ;
    rdfs:label "missing contribution attribution warning shape"@en ;
    rdfs:comment "Warns when a Core contribution has no explicit general or author attribution and is not represented as unavailable by a tombstone."@en ;
    sh:targetClass convo:Contribution ;
    sh:severity sh:Warning ;
    sh:sparql [
        sh:message "A Core contribution should carry prov:wasAttributedTo or convo:authoredBy unless a tombstone records that it is unavailable."@en ;
        sh:select """
            PREFIX convo: <https://ontology.inferal.com/modules/conversation/>
            PREFIX prov: <http://www.w3.org/ns/prov#>
            SELECT $this WHERE {
                FILTER NOT EXISTS { $this prov:wasAttributedTo ?agent . }
                FILTER NOT EXISTS { $this convo:authoredBy ?agent . }
                FILTER NOT EXISTS { ?tombstone convo:tombstoneFor $this . }
            }
        """ ;
    ] .
