PREFIX st:   <http://ns.inria.fr/sparql-template/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX dc: <http://purl.org/dc/elements/1.1/> 
PREFIX fun: <http://w3id.org/sparql-generate/fn/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX swrl: <http://www.w3.org/2003/11/swrl#>
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX iter: <http://w3id.org/sparql-generate/iter/>
PREFIX schema: <http://schema.org/>

BASE <https://saref.etsi.org/documentation/>
 
# See https://www.w3.org/TR/owl2-quick-reference/#Properties 
# Object Property Axioms 
TEMPLATE <term/objectProperty.rqg>( ?op ) {

  """ 
  \n<div class='description'><dl>{st:incr()}
  """


  # characteristics property
  TEMPLATE { 
    before = "\n<p>{ fun:property(<en.properties>, 'hascharacteristics') }: " ;
      fun:property(<en.properties>, ?label)
    ; separator = ", "
    ; after = "</p>"
  } 
  DISTINCT WHERE {
    VALUES (?type ?label)  { 
      ( owl:FunctionalProperty 'functional' )
      ( owl:InverseFunctionalProperty 'inversefunctional' )
      ( owl:ReflexiveProperty 'reflexive' )
      ( owl:IrreflexiveProperty 'irreflexive' )
      ( owl:SymmetricProperty 'symmetric' )
      ( owl:AsymmetricProperty 'asymmetric' )
      ( owl:TransitiveProperty 'transitive' )
    }
    ?op a ?type .
  } .

  # equivalent properties
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hasequivalentproperties') }</dt><dd>" ;
      TEMPLATE <term/propertyDescription.rqg>( ?op2 ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    { ?op owl:equivalentProperty ?op2 }
    UNION
    { ?op2 owl:equivalentProperty ?op }
  } .

  # hassuperproperties
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hassuperproperties') }</dt><dd>" ;
      TEMPLATE <term/propertyDescription.rqg>( ?op2 ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op rdfs:subPropertyOf ?op2
  } .

  # hassubproperties
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hassubproperties') }</dt><dd>" ;
      TEMPLATE <term/propertyDescription.rqg>( ?op2 ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op2 rdfs:subPropertyOf ?op
  } .

  # property domain
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hasdomain') }</dt><dd>" ;
      TEMPLATE <term/classDescription.rqg>( ?c , true ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op rdfs:domain ?c
  } .

  # property domain includes
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'domainIncludes') }</dt><dd>" ;
      TEMPLATE <term/classDescription.rqg>( ?c , true ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op schema:domainIncludes ?c
  } .

  # property range
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hasrange') }</dt><dd>" ;
      TEMPLATE <term/classDescription.rqg>( ?c , true ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op rdfs:range ?c
  } .

  # property range includes
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'rangeIncludes') }</dt><dd>" ;
      TEMPLATE <term/classDescription.rqg>( ?c , true ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op schema:rangeIncludes ?c
  } .

  # inverse properties
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'isinverseof') }</dt><dd>" ;
      TEMPLATE <term/propertyDescription.rqg>( ?op2 ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    { ?op owl:inverseOf ?op2 }
    UNION
    { ?op2 owl:inverseOf ?op }
    FILTER( ISURI(?op2) ) 
  } .

  # property chains
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'hassubpropertychains') }</dt><dd>" ;
    TEMPLATE <term/propertyDescription.rqg>( ?op1 ) .
    TEMPLATE <subSubPropertyChain.rqg>( ?c1 ) .
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  DISTINCT WHERE {
    ?op owl:propertyChainAxiom ?c0 .
    ?c0 rdf:first ?op1 .
    ?c0 rdf:rest ?c1 .
  } .

  # disjoint properties
  TEMPLATE {
    before = "\n<dt>{ fun:property(<en.properties>, 'isdisjointwith') }</dt><dd>" ;
      TEMPLATE <term/propertyDescription.rqg>( ?op2 ) . 
    ; separator = "<br/> "
    ; after = "</dd>"
  } 
  WHERE {
    { ?op owl:propertyDisjointWith ?op2 }
    UNION
    { ?op2 owl:propertyDisjointWith ?op }
  } .

 "\n</dl></div>"

}