@prefix xsd: 	   <http://www.w3.org/2001/XMLSchema#> . 
@prefix rdf: 	   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 
@prefix rdfs: 	   <http://www.w3.org/2000/01/rdf-schema#> . 
@prefix owl: 	   <http://www.w3.org/2002/07/owl#> . 

@prefix skos: 	   <http://www.w3.org/2004/02/skos/core#> . 
@prefix vann: 	   <http://purl.org/vocab/vann/> . 
@prefix dc: 	   <http://purl.org/dc/elements/1.1/> . 
@prefix foaf: 	   <http://xmlns.com/foaf/0.1/> . 
@prefix dcterms:   <http://purl.org/dc/terms/> . 
@prefix cc:        <http://creativecommons.org/ns#> .
@prefix sh: 	   <http://www.w3.org/ns/shacl#> . 
@prefix shsh:      <http://www.w3.org/ns/shacl-shacl#> .

@prefix ex: 	   <http://example.net/ns#> . 

@prefix ottr: 	   <http://ns.ottr.xyz/0.4/> . 

@prefix o-wottr:   <http://spec.ottr.xyz/wOTTR/0.4/tpl/> . 

<> owl:imports <http://spec.ottr.xyz/rOTTR/0.2/types.shacl.ttl> .

ottr:RDFListShape a sh:NodeShape ;
  sh:targetSubjectsOf rdf:first , rdf:rest ;
  sh:node shsh:ListShape ;
  sh:name "RDF lists" ;
  sh:message "RDF lists must be regular linked lists." 
.



ottr:InstanceShape a sh:NodeShape ;
  sh:targetSubjectsOf ottr:of , ottr:arguments , ottr:values ;
  sh:targetObjectsOf ottr:pattern, ottr:annotation ;
  sh:property 
    [ sh:path ottr:of ;
      sh:minCount 1 ;
      sh:maxCount 1 ;
      sh:nodeKind sh:IRI ;
      sh:name "Instance's reference to signature" ;
      sh:message "An instance must have exactly one reference to a signature, which must be an IRI."
    ] ,
    [ sh:path ottr:modifier ;
      sh:maxCount 1 ;
      sh:node _:instanceModifierInList ;
      sh:name "Instance modifier" ;
      sh:message "An instance can only have one modifier, which must be either ottr:cross, ottr:zipMin or ottr:zipMax."
    ];
  sh:xone 
    (
      [ sh:property
        [ sh:path ottr:arguments ;
          sh:minCount 1 ;
          sh:maxCount 1 ;
	  sh:node shsh:ListShape ;
	  sh:property [
	    sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
	    sh:node ottr:ArgumentShape ;
	  ] ;
	  sh:name "Instance argument list" ;
	  sh:message "An instance must have exactly (possibly empty) one argument list or argument value list. The argument list must contain arguments---and not argument values."
        ]  
      ]
      [ sh:property 
        [ sh:path ottr:values ;
          sh:minCount 1;
          sh:maxCount 1 ;
          sh:node shsh:ListShape
        ] ;
        sh:name "Instance argument value list" ;
	sh:message "An instance must have exactly one (possibly empty) argument list or argument value list."
      ]
    ) ;
  ## instance has listExpander if and only if exists argument with modifier.
  ## modelled as (( not A or B ) and ( not B or A))
  sh:and (
    [ sh:or ( [ sh:not _:hasPropertyInstanceModifier ] _:hasPropertyArgumentWithListExpander ) ]
    [ sh:or ( [ sh:not _:hasPropertyArgumentWithListExpander ] _:hasPropertyInstanceModifier ) ]
  )
.

### Some shapes represented by named blank nodes to avoid repetition:

# legal instance modifiers:
_:instanceModifierInList sh:in ( ottr:cross ottr:zipMin ottr:zipMax ) .

# instance has a modifier:
_:hasPropertyInstanceModifier 
  sh:property [ 
    sh:path ottr:modifier ;
    sh:minCount 1 ;
    sh:node _:instanceModifierInList ] .

# instance has an argument with a modifier:
_:hasPropertyArgumentWithListExpander 
  sh:property [
    sh:path ( ottr:arguments [ sh:zeroOrMorePath rdf:rest ] rdf:first ottr:modifier ) ;
    sh:minCount 1 ;
    sh:hasValue ottr:listExpand ] .


ottr:ArgumentShape a sh:NodeShape ;
  sh:targetSubjectsOf ottr:value ;
  ## sh:nodeKind sh:BlankNode ; ## only in strict mode?
  sh:property 
    [ sh:path ottr:modifier ;
      sh:maxCount 1;
      sh:node [ sh:in ( ottr:listExpand ) ] ;
      sh:name "Argument modifier" ;
      sh:message "An argument can only have the modifier ottr:listExpand."
    ] ,
    [ sh:path ottr:value ;
      sh:minCount 1;
      sh:maxCount 1;
      sh:name "Argument value" ;
      sh:message "An argument can only have one value."
    ] ;
  ## if listExpander, then must be blanknode/list
  ## modelled as not A or B.
  sh:or (
    [ sh:not [ sh:path ottr:modifier ; sh:hasValue ottr:listExpand ] ]
    [ sh:path ottr:value ; 
      sh:nodeKind sh:BlankNode ;
      sh:message "An argument with a ottr:listExpand modifier must have a blanknode (possibly representing a list) as value.";
    ]
  ) 
.

ottr:SignatureShape a sh:NodeShape ;
  sh:targetClass ottr:Signature ;
  sh:targetSubjectsOf ottr:parameters, ottr:annotation ;
  sh:class ottr:Signature ;
  sh:nodeKind sh:IRI ;
  sh:message "A signature must have the type ottr:Signature or one of its subclasses, and be identified by an IRI." ;
  sh:property 
    [ sh:path ottr:parameters ;
      sh:minCount 1 ;
      sh:maxCount 1 ;
      sh:node shsh:ListShape ;
      sh:property [
        sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
	sh:node ottr:ParameterShape ;
      ] ;
      sh:name "Signature parameter list" ;
      sh:message "A signature must declare exactly one parameter list, which must contain parameters."
    ]
.

ottr:ParameterShape a sh:NodeShape ;
  sh:targetSubjectsOf ottr:variable, ottr:type, ottr:default ;
  ## sh:nodeKind sh:BlankNode ;  ## only in strict mode?
  sh:property 
    [ sh:path ottr:variable ;
      ##REMOVED sh:nodeKind sh:BlankNode ;  ## only in strict mode?
      sh:minCount 1 ;
      sh:maxCount 1 ;
      sh:name "Parameter variable" ;
      sh:message "A parameter must have exactly one variable.";
    ] ,
    [ sh:path ottr:type ;
      sh:node ottr:TypeListShape ;
      sh:maxCount 1 ;
      sh:name "Parameter type" ;
      sh:message "A parameter can only have one type, which must be a permissible type value."
    ] ,
    [ sh:path ottr:default ;
      sh:maxCount 1 ;
      sh:name "Parameter default value" ;
      sh:message "A parameter can only have one default value."
    ] ,
    [ sh:path ottr:modifier ;
      sh:node [ sh:in ( ottr:optional ottr:nonBlank ) ] ;
      sh:name "Parameter modifier" ;
      sh:message "A parameter can only have the modifiers ottr:optional or ottr:nonBlank."
    ] 
.

ottr:TypeListShape a sh:NodeShape ;
   sh:targetObjectsOf ottr:type ;
   sh:xone 
     (
       [ sh:node shsh:ListShape ;
         sh:property 
           [ sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
	     sh:node ottr:TypeShape ;
	     sh:minCount 1;
           ] ;
         sh:name "Complex parameter type" ;
	 sh:message """Unrecognised complex type. A type is specified either as a list of types, 
	 where the last item in the list must be a basic type, the second last can be a 'least upper bound' 
	 type, and the types preceeding it can be list types."""
       ] 
       [ sh:node ottr:BasicTypeShape ;
         sh:name "Basic parameter type" ;
	 sh:message "Unrecognised basic type. A type is specified either as an RDF list of types or a single basic type."
       ]
     )
.

ottr:TemplateShape a sh:NodeShape ;
  sh:targetClass ottr:Template ;
  sh:targetSubjectsOf ottr:pattern ;
  sh:class ottr:Template .

ottr:BaseTemplateShape a sh:NodeShape ;
  sh:targetClass ottr:BaseTemplate ;
  sh:class ottr:BaseTemplate ;
  sh:property 
    [ sh:path ottr:pattern ;
      sh:maxCount 0 ;
      sh:message "A base template cannot have a pattern."
    ] .

ottr:ModifierShape a sh:NodeShape ;
  sh:targetObjectsOf ottr:modifier ;
  sh:xone 
    ( 
      [ sh:path [ sh:inversePath ottr:modifier ] ;
        sh:node ottr:InstanceShape 
      ]
      [ sh:path [ sh:inversePath ottr:modifier ] ;
        sh:node ottr:ArgumentShape 
      ]
      [ sh:path [ sh:inversePath ottr:modifier ] ;
        sh:node ottr:ParameterShape 
      ]
) .
