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
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é:
private void createOneToMany(OntModel ontoModel, OntClass ontoClass, OntProperty prop, Resource resource) {
OntClass allValuesFromRestriction = ontoModel.createAllValuesFromRestriction(null, prop, resource);
ontoClass.addSuperClass(allValuesFromRestriction);
OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 1);
ontoClass.addSuperClass(minCardinalityRestriction);
}
private void createZeroToMany(OntModel ontoModel, OntClass ontoClass, OntProperty prop, Resource resource) {
OntClass allValuesFromRestriction = ontoModel.createAllValuesFromRestriction(null, prop, resource);
ontoClass.addSuperClass(allValuesFromRestriction);
OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 0);
ontoClass.addSuperClass(minCardinalityRestriction);
}
private void createZeroToOne(OntModel ontoModel, OntClass ontoClass1, OntProperty prop, OntClass ontoClass2) {
OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 0);
ontoClass1.addSuperClass(minCardinalityRestriction);
OntClass maxCardinalityRestriction = ontoModel.createMaxCardinalityRestriction(null, prop, 1);
ontoClass1.addSuperClass(maxCardinalityRestriction);
}
private void createOneToOne(OntModel ontoModel, OntClass ontoClass1, OntProperty prop, OntClass ontoClass2) {
OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 1);
ontoClass1.addSuperClass(minCardinalityRestriction);
OntClass maxCardinalityRestriction = ontoModel.createMaxCardinalityRestriction(null, prop, 1);
ontoClass1.addSuperClass(maxCardinalityRestriction);
}
Then you can just do:
OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
OntClass task = ontModel.createClass(OWL.NS + "Task");
OntClass actor = ontModel.createClass(OWL.NS + "Actor");
OntProperty propTask = ontModel.createObjectProperty( OWL.NS + "Task-performedBy-Actor");
OntProperty propActor = ontModel.createObjectProperty( OWL.NS + "Actor-performs-Task");
To call:
createOneToMany(ontModel, task, prop, actor);
createZeroToMany(ontModel, task, prop, actor);
createOneToOne(ontModel, task, propTask, actor);
createZeroToOne(ontModel, actor, propActor, task);
Sample of result:
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
<owl:Class rdf:about="http://www.w3.org/2002/07/owl#Task">
<rdfs:subClassOf>
<owl:Restriction rdf:nodeID="A0">
<owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:minCardinality>
<owl:onProperty>
<owl:ObjectProperty rdf:about="http://www.w3.org/2002/07/owl#Actor-performs-Task"/>
</owl:onProperty>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
<owl:Class rdf:about="http://www.w3.org/2002/07/owl#Actor">
<rdfs:subClassOf>
<owl:Restriction>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
<owl:onProperty rdf:resource="http://www.w3.org/2002/07/owl#Actor-performs-Task"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf rdf:nodeID="A0"/>
</owl:Class>
<owl:ObjectProperty rdf:about="http://www.w3.org/2002/07/owl#Task-performedBy-Actor"/>
</rdf:RDF>
Now there is also ONT-API, which is Jena extension for OWL2:
String ns = "https://stackoverflow.com/q/20562107/1281433/";
OntGraphModel model = OntModelFactory.createModel()
.setNsPrefixes(OntModelFactory.STANDARD)
.setNsPrefix("test", ns);
OntClass c = model.createOntEntity(OntClass.class, ns + "Kolik_Fazovy");
OntNOP p = model.createOntEntity(OntNOP.class, ns + "JeVysledkom");
model.createOntEntity(OntClass.class, ns + "Test")
.addSubClassOf(model.createObjectCardinality(p, 1, c));
model.write(System.out, "ttl");