javardfjenaowldescription-logic

How to add qualified cardinality in JENA


How can I add qualified cardinality restriction in Jena? I can not use createCardinalityQRestriction because the OntModelSpec is for the first version of OWL, not OWL2. In ModelFactory's createOntologyModel, is there a way to create an OWL2 ontology? I need a class expression like

JeVysledkom exactly 1 Kolik_Fazovy

I've tried using this code:

OntModel ontModel = ModelFactory.createOntologyModel();
OntClass ret = ontModel.createCardinalityQRestriction(null, ontProperty, cardinality,    ontClass2 );
ontClass.addSuperClass(ret);

but I get this exception:

com.hp.hpl.jena.ontology.ProfileException: Attempted to use language construct CARDINALITY_Q that is not supported in the current language profile: OWL Full


Solution

  • I actually just ran into this while handling another question, Adding more complicated subclass axiom. Creating this in Jena is a little bit tricky because support for the qualified cardinality restrictions is an OWL2 feature, and Jena has limited support for OWL2:

    Jena Ontology API

    Note that, at present, the Jena ontology API has only limited support for OWL2's qualified cardinality restrictions (i.e. cardinalityQ, minCardinalityQ and maxCardinalityQ). Qualified cardinality restrictions are encapsulated in the interfaces CardinalityQRestriction, MinCardinalityQRestriction and CardinalityQRestriction. OntModel also provides methods for creating and accessing qualified cardinality restrictions. Since they are not part of the OWL 1.0 language definition, qualified cardinality restrictions are not supported in OWL ontologies. Qualified cardinality restrictions were added to the OWL 2 update. OWL2 support in Jena will be added in due course.

    Additionally, the Javadoc for the OWL2 vocabulary class says:

    OWL2 vocabulary. NOTE: Jena does not provide OWL2 inference or OntModel support. These constants are provided for the convenience of users who are doing OWL2 work with the current OWL1 support and desire a suitable set of names.

    You might also see a response that I posted to the Jena mailing list about a similar question, Re: Owl maxCardinality restriction.

    But you want to create one anyway? Then you're one of those “users who are doing OWL2 work with the current OWL1 support and desire a suitable set of names.” To find out how the OWL2 construction should be serialized in RDF, we need to take a look at OWL 2 Web Ontology Language Mapping to RDF Graphs (Second Edition), particularly section 2 Mapping from the Structural Specification to RDF Graphs, which tells us that the class expression

    ObjectExactCardinality( n OPE CE )
    

    is serialized as the following set of triples

    _:x rdf:type owl:Restriction .
    _:x owl:onProperty T(OPE) .
    _:x owl:qualifiedCardinality "n"^^xsd:nonNegativeInteger .
    _:x owl:onClass T(CE) .
    

    where _:x is the resource that is the class. The non-qualified case, which Jena already handles, turns

    ObjectExactCardinality( n OPE )
    

    into

    _:x rdf:type owl:Restriction .
    _:x owl:onProperty T(OPE) .
    _:x owl:cardinality "n"^^xsd:nonNegativeInteger .
    

    If we had one of the latter, we could replace its owl:cardinality property with an owl:qualifiedCardinality property, and add the appropriate owl:onClass property. Here's some Java code that does just that:

    import com.hp.hpl.jena.ontology.OntClass;
    import com.hp.hpl.jena.ontology.OntModel;
    import com.hp.hpl.jena.ontology.OntModelSpec;
    import com.hp.hpl.jena.ontology.OntProperty;
    import com.hp.hpl.jena.rdf.model.ModelFactory;
    import com.hp.hpl.jena.rdf.model.Property;
    import com.hp.hpl.jena.vocabulary.OWL;
    import com.hp.hpl.jena.vocabulary.OWL2;
    
    public class QualifiedRestrictionExample {
        public static OntClass createCardinalityQRestriction(
                OntModel model,
                String uri,
                Property prop,
                int cardinality, 
                OntClass clas ) {
            OntClass klass = model.createCardinalityRestriction( uri, prop, cardinality );
            klass.removeAll( OWL.cardinality );
            klass.addLiteral( OWL2.qualifiedCardinality, cardinality );
            klass.addProperty( OWL2.onClass, clas );
            return klass;
        }
    
        public static void main(String[] args) {
            String NS = "https://stackoverflow.com/q/20562107/1281433/";
            OntModel model = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_MEM );
            OntClass test = model.createClass( NS+"Test" );
            OntProperty j = model.createObjectProperty( NS+"JeVysledkom" );
            OntClass k = model.createClass( NS+"Kolik_Fazovy" );
            OntClass x = createCardinalityQRestriction(model, null, j, 1, k);
            test.addSuperClass( x );
            model.write( System.out, "RDF/XML-ABBREV" );
        }
    }
    

    Output:

    <rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:owl="http://www.w3.org/2002/07/owl#"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
        xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
      <owl:Class rdf:about="https://stackoverflow.com/q/20562107/1281433/Kolik_Fazovy"/>
      <owl:Class rdf:about="https://stackoverflow.com/q/20562107/1281433/Test">
        <rdfs:subClassOf>
          <owl:Restriction>
            <owl:onClass rdf:resource="https://stackoverflow.com/q/20562107/1281433/Kolik_Fazovy"/>
            <owl:qualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#long"
            >1</owl:qualifiedCardinality>
            <owl:onProperty>
              <owl:ObjectProperty rdf:about="https://stackoverflow.com/q/20562107/1281433/JeVysledkom"/>
            </owl:onProperty>
          </owl:Restriction>
        </rdfs:subClassOf>
      </owl:Class>
    </rdf:RDF>
    

    In Protégé:

    subclass axiom in Protege