I am using Jena with TDB. I am successfully storing triples but need to specify that a certain property "isA" is transitive in order to use the TransitiveReasoner for inference.
The following is some of the methods I am using:
private void AddTriple(String arg1, String pred, String arg2) {
Resource r = m.createResource(NS + arg1);
Property p = m.createProperty(NS + pred);
Property p2 = m.createProperty(NS + arg2);
r.addProperty(p, p2);
}
private void addTest() {
AddTriple("cat", "isA", "feline");
AddTriple("feline", "isA", "mammal");
AddTriple("mammal", "isA", "animal");
m.close();
}
I am loading the model as follows:
Dataset dataset = TDBFactory.createDataset(directory);
m = dataset.getDefaultModel();
addTest();
I am setting up the reasoner as follows:
Reasoner reasoner = ReasonerRegistry.getTransitiveReasoner();
InfModel inference = ModelFactory.createInfModel(reasoner, m);
The inference model contains:
<ModelCom {http://namespace/test#cat #http://namespace/test#isA http://namespace/test#feline; http://namespace/test#feline #http://namespace/test#isA http://namespace/test#mammal; http://namespace/test#mammal #http://namespace/test#isA http://namespace/test#animal} | >
Since the "isA" property is not specified as being transitive the inference model contains the exact same triples as the original model. How I can specify that the "isA" property is transitive so I can get the following triples:
cat isA mammal
cat isA animal
"When one defines a property P to be a transitive property, this means that if a pair (x,y) is an instance of P, and the pair (y,z) is also instance of P, then we can infer the the pair (x,z) is also an instance of P.
Syntactically, a property is defined as being transitive by making it an instance of the the built-in OWL class owl:TransitiveProperty, which is defined as a subclass of owl:ObjectProperty."
-- http://www.w3.org/TR/owl-ref/#TransitiveProperty-def
Therefore, you need to define your property as being transitive, you can do that by adding the following RDF triple to your Jena Model:
<http://namespace/test#isA> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#TransitiveProperty>
m.add ( ResourceFactory.createResource(NS + "isA"), RDF.type, OWL.TransitiveProperty )
I also recommend you read the documentation on the Jena website relative to ontologies and inference:
http://incubator.apache.org/jena/documentation/ontology/
http://incubator.apache.org/jena/documentation/inference/
Related
I have the following SDN 4 entity:
#NodeEntity
public class Decision {
#Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private Set<Decision> parentDecisions;
...
}
I'd like to find this entity by id and return all its parentDecisions with a following SDN4 repository method and the custom Cypher query:
MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) RETURN d, rdp, parentD
Decision getById(#Param("decisionId") Long decisionId);
right now in case of existing parentD it fails with the following exception:
java.lang.RuntimeException: Result not of expected size. Expected 1 row but found 3
at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.queryForObject(ExecuteQueriesDelegate.java:73)
at org.neo4j.ogm.session.Neo4jSession.queryForObject(Neo4jSession.java:382)
at sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
How to properly implement this logic with SDN4 repository method and the custom Cypher query ?
UPDATED
I tested approach suggested by frant.hartm. Unfortunately it still doesn't work.
For example the following SDN4 repository method correctly returns 2 Decision:
#Query("MATCH (d:Decision)-[drd:FOLLOWS]->(following:Decision) WHERE d.id = {decisionId} RETURN following")
List<Decision> test(#Param("decisionId") Long decisionId);
but the next one:
#Query("MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)-[rdf:FOLLOWS]->(followD:Decision) RETURN d as decision, collect(rdf), collect(followD) ")
DecisionHolder test1(#Param("decisionId") Long decisionId);
returns only main decision (holder.getDecision()) but with empty collection of followD (holder.getDecision().getFollowDecisions()) Decision.
This is Decision entity:
#NodeEntity
public class Decision {
private static final String FOLLOWS = "FOLLOWS";
#Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
private Set<Decision> followDecisions;
#Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public Set<Decision> getFollowDecisions() {
return followDecisions;
}
#Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public void setFollowDecisions(Set<Decision> followDecisions) {
this.followDecisions = followDecisions;
}
....
}
What am I doing wrong ?
The core issue is that your query returns multiple Decision instances (under different variables - d and parentD), so it can't just arbitrarily chose one. Use #QueryResult to extract desired value. Also use COLLECT to get a single result.
#QueryResult
public class DecisionHolder {
Decision d;
}
MATCH (d:Decision) WHERE d.id = {decisionId} " +
"OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) " +
"RETURN d, collect(rdp), collect(parentD)")
DecisionHolder getById(#Param("decisionId") Long decisionId);
Update:
For the relationships to map correctly relationship entities and simple relationships with same type must not be mixed.
If you have a simple relationship and relationship entity with same type
when they represent same relationship type use relationship entity class in your relationship definition (e.g. Set<ParentDecisionRelationship> parentDecisions)
when they represent different types rename one of them
Is there an easy way to translate the "src" loc of model#uses to a class?
The problem I am having is I tried to use the model#declarations to match and find the class by location, but matching between file:// and project:// (m3 model) is not 100% pure (ignoring .scheme), comparing
begin.line >=
and
end.line <=
still results in 2 classes, when a "src" line is in the innerclass.
To summarise: Is there a function that returns the class, e.g.
loc classLoc = getClass( |home:///Workspaces/Rascal/src/Fruit.java|(150,1,<11,12>,<11,13>) );
That will return |java+class://Fruit|, having line 11 be a line in class Fruit.
Sure. Consider this example Java code:
public abstract class Fruit {
private class X {
}
int main() {
X x = new X();
return 1;
}
}
and consider I stored the M3 model in m and take the use of X located at this source location l = |home:///Workspaces/Rascal/rascal/src/org/rascalmpl/courses/example-project/src/Fruit.java|(150,1,<11,12>,<11,13>);
Then this expression will tell you to which declaration the class points to:
rascal>cl = m#uses[l];
set[loc]: {|java+class:///Fruit/X|}
To find out in which other class this class is then nested we invert the containment relation and look up the parent of the nested class like so:
rascal>m#containment<to,from>[cl]
set[loc]: {|java+class:///Fruit|}
I want to traverse the AST of a simple class having one member variable and one method. I have figured out that the class is represented as CXXRecordDecl.
What is the api within CXXREcordDecl to get the list of member variables which are represented as FieldDecl ?
The fields can be retrieved with RecordDecl::fields (there exist also methods the get the begin and end iterators of that range), e.g. for a CXXRecordDecl
CXXRecordDecl* cl = ...;
for (const auto& field : cl->fields) {
const auto& name = field->getName();
const auto field_cl = field->getType()->getAsCXXRecordDecl();
}
Similarly you would access the methods with methods().
I have two ontologies, photo1 and index. Photo1 contains ABox assertions, and index contains Tbox assertions.
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
OWLOntology photo1 = manager.loadOntologyFromOntologyDocument(new File("files/ontologies/OBMA2/photo1.owl"));
OWLDataFactory factory = manager.getOWLDataFactory();
reasoner = new FaCTPlusPlusReasonerFactory().createReasoner(photo1);
reasoner = (FaCTPlusPlusReasoner) reasoner;
System.out.println(reasoner.getInstances(factory.getOWLThing(), false));
The above prints:
Nodeset[
Node( <http://www.semanticweb.org/noor/ontologies/2013/6/photo1.owl#photo1> ),
Node( <http://www.semanticweb.org/noor/ontologies/2013/6/photo1.owl#photo1-tiger2> ),
Node( <http://www.semanticweb.org/noor/ontologies/2013/6/photo1.owl#photo1-tiger1> )
]
However, now, I'm loading the Tbox and adding all ABox axioms from photo1 and then getting instances of owl:Thing as follows:
OWLOntologyManager managerTbox = OWLManager.createOWLOntologyManager();
OWLOntology Tbox = manager.loadOntologyFromOntologyDocument(new File("files/ontologies/index.owl"));
OWLDataFactory factoryTbox = manager.getOWLDataFactory();
OWLReasoner reasonerTbox = new FaCTPlusPlusReasonerFactory().createReasoner(Tbox);
//adding the axioms from the photo1 abox to Tbox's abox
managerTbox.addAxioms(Tbox, photo1.getABoxAxioms(true));
reasonerTbox = (FaCTPlusPlusReasoner) reasonerTbox;
System.out.println(reasonerTbox.getInstances(factoryTbox.getOWLThing(), false));
Now, even though I have added all axioms from Photo1's ABox to TBox's ABox, I get no output:
Nodeset[]
I'm not much of an OWL API user, but I suspect that what's happening is that the ABox axioms that you're including in the second case don't include the individual declarations for the individuals that the axioms talk about, and that as a result, the ABox axioms are getting ignored.
From the OWLAPI source, the ABoxAxiomTypes are defined as:
public static final Set<AxiomType<?>> ABoxAxiomTypes = new HashSet<AxiomType<?>>(
Arrays.asList(CLASS_ASSERTION, SAME_INDIVIDUAL,
DIFFERENT_INDIVIDUALS, OBJECT_PROPERTY_ASSERTION,
NEGATIVE_OBJECT_PROPERTY_ASSERTION,
DATA_PROPERTY_ASSERTION, NEGATIVE_DATA_PROPERTY_ASSERTION,
DATATYPE_DEFINITION));
I expect that if you add photo1's OWLDeclarationAxioms first (which it looks like you'd retrieve using getAxioms(AxiomType<Declaration>), and then add its ABoxAxioms, you might get the results that you're expecting.
You are creating a buffering reasoner with the first call to the reasoner factory; then you are adding the axioms to the ontology correctly, but the reasoner will not see the updates until you call reasoner.flush().
You can create a non-buffering reasoner with the same factory (see OWLReasonerFactory.createNonBufferingReasoner()), but this might have performance repercussions, as there might be a reclassification at every change.
Currently I am using Jena to work around ontology file, but could not find a way to remove functional attribute from certain property.
Could anyone point out how to do this using Jena?
-- Edit --
What I wanted to do is to iterate all over the properties in the ontology and if it found functionalProperty, then convert it into non-functional property
My code is something like this:
Iterator<OntProperty> ont = model.listOntProperties();
while(ont.hasNext()) {
OntProperty p = ont.next();
if(p.isFunctionalProperty()) {
p.removeProperty(RDF.type, OWL.FunctionalProperty);
}
}
But currently it yield java.util.ConcurrentModificationException error.
Thanks!
The various ontology API classes in Jena, such as FunctionalProperty are there just to provide a convenient programming API. All of the state information is actually held in the underlying Model. Therefore, to make a property not be a functional property any more, you just need to remove the corresponding rdf:type triple from the model.
For example (untested code, but should work):
OntModel m = ModelFactory.createOntology( OntModelSpec.OWL_MEM );
NS = "http://www.example.com/ontology#";
FunctionalProperty p = m.createFunctionalProperty( NS + "p" );
// now change p to normal object property
// setRDFType removes all existing rdf:type triples and adds one new one
// alternatively, we could just call:
// p.removeProperty( RDF.type, OWL.FunctionalProperty );
p.setRDFType( OWL.ObjectProperty );
ObjectProperty p1 = p.as( ObjectProperty.class );
Update
Your code throws a ConcurrentModificationError because you are trying to make changes to a collection while iterating over that collection - hence modifying it concurrently with iterating. The solution is to do the work in two phases: first create a collection object, such as an ArrayList with the properties you want to change, and secondly make the changes to those properties.
List<FunctionalProperty> fps = new ArrayList<FunctionalProperty>();
Iterator<OntProperty> ont = model.listOntProperties();
while(ont.hasNext()) {
OntProperty p = ont.next();
if(p.isFunctionalProperty()) {
fps.add( p.asFunctionalProperty() );
}
}
for (FunctionalProperty fp: fps) {
fp.removeProperty(RDF.type, OWL.FunctionalProperty);
}