psychoinformatics-de / datalad-concepts

Other
3 stars 2 forks source link

Incomplete SHACL export of `any_of` range #179

Open jsheunis opened 1 month ago

jsheunis commented 1 month ago

I picked this up in shacl-vue and traced it back to the following:

https://github.com/psychoinformatics-de/datalad-concepts/blob/main/src/prov/unreleased.yaml#L165-L177:

  influencer:
    slot_uri: dlprov:influencer
    description: >-
      Reference the resource (Entity, Agent, or Activity) whose influence is
      being qualified in a qualified influence pattern.
    any_of:
      - range: Activity
      - range: Agent
      - range: Entity
    exact_mappings:
      - prov:influencer
    broad_mappings:
      - dcterms:relation

It looks like the any_of range doesn't get propagated correctly to the SHACL export. I need to investigate whether LinkML's shaclgen actually deals with this.

jsheunis commented 1 month ago

SHACL's Logical Constraint Components can be used to achieve this. The resulting SHACL shape should be something like:

@prefix ex: <http://example.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

ex:InfluencerShape
    a sh:NodeShape ;
    sh:property [
        sh:path ex:influencer ;
        sh:or (
            [ sh:class ex:Activity ]
            [ sh:class ex:Agent ]
            [ sh:class ex:Entity ]
        ) ;
    ] ;
    sh:description "Reference to the resource (Entity, Agent, or Activity) whose influence is being qualified in a qualified influence pattern." .
jsheunis commented 1 month ago

Actually looks like shaclgen is trying to account for any_of here: https://github.com/linkml/linkml/blob/4a2e6f7af1130c9837b46231f2d4d5145985d2fc/linkml/generators/shaclgen.py#L136C39-L136C46

jsheunis commented 1 month ago

Updated to latest version of linkml and this seems to be resolved:

sh:property [ sh:description "Reference the resource (Entity, Agent, or Activity) whose influence is being qualified in a qualified influence pattern." ;
            sh:maxCount 1 ;
            sh:or ( [ sh:class dlprov:Activity ] [ sh:class dlprov:Agent ] [ sh:class dlprov:Entity ] ) ;
            sh:order 0 ;
            sh:path dlprov:influencer ],