Nanoarguments: Conformance Shapes

Author
Virginia Balseiro
License
CC BY 4.0

Introduction

The Nanoarguments conformance shapes are a SHACL description of what counts as a well-formed Nanoarguments nanopublication, for validating instances produced by the templates or retrieved from the network. They are pure SHACL Core, so any conformant validator runs them.

Shapes

What each shape checks:

  • DiscourseContribution (schema:Statement or schema:Question): exactly one rdf:value; as:inReplyTo at most once; cito:citesAsEvidence repeatable. The CiTO stance predicate is unconstrained for statements; for questions see QuestionStance.
  • QuestionStance (schema:Question): no affirmative stance (cito:supports, cito:agreesWith, cito:extends, cito:confirms).
  • Evidence (sio:SIO_001394): exactly one rdf:value.
  • AssertionProvenance: the assertion is prov:wasAttributedTo an agent; prov:wasDerivedFrom is an IRI when present.
  • Nanopublication: a dct:creator and dct:license; a missing dct:created is a warning, not an error.

The Web Annotation layer of an annotation contribution (the oa:Annotation and its selectors) is validated against the W3C Web Annotation model and its test suite, not re-specified here; Nanoarguments-specific annotation shapes may be added later.

@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <https://schema.org/> .
@prefix cito:   <http://purl.org/spar/cito/> .
@prefix sio:    <http://semanticscience.org/resource/> .
@prefix as:     <https://www.w3.org/ns/activitystreams#> .
@prefix prov:   <http://www.w3.org/ns/prov#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix np:     <http://www.nanopub.org/nschema#> .
@prefix nash:   <https://w3id.org/nanoarguments/shapes/> .

# Nanoarguments conformance shapes (SHACL Core) for a signed nanopublication.
# Validate over the union of the nanopub's four graphs; see shapes.html to run it.

nash:DiscourseContribution a sh:NodeShape ;
  rdfs:label "Discourse contribution (content node)" ;
  sh:targetClass schema:Statement ;
  sh:targetClass schema:Question ;
  sh:property [
    sh:path      rdf:value ;
    sh:name      "statement or question text" ;
    sh:datatype  xsd:string ;
    sh:minCount  1 ;
    sh:maxCount  1 ;
    sh:message   "A discourse contribution needs exactly one rdf:value string." ;
  ] ;
  sh:property [
    sh:path      as:inReplyTo ;
    sh:name      "in reply to" ;
    sh:nodeKind  sh:IRI ;
    sh:maxCount  1 ;
  ] ;
  sh:property [
    sh:path      cito:citesAsEvidence ;
    sh:name      "cites as evidence" ;
    sh:nodeKind  sh:IRI ;
  ] .

nash:QuestionStance a sh:NodeShape ;
  rdfs:label "Question stance (non-affirmative)" ;
  sh:targetClass schema:Question ;
  sh:property [
    sh:path      cito:supports ;
    sh:maxCount  0 ;
    sh:message   "A question must not take an affirmative stance (cito:supports); that would be an assertion." ;
  ] ;
  sh:property [
    sh:path      cito:agreesWith ;
    sh:maxCount  0 ;
    sh:message   "A question must not take an affirmative stance (cito:agreesWith); that would be an assertion." ;
  ] ;
  sh:property [
    sh:path      cito:extends ;
    sh:maxCount  0 ;
    sh:message   "A question must not take an affirmative stance (cito:extends); that would be an assertion." ;
  ] ;
  sh:property [
    sh:path      cito:confirms ;
    sh:maxCount  0 ;
    sh:message   "A question must not take an affirmative stance (cito:confirms); that would be an assertion." ;
  ] .

nash:Evidence a sh:NodeShape ;
  rdfs:label "Evidence finding" ;
  sh:targetClass sio:SIO_001394 ;   # SIO "evidence"
  sh:property [
    sh:path      rdf:value ;
    sh:name      "finding text" ;
    sh:datatype  xsd:string ;
    sh:minCount  1 ;
    sh:maxCount  1 ;
    sh:message   "An evidence finding needs exactly one rdf:value string." ;
  ] .

# The Web Annotation layer (oa:Annotation, oa:SpecificResource, oa:TextQuoteSelector)
# is validated against the W3C Web Annotation model and its test suite, not
# re-specified here. Nanoarguments-specific annotation shapes may be added later.

nash:AssertionProvenance a sh:NodeShape ;
  rdfs:label "Assertion provenance" ;
  sh:targetObjectsOf np:hasAssertion ;
  sh:property [
    sh:path      prov:wasAttributedTo ;
    sh:name      "attributed to" ;
    sh:nodeKind  sh:IRI ;
    sh:minCount  1 ;
    sh:message   "The assertion needs prov:wasAttributedTo an agent." ;
  ] ;
  sh:property [
    sh:path      prov:wasDerivedFrom ;
    sh:name      "derived from" ;
    sh:nodeKind  sh:IRI ;
  ] .

nash:Nanopublication a sh:NodeShape ;
  rdfs:label "Nanopublication pubinfo" ;
  sh:targetClass np:Nanopublication ;
  sh:property [
    sh:path      dct:creator ;
    sh:name      "creator" ;
    sh:nodeKind  sh:IRI ;
    sh:minCount  1 ;
    sh:message   "The nanopublication needs a dct:creator." ;
  ] ;
  sh:property [
    sh:path      dct:license ;
    sh:name      "license" ;
    sh:nodeKind  sh:IRI ;
    sh:minCount  1 ;
    sh:message   "The nanopublication needs a dct:license." ;
  ] ;
  sh:property [
    sh:path      dct:created ;
    sh:name      "created" ;
    sh:datatype  xsd:dateTime ;
    sh:minCount  1 ;
    sh:severity  sh:Warning ;
    sh:message   "The nanopublication has no dct:created timestamp." ;
  ] .

Running the shapes (Python example)

Two of the shapes (AssertionProvenance, Nanopublication) read across a nanopublication's four graphs, so validate the whole nanopublication, not a single extracted graph. The example below uses Python (pySHACL and the nanopub library); np.rdf holds all four graphs, which pySHACL reads across.

import pyshacl
# np.rdf, from the nanopub Python library, holds all four of the nanopub's graphs
conforms, report_graph, report_text = pyshacl.validate(
    np.rdf, shacl_graph="shapes/conformance.shacl.ttl")

A runnable end-to-end example, with a passing and a failing nanopublication, is in notebooks/validation.ipynb.