@prefix ex: <https://example.com/ontology-migration/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix new: <https://example.com/person/v2/> .
@prefix old: <https://example.com/person/v1/> .
@prefix om: <https://ontology.inferal.com/modules/ontology-migration/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix vann: <http://purl.org/vocab/vann/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

old:v1
    a owl:Ontology ;
    dcterms:title "Example Person Ontology version 1" ;
    dcterms:license <https://creativecommons.org/publicdomain/zero/1.0/> ;
    vann:preferredNamespacePrefix "old" ;
    vann:preferredNamespaceUri "https://example.com/person/v1/" ;
    rdfs:label "Person ontology version 1" ;
    owl:versionInfo "1" .

old:Person
    a rdfs:Class ;
    rdfs:label "version 1 person" ;
    rdfs:comment "A person described using the example version 1 vocabulary." ;
    rdfs:isDefinedBy old:v1 .

old:fullName
    a rdf:Property ;
    rdfs:label "full name" ;
    rdfs:comment "The example version 1 person's full name." ;
    rdfs:domain old:Person ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy old:v1 .

old:status
    a rdf:Property ;
    rdfs:label "status" ;
    rdfs:comment "The example version 1 person's lifecycle status token." ;
    rdfs:domain old:Person ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy old:v1 .

old:legacyCode
    a rdf:Property ;
    rdfs:label "legacy code" ;
    rdfs:comment "An example version 1 property for which this migration set declares no direct target." ;
    rdfs:domain old:Person ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy old:v1 .

new:v2
    a owl:Ontology ;
    dcterms:title "Example Person Ontology version 2" ;
    dcterms:license <https://creativecommons.org/publicdomain/zero/1.0/> ;
    vann:preferredNamespacePrefix "new" ;
    vann:preferredNamespaceUri "https://example.com/person/v2/" ;
    rdfs:label "Person ontology version 2" ;
    owl:versionInfo "2" .

new:Person
    a rdfs:Class ;
    rdfs:label "version 2 person" ;
    rdfs:comment "A person described using the example version 2 vocabulary." ;
    rdfs:isDefinedBy new:v2 .

new:displayName
    a rdf:Property ;
    rdfs:label "display name" ;
    rdfs:comment "The display name of an example version 2 person." ;
    rdfs:domain new:Person ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy new:v2 .

new:active
    a rdf:Property ;
    rdfs:label "active" ;
    rdfs:comment "Whether an example version 2 person is active." ;
    rdfs:domain new:Person ;
    rdfs:range xsd:boolean ;
    rdfs:isDefinedBy new:v2 .

ex:person-v1-to-v2
    a om:OntologyMigrationSet ;
    dcterms:title "Example Person v1 to v2 migration set" ;
    dcterms:license <https://creativecommons.org/publicdomain/zero/1.0/> ;
    vann:preferredNamespacePrefix "ex" ;
    vann:preferredNamespaceUri "https://example.com/ontology-migration/" ;
    rdfs:label "Person v1 to v2 migration set" ;
    rdfs:comment "Three independent additive transformation cases construct version 2 person types, display names, and supported status assertions; each case carries a named post-validation SHACL SPARQL Rule that plans exact retractions for successfully migrated source triples." ;
    om:sourceOntology old:v1 ;
    om:targetOntology new:v2 ;
    om:sourceShapesGraph ex:PersonV1MigrationShapes ;
    om:targetShapesGraph ex:PersonV2Shapes ;
    om:executionShapesGraph ex:person-v1-to-v2-shapes ;
    owl:versionInfo "1" .

ex:person-v1-to-v2-shapes
    a owl:Ontology ;
    dcterms:title "Example Person v1 to v2 execution shapes graph" ;
    dcterms:license <https://creativecommons.org/publicdomain/zero/1.0/> ;
    vann:preferredNamespacePrefix "ex" ;
    vann:preferredNamespaceUri "https://example.com/ontology-migration/" ;
    rdfs:label "Person v1 to v2 execution shapes graph" ;
    rdfs:comment "Identifies the assembled shapes graph whose additive SHACL-AF rules are executed before validation." ;
    sh:entailment sh:Rules ;
    owl:versionInfo "1" .

ex:PersonV2Shapes
    rdfs:label "Person version 2 target shapes graph" ;
    rdfs:comment "Identifies the migration-specific SHACL contract used to validate the final Person version 2 consumer view before any example retraction plan is constructed." .

ex:PersonV1MigrationShapes
    rdfs:label "Person version 1 migration source shapes graph" ;
    rdfs:comment "Identifies the migration-specific SHACL contract used to validate source Person records before any example transformation rule executes." .

ex:PersonTypeCase
    a sh:NodeShape ;
    om:caseOf ex:person-v1-to-v2 ;
    rdfs:label "person type transformation case" ;
    rdfs:comment "Transforms instances of the version 1 Person class into instances of the version 2 Person class." ;
    sh:targetClass old:Person ;
    om:hasRetractionRule ex:RetractPersonType ;
    sh:rule ex:PersonTypeRule .

ex:PersonTypeRule
    a sh:TripleRule ;
    rdfs:label "person type transformation rule" ;
    rdfs:comment "Constructs a version 2 Person type for a version 1 Person focus node." ;
    sh:subject sh:this ;
    sh:predicate rdf:type ;
    sh:object new:Person .

ex:RetractPersonType
    a sh:SPARQLRule ;
    rdfs:label "person type retraction rule" ;
    rdfs:comment "Constructs each source Person type triple whose focus node also has the produced target Person type." ;
    sh:construct """
        PREFIX new: <https://example.com/person/v2/>
        PREFIX old: <https://example.com/person/v1/>
        CONSTRUCT {
            $this a old:Person .
        }
        WHERE {
            $this a old:Person, new:Person .
        }
    """ .

ex:FullNameCase
    a sh:NodeShape ;
    om:caseOf ex:person-v1-to-v2 ;
    rdfs:label "full name transformation case" ;
    rdfs:comment "Copies each version 1 full name value to the version 2 display-name property." ;
    sh:targetSubjectsOf old:fullName ;
    sh:rule ex:FullNameRule .

ex:FullNameRule
    a sh:TripleRule ;
    rdfs:label "full name transformation rule" ;
    rdfs:comment "Constructs version 2 display names from version 1 full names." ;
    sh:subject sh:this ;
    sh:predicate new:displayName ;
    sh:object [ sh:path old:fullName ] .

ex:RetractFullName
    a sh:SPARQLRule ;
    om:retractionRuleOf ex:FullNameCase ;
    rdfs:label "full name retraction rule" ;
    rdfs:comment "Constructs each source full-name triple whose value was copied to the target display-name property." ;
    sh:construct """
        PREFIX new: <https://example.com/person/v2/>
        PREFIX old: <https://example.com/person/v1/>
        CONSTRUCT {
            $this old:fullName ?name .
        }
        WHERE {
            $this old:fullName ?name ;
                  new:displayName ?name .
        }
    """ .

ex:EnabledStatusCase
    a sh:NodeShape ;
    om:caseOf ex:person-v1-to-v2 ;
    rdfs:label "enabled status transformation case" ;
    rdfs:comment "Transforms the explicitly supported version 1 status token enabled; other status values produce no target assertion." ;
    sh:targetSubjectsOf old:status ;
    om:hasRetractionRule ex:RetractEnabledStatus ;
    sh:rule ex:EnabledStatusRule .

ex:EnabledStatusRule
    a sh:SPARQLRule ;
    rdfs:label "enabled status transformation rule" ;
    rdfs:comment "Constructs an active true assertion for the supported enabled source status." ;
    sh:construct """
        PREFIX new: <https://example.com/person/v2/>
        PREFIX old: <https://example.com/person/v1/>
        CONSTRUCT {
            $this new:active true .
        }
        WHERE {
            $this old:status "enabled" .
        }
    """ .

ex:RetractEnabledStatus
    a sh:SPARQLRule ;
    rdfs:label "enabled status retraction rule" ;
    rdfs:comment "Constructs only the supported enabled source-status triple after the corresponding target active assertion exists." ;
    sh:construct """
        PREFIX new: <https://example.com/person/v2/>
        PREFIX old: <https://example.com/person/v1/>
        CONSTRUCT {
            $this old:status "enabled" .
        }
        WHERE {
            $this old:status "enabled" ;
                  new:active true .
        }
    """ .
