GRValidator Implemented E19

Error 19

E19: Check that certain properties should be used only once for the same object (i.e. the max. cardinality is 1). However, this is not formally specified in the ontology --> Datatype properties

Validator Tool: Step # 31

Error Message

Cardinalities must follow the specification of GoodRelations Ontology.

Specific examples:

  • Check for lacking UnitsOfMeasurement everywhere, exactly one. (Validator Tool: Step # 13)
  • Check for quantity spec in the bundle. (amountOfThisGood is mandatory), exactly one. (Validator Tool: Step # 15)
  • Check that all PriceSpecifications have exactly one hasCurrency Attribute. (Validator Tool: Step # 22)

Potential Problem

Care must be taken that cardinalities in object properties (from a class to a class) follow the prime suggestions.

Examples of Wrong Data

No gr:ammountOfThisGood is included (According to the GR prime: amountOfThisGood (1..1), exaclty one should be specified, validation # 1 in the SPARQL section)

@prefix toy: <http://www.heppnetz.de/ontologies/examples/toy#> .
@prefix protege: <http://protege.stanford.edu/plugins/owl/protege#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://www.heppnetz.de/ontologies/examples/gr> rdf:type owl:Ontology ;
    owl:imports <http://www.heppnetz.de/ontologies/examples/toy> ,
        <http://purl.org/goodrelations/v1> .
<http://www.heppnetz.de/ontologies/examples/gr#ElectronicsCom> rdf:type gr:BusinessEntity ;
    gr:legalName "Electronics.com Ltd."^^<&xsd;string> ;
    rdfs:seeAlso "" ;
    gr:offers <http://www.heppnetz.de/ontologies/examples/gr#Offering_1> .
<http://www.heppnetz.de/ontologies/examples/gr#mySony100TVSet> rdf:type gr:ActualProductOrServiceInstance ,
        <http://www.heppnetz.de/ontologies/examples/&toy;TVSet> ;
    toy:hasScreenSize <http://www.heppnetz.de/ontologies/examples/gr#QuantitativeValueFloat_1> .
<http://www.heppnetz.de/ontologies/examples/gr#Offering_1> rdf:type gr:Offering ;
    gr:hasPriceSpecification <http://www.heppnetz.de/ontologies/examples/gr#UnitPriceSpecification_1> ;
    gr:hasBusinessFunction <http://www.heppnetz.de/ontologies/examples/&gr;Sell> ;
    gr:includesObject <http://www.heppnetz.de/ontologies/examples/gr#TypeAndQuantityNode_1> .
<http://www.heppnetz.de/ontologies/examples/gr#QuantitativeValueFloat_1> rdf:type gr:QuantitativeValueFloat ;
    gr:hasValueFloat "30.0"^^<&xsd;float> ;
    gr:hasUnitOfMeasurement "CMT"^^<&xsd;string> .
<http://www.heppnetz.de/ontologies/examples/gr#TypeAndQuantityNode_1> rdf:type gr:TypeAndQuantityNode ;
    gr:hasUnitOfMeasurement "C62"@en ;
    gr:typeOfGood <http://www.heppnetz.de/ontologies/examples/gr#mySony100TVSet> .
<http://www.heppnetz.de/ontologies/examples/gr#UnitPriceSpecification_1> rdf:type gr:UnitPriceSpecification ;
    gr:hasCurrencyValue "200.0"^^<&xsd;float> ;
    gr:hasUnitOfMeasurement "C62"^^<&xsd;string> ;
    gr:hasCurrency "EUR"^^<&xsd;string>

More than one gr:hasCurrency is included (According to the GR prime: hasCurrency (1..1), exaclty one should be specified, validation # 6 in the SPARQL section)

@prefix toy: <http://www.heppnetz.de/ontologies/examples/toy#> .
@prefix protege: <http://protege.stanford.edu/plugins/owl/protege#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://www.heppnetz.de/ontologies/examples/gr> rdf:type owl:Ontology ;
    owl:imports <http://www.heppnetz.de/ontologies/examples/toy> ,
        <http://purl.org/goodrelations/v1> .
<http://www.heppnetz.de/ontologies/examples/gr#ElectronicsCom> rdf:type gr:BusinessEntity ;
    gr:legalName "Electronics.com Ltd."^^<&xsd;string> ;
    rdfs:seeAlso "" ;
    gr:offers <http://www.heppnetz.de/ontologies/examples/gr#Offering_1> .
<http://www.heppnetz.de/ontologies/examples/gr#mySony100TVSet> rdf:type gr:ActualProductOrServiceInstance ,
        <http://www.heppnetz.de/ontologies/examples/&toy;TVSet> ;
    toy:hasScreenSize <http://www.heppnetz.de/ontologies/examples/gr#QuantitativeValueFloat_1> .
<http://www.heppnetz.de/ontologies/examples/gr#Offering_1> rdf:type gr:Offering ;
    gr:hasPriceSpecification <http://www.heppnetz.de/ontologies/examples/gr#UnitPriceSpecification_1> ;
    gr:hasBusinessFunction <http://www.heppnetz.de/ontologies/examples/&gr;Sell> ;
    gr:includesObject <http://www.heppnetz.de/ontologies/examples/gr#TypeAndQuantityNode_1> .
<http://www.heppnetz.de/ontologies/examples/gr#QuantitativeValueFloat_1> rdf:type gr:QuantitativeValueFloat ;
    gr:hasValueFloat "30.0"^^<&xsd;float> ;
    gr:hasUnitOfMeasurement "CMT"^^<&xsd;string> .
<http://www.heppnetz.de/ontologies/examples/gr#TypeAndQuantityNode_1> rdf:type gr:TypeAndQuantityNode ;
    gr:hasUnitOfMeasurement "C62"@en ;
    gr:typeOfGood <http://www.heppnetz.de/ontologies/examples/gr#mySony100TVSet> .
<http://www.heppnetz.de/ontologies/examples/gr#UnitPriceSpecification_1> rdf:type gr:UnitPriceSpecification ;
    gr:hasCurrencyValue "200.0"^^<&xsd;float> ;
    gr:hasUnitOfMeasurement "C62"^^<&xsd;string> ;
    gr:hasCurrency "EUR"^^<&xsd;string> ,
        "COP"^^<&xsd;string> .

SPARQL Query

From properties 1 to 13 (only those with cardinality restrictions, deprecated are not included)

PREFIX gr:<http://purl.org/goodrelations/v1#>
#Datatype properties cardinalities
SELECT distinct ?object
WHERE {
# 1. amountOfThisGood (1..1), only count = 1 is OK, check count != 1 --line 5
  {
    ?object a gr:TypeAndQuantityNode .
    FILTER (1 != (
      SELECT count(?amount)
      WHERE {
          ?object gr:amountOfThisGood ?amount
      }
    ))
  }
# 2. closes (1..1), only count = 1 is OK, check count != 1  --line 15
  UNION {
    ?object a gr:OpeningHoursSpecification .
    FILTER (1 != (
      SELECT count(?closes)
      WHERE {
          ?object gr:closes ?closes
      }
    ))
  }
# 4. durationOfWarrantyInMonths (0..1), count = 0 and count = 1 is OK, check count >= 2  --line 25
  UNION {
    ?object a gr:WarrantyPromise .
    FILTER (2 <= (
      SELECT count(?durationOfWarrantyInMonths)
      WHERE {
          ?object gr:durationOfWarrantyInMonths ?durationOfWarrantyInMonths
      }
    ))
  }
# 6. hasCurrency (1..1), only count = 1 is OK, check count != 1  --line 35
  UNION { #PriceSpecification
    ?object a gr:PriceSpecification .
    FILTER (1 != (
      SELECT count(?hasCurrency)
      WHERE {
          ?object gr:hasCurrency ?hasCurrency
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?hasCurrency)
      WHERE {
          ?object gr:hasCurrency ?hasCurrency
      }
    ))
  } UNION { #PaymentChargeSpecification
    ?object a gr:PaymentChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasCurrency)
      WHERE {
          ?object gr:hasCurrency ?hasCurrency
      }
    ))
  } UNION { #DeliveryChargeSpecification
    ?object a gr:DeliveryChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasCurrency)
      WHERE {
          ?object gr:hasCurrency ?hasCurrency
      }
    ))
  }
# 7. hasCurrencyValue (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 69
  UNION { #PriceSpecification
    ?object a gr:PriceSpecification .
    FILTER (2 <= (
      SELECT count(?hasCurrencyValue)
      WHERE {
          ?object gr:hasCurrencyValue ?hasCurrencyValue
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (2 <= (
      SELECT count(?hasCurrencyValue)
      WHERE {
          ?object gr:hasCurrencyValue ?hasCurrencyValue
      }
    ))
  } UNION { #PaymentChargeSpecification
    ?object a gr:PaymentChargeSpecification .
    FILTER (2 <= (
      SELECT count(?hasCurrencyValue)
      WHERE {
          ?object gr:hasCurrencyValue ?hasCurrencyValue
      }
    ))
  } UNION { #DeliveryChargeSpecification
    ?object a gr:DeliveryChargeSpecification .
    FILTER (2 <= (
      SELECT count(?hasCurrencyValue)
      WHERE {
          ?object gr:hasCurrencyValue ?hasCurrencyValue
      }
    ))
  }
# 8. hasDUNS (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 103
  UNION {
    ?object a gr:BusinessEntity .
    FILTER (2 <= (
      SELECT count(?hasDUNS)
      WHERE {
          ?object gr:hasDUNS ?hasDUNS
      }
    ))
  }
# 11. hasGlobalLocationNumber (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 113
  UNION {
    ?object a gr:BusinessEntity .
    FILTER (2 <= (
      SELECT count(?hasGlobalLocationNumber)
      WHERE {
          ?object gr:hasGlobalLocationNumber ?hasGlobalLocationNumber
      }
    ))
  } UNION {
    ?object a gr:LocationOfSalesOrServiceProvisioning .
    FILTER (2 <= (
      SELECT count(?hasGlobalLocationNumber)
      WHERE {
          ?object gr:hasGlobalLocationNumber ?hasGlobalLocationNumber
      }
    ))
  }
# 13. hasMaxCurrencyValue (1..1), only count = 1 is OK, check count != 1 --line 131
  UNION { #PriceSpecification
    ?object a gr:PriceSpecification .
    FILTER (1 != (
      SELECT count(?hasMaxCurrencyValue)
      WHERE {
          ?object gr:hasMaxCurrencyValue ?hasMaxCurrencyValue
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?hasMaxCurrencyValue)
      WHERE {
          ?object gr:hasMaxCurrencyValue ?hasMaxCurrencyValue
      }
    ))
  } UNION { #PaymentChargeSpecification
    ?object a gr:PaymentChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasMaxCurrencyValue)
      WHERE {
          ?object gr:hasMaxCurrencyValue ?hasMaxCurrencyValue
      }
    ))
  } UNION { #DeliveryChargeSpecification
    ?object a gr:DeliveryChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasMaxCurrencyValue)
      WHERE {
          ?object gr:hasMaxCurrencyValue ?hasMaxCurrencyValue
      }
    ))
  }
}

From properties 14 to 31 (only those with cardinality restrictions, deprecated are not included)

PREFIX gr:<http://purl.org/goodrelations/v1#>
#Datatype properties cardinalities
SELECT distinct ?object
WHERE {
# 14. hasMaxValue (0..0), no direct instances --line 165
   {
    ?object gr:hasMaxValue ?value.
  }
# 15. hasMaxValueFloat (1..1), only count = 1 is OK, check count != 1 --line 169
  UNION {
    ?object a gr:QuantitativeValueFloat .
    FILTER (1 != (
      SELECT count(?hasMaxValueFloat)
      WHERE {
          ?object gr:hasMaxValueFloat ?hasMaxValueFloat
      }
    ))
  }
# 16. hasMaxValueInteger (1..1), only count = 1 is OK, check count != 1 --line 179
  UNION {
    ?object a gr:QuantitativeValueInteger .
    FILTER (1 != (
      SELECT count(?hasMaxValueInteger)
      WHERE {
          ?object gr:hasMaxValueInteger ?hasMaxValueInteger
      }
    ))
  }
# 17. hasMinCurrencyValue (1..1), only count = 1 is OK, check count != 1 --line 189
  UNION { #PriceSpecification
    ?object a gr:PriceSpecification .
    FILTER (1 != (
      SELECT count(?hasMinCurrencyValue)
      WHERE {
          ?object gr:hasMinCurrencyValue ?hasMinCurrencyValue
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?hasMinCurrencyValue)
      WHERE {
          ?object gr:hasMinCurrencyValue ?hasMinCurrencyValue
      }
    ))
  } UNION { #PaymentChargeSpecification
    ?object a gr:PaymentChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasMinCurrencyValue)
      WHERE {
          ?object gr:hasMinCurrencyValue ?hasMinCurrencyValue
      }
    ))
  } UNION { #DeliveryChargeSpecification
    ?object a gr:DeliveryChargeSpecification .
    FILTER (1 != (
      SELECT count(?hasMinCurrencyValue)
      WHERE {
          ?object gr:hasMinCurrencyValue ?hasMinCurrencyValue
      }
    ))
  }
# 18. hasMinValue (0..0), no direct instances --line 223
  UNION {
    ?object gr:hasMinValue ?value.
  }
# 19. hasMinValueFloat (1..1), only count = 1 is OK, check count != 1 --line 227
  UNION {
    ?object a gr:QuantitativeValueFloat .
    FILTER (1 != (
      SELECT count(?hasMinValueFloat)
      WHERE {
          ?object gr:hasMinValueFloat ?hasMinValueFloat
      }
    ))
  }
# 20. hasMinValueInteger (1..1), only count = 1 is OK, check count != 1 --line 237
  UNION {
    ?object a gr:QuantitativeValueInteger .
    FILTER (1 != (
      SELECT count(?hasMinValueInteger)
      WHERE {
          ?object gr:hasMinValueInteger ?hasMinValueInteger
      }
    ))
  }
# 23. hasUnitOfMeasurement  (1..1), only count = 1 is OK, check count != 1 --line 248
  UNION { #QuatitativeValue
    ?object a gr:QuantitativeValue .
    FILTER (1 != (
      SELECT count(?hasUnitOfMeasurement)
      WHERE {
          ?object gr:hasUnitOfMeasurement ?hasUnitOfMeasurement
      }
    ))
  } UNION { #QuantitativeValueFloat
    ?object a gr:QuantitativeValueFloat .
    FILTER (1 != (
      SELECT count(?hasUnitOfMeasurement)
      WHERE {
          ?object gr:hasUnitOfMeasurement ?hasUnitOfMeasurement
      }
    ))
  } UNION { #QuantitativeValueInteger
    ?object a gr:QuantitativeValueInteger .
    FILTER (1 != (
      SELECT count(?hasUnitOfMeasurement)
      WHERE {
          ?object gr:hasUnitOfMeasurement ?hasUnitOfMeasurement
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?hasUnitOfMeasurement)
      WHERE {
          ?object gr:hasUnitOfMeasurement ?hasUnitOfMeasurement
      }
    ))
  } UNION { #TypeAndQuantityNode
    ?object a gr:TypeAndQuantityNode .
    FILTER (1 != (
      SELECT count(?hasUnitOfMeasurement)
      WHERE {
          ?object gr:hasUnitOfMeasurement ?hasUnitOfMeasurement
      }
    ))
  }
# 24. hasValueFloat (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 290
  UNION {
    ?object a gr:QuantitativeValueFloat .
    FILTER (2 <= (
      SELECT count(?hasValueFloat)
      WHERE {
          ?object gr:hasValueFloat ?hasValueFloat
      }
    ))
  }
# 25. hasValueInteger (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 300
  UNION {
    ?object a gr:QuantitativeValueInteger .
    FILTER (2 <= (
      SELECT count(?hasValueInteger)
      WHERE {
          ?object gr:hasValueInteger ?hasValueInteger
      }
    ))
  }
# 28. priceType (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 310
  UNION {
    ?object a gr:UnitPriceSpecification .
    FILTER (2 <= (
      SELECT count(?priceType)
      WHERE {
          ?object gr:priceType ?priceType
      }
    ))
  }
# 29. validFrom (1..1), only count = 1 is OK, check count != 1 --line 320
  UNION { #Offering
    ?object a gr:Offering .
    FILTER (1 != (
      SELECT count(?validFrom)
      WHERE {
          ?object gr:validFrom ?validFrom
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?validFrom)
      WHERE {
          ?object gr:validFrom ?validFrom
      }
    ))
  }
# 30. validThrough (1..1), only count = 1 is OK, check count != 1 --line 338
  UNION { #Offering
    ?object a gr:Offering .
    FILTER (1 != (
      SELECT count(?validThrough)
      WHERE {
          ?object gr:validThrough ?validThrough
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (1 != (
      SELECT count(?validThrough)
      WHERE {
          ?object gr:validThrough ?validThrough
      }
    ))
  }
# 31. valueAddedTaxIncluded (0..1), count = 0 and count = 1 is OK, check count >= 2 --line 356
  UNION { #PriceSpecification
    ?object a gr:PriceSpecification .
    FILTER (2 <= (
      SELECT count(?valueAddedTaxIncluded)
      WHERE {
          ?object gr:valueAddedTaxIncluded ?valueAddedTaxIncluded
      }
    ))
  } UNION { #UnitPriceSpecification
    ?object a gr:UnitPriceSpecification .
    FILTER (2 <= (
      SELECT count(?valueAddedTaxIncluded)
      WHERE {
          ?object gr:valueAddedTaxIncluded ?valueAddedTaxIncluded
      }
    ))
  } UNION { #PaymentChargeSpecification
    ?object a gr:PaymentChargeSpecification .
    FILTER (2 <= (
      SELECT count(?valueAddedTaxIncluded)
      WHERE {
          ?object gr:valueAddedTaxIncluded ?valueAddedTaxIncluded
      }
    ))
  } UNION { #DeliveryChargeSpecification
    ?object a gr:DeliveryChargeSpecification .
    FILTER (2 <= (
      SELECT count(?valueAddedTaxIncluded)
      WHERE {
          ?object gr:valueAddedTaxIncluded ?valueAddedTaxIncluded
      }
    ))
  }
}