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#>
 
BASE <https://saref.etsi.org/documentation/>
 
TEMPLATE  <term/classDescription.rqg>( ?class , ?first ) {

  fun:log("classDescription", ?class, ?first)

  TEMPLATE {
    "<a href='#{fun:prefixedIRI(?class)}' title='{?class}'>{fun:prefixedIRI(?class)}</a>"
    "<sup title='{ fun:property(<en.properties>, 'class') }' class='type-c'>c</sup>"
  } WHERE {
    FILTER(ISURI(?class))
  } .

  TEMPLATE {

    IF(!?first, " (", "")

    # see http://www.w3.org/TR/2012/REC-owl2-primer-20121211/#Classes_and_Instances

    TEMPLATE {
      TEMPLATE <term/classDescription.rqg>( ?C , false ) .
      ; separator= " <span class='logic'>and</span> "
    } WHERE {
      ?class owl:intersectionOf / rdf:rest* / rdf:first ?C
    } .

    TEMPLATE {
      TEMPLATE <term/classDescription.rqg>( ?C , false ) .
      ; separator= " <span class='logic'>or</span> "
    } WHERE {
      ?class owl:unionOf / rdf:rest* / rdf:first ?C
    } .

    TEMPLATE {
      " <span class='logic'>not</span> "
      TEMPLATE <term/classDescription.rqg>( ?C , false ) .
    } WHERE {
      ?class owl:complementOf ?C
    } .

    TEMPLATE {
      before= "\{" ;
      TEMPLATE <individualAndLiteralDescription.rqg>( <en.properties> , ?ni ) .
      ; separator= ", "
      ; after= "}" 
    } WHERE {
      ?class owl:oneOf / rdf:rest* / rdf:first ?ni
    } .

    # object property restrictions
    TEMPLATE {

      # universal
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>only</span> "
        TEMPLATE <term/classDescription.rqg>( ?only , false ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:allValuesFrom ?only 
      } .

      # existential
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>( ?property ) .
        " <span class='logic'>some</span> "
        TEMPLATE <term/classDescription.rqg>( ?some , false ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:someValuesFrom ?some
      } .

      # individual value
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>value</span> "
        TEMPLATE <individualAndLiteralDescription.rqg>( <en.properties> , ?value ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:hasValue ?value
      } .

      # local reflexivity
      TEMPLATE {
        " <span class='logic'>has self</span> "
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:hasSelf true
      } .

      # exact cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>exactly</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:cardinality ?cardinality .
      } .

      # qualified exact cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>exactly</span> { ?cardinality } "
        TEMPLATE <term/classDescription.rqg>( ?C , false ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:qualifiedCardinality ?cardinality ;
          owl:onClass ?C .
      } .

      # maximum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>max</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:maxCardinality ?cardinality .
      } .

      # qualified maximum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>max</span> { ?cardinality } "
        TEMPLATE <term/classDescription.rqg>( ?C , false ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:maxQualifiedCardinality ?cardinality ;
          owl:onClass ?C .
      } .

      # minimum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>min</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:minCardinality ?cardinality .
      } .

      # qualified minimum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>min</span> { ?cardinality } "
        TEMPLATE <term/classDescription.rqg>( ?C , false ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:minQualifiedCardinality ?cardinality ;
          owl:onClass ?C .
      } .

    } WHERE { 
      { ?property a owl:ObjectProperty } 
      UNION 
      { ?property owl:inverseOf [] } 
      UNION 
      { [] owl:inverseOf ?property } 
      UNION 
      {
        FILTER( ?property = owl:topObjectProperty || ?property = owl:bottomObjectProperty)
      } 
    } .

    # data property restrictions
    TEMPLATE {

      # universal
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>only</span> "
        TEMPLATE <dataRangeDescription.rqg>( <en.properties> , ?only ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:allValuesFrom ?only 
      } .

      # existential
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>some</span> "
        TEMPLATE <dataRangeDescription.rqg>( <en.properties> , ?some ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:someValuesFrom ?some
      } .

      # individual value
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>value</span> "
        TEMPLATE <individualAndLiteralDescription.rqg>( <en.properties> , ?value ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:hasValue ?value
      } .

      # exact cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>exactly</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:cardinality ?cardinality .
      } .

      # qualified exact cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>exactly</span> { ?cardinality } "
        TEMPLATE <dataRangeDescription.rqg>( <en.properties> , ?D  ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:qualifiedCardinality ?cardinality ;
          owl:onDataRange ?D .
      } .

      # maximum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>max</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:maxCardinality ?cardinality .
      } .

      # qualified maximum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>max</span> { ?cardinality } "
        TEMPLATE <dataRangeDescription.rqg>( <en.properties> , ?D ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:maxQualifiedCardinality ?cardinality ;
          owl:onDataRange ?D .
      } .

      # minimum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>min</span> { ?cardinality } "
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:minCardinality ?cardinality .
      } .

      # qualified minimum cardinality
      TEMPLATE {
        TEMPLATE <term/propertyDescription.rqg>(?property ) .
        " <span class='logic'>min</span> { ?cardinality } "
        TEMPLATE <dataRangeDescription.rqg>( <en.properties> , ?D ) .
      } WHERE {
        ?class owl:onProperty ?property ;
          owl:minQualifiedCardinality ?cardinality ;
          owl:onDataRange ?D .
      } .

    } WHERE { 
      { ?property a owl:DatatypeProperty } 
      UNION 
      {
        FILTER( ?property = owl:topDataProperty || ?property = owl:bottomDataProperty)
      } 
    } .

    IF(!?first, ")", "")

  } WHERE {
    FILTER(ISBLANK(?class))    
  } .


}