How to add rdfs:label to OWLIndividual via OWLAPI? - semantic-web

I would like to add an rdfs:label to an OWLIndividual, I have the following:
OWLIndividual newIndividual = factory.getOWLNamedIndividual(IRI.create(name));
OWLLiteral lbl = factory.getOWLLiteral(name);
OWLAnnotation label =
factory.getOWLAnnotation(
factory.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL.getIRI()), lbl);
Now, how can I associate the label to the individual?

You can associate the label the following way:
OWLAxiom axiom = factory.getOWLAnnotationAssertionAxiom(newIndividual.asOWLNamedIndividual().getIRI(), label);
manager.applyChange(new AddAxiom(ontology, axiom));
In this case you need to work with a NamedIndividual in order to retrieve the IRI to assert the annotation.

Related

Access subclassOf/subclassOf level using ForwardChainingRDFSInferencer with SPARQL

I am running some SPARQL queries using the class ForwardChainingRDFSInferencer, which basic constructs an inferencer. For my examples I use the schema.org ontology.
My code looks like the following example
MemoryStore store = new MemoryStore();
ForwardChainingRDFSInferencer inferencer = new ForwardChainingRDFSInferencer(store); //the inference class
Repository repo = new SailRepository(inferencer);
repo.initialize();
URL data = new URL("file:/home/user/Documents/schemaorg-current-https.nt");
RDFFormat fileRDFFormat = RDFFormat.NTRIPLES;
RepositoryConnection con = repo.getConnection();
con.add(data, null, fileRDFFormat);
System.out.println("Repository loaded");
String queryString =
" PREFIX schema: <https://schema.org/>" +
" SELECT DISTINCT ?subclassName_one" +
" WHERE { " +
" ?type rdf:type rdfs:Class ." +
" ?type rdfs:subClassOf/rdfs:subClassOf? schema:Thing ." +
" ?type rdfs:label ?subclassName_one ." +
" }";
TupleQuery tupleQuery = con.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
TupleQueryResult result = tupleQuery.evaluate();
while (result.hasNext()) {
BindingSet bindingSet = result.next();
System.out.println(bindingSet.toString());
stdout.println(bindingSet.toString());
}
repo.close()
What I want is to print two subclass levels down the class Thing. So if for example we have,
Thing > Action (sub-class 1) > ConsumeAction (sub-class 2) > DrinkAction
What I want is to return the class CosumeAction which is two levels (subclasses) down from class Thing, while using the inference java class.
The current query, as given in the code sample above, returns all the classes and subclasses from every class of the schema.org ontology. Thus, there is something that I do wrong while using the inference class.
You could remove the classes you are not interested in with FILTER NOT EXISTS:
FILTER NOT EXISTS {
?type rdfs:subClassOf+/rdfs:subClassOf/rdfs:subClassOf schema:Thing .
}
Examples
For DrinkAction (level 3):
FILTER NOT EXISTS {
?type
rdfs:subClassOf+ / # schema:ConsumeAction
rdfs:subClassOf / # schema:Action
rdfs:subClassOf schema:Thing .
}
For WearAction (level 4):
FILTER NOT EXISTS {
?type
rdfs:subClassOf+ / # schema:UseAction / schema:ConsumeAction
rdfs:subClassOf / # schema:Action
rdfs:subClassOf schema:Thing .
}

How to convert a class expression (from restriction unionOf) to a string?

A SPARQL query returns a result with restrictions with allValuesFrom and unionOf. I need do concat these values, but, when I use bind or str functions, the result is blank.
I tried bind, str and group_concat functions, but, all of it was unsuccessful. Group_concat return a blank node.
SELECT DISTINCT ?source ?is_succeeded_by
WHERE {
?source rdfs:subClassOf ?restriction .
?restriction owl:onProperty j.0:isSucceededBy .
?restriction owl:allValuesFrom ?is_succeeded_by .
FILTER (REGEX(STR(?source), 'gatw-Invoice_match'))
}
Result of SPARQL query in Protegé:
You can hardly obtain strings like 'xxx or yyy' programmatically in Jena,
since it is Manchester Syntax, an OWL-API native format, and it is not supported by Jena.
Any class expression is actually b-node, there are no such builtin symbols like 'or' in raw RDF.
To represent any anonymous class expression as a string, you can use ONT-API,
which is a jena-based OWL-API, and, therefore, both SPARQL and Manchester Syntax are supported there.
Here is an example based on pizza ontology:
// use pizza, since no example data provided in the question:
IRI pizza = IRI.create("https://raw.githubusercontent.com/owlcs/ont-api/master/src/test/resources/ontapi/pizza.ttl");
// get OWLOntologyManager instance from ONT-API
OntologyManager manager = OntManagers.createONT();
// as extended Jena model:
OntModel model = manager.loadOntology(pizza).asGraphModel();
// prepare query that looks like the original, but for pizza
String txt = "SELECT DISTINCT ?source ?is_succeeded_by\n" +
"WHERE {\n" +
" ?source rdfs:subClassOf ?restriction . \n" +
" ?restriction owl:onProperty :hasTopping . \n" +
" ?restriction owl:allValuesFrom ?is_succeeded_by .\n" +
" FILTER (REGEX(STR(?source), 'Am'))\n" +
"}";
Query q = new Query();
q.setPrefixMapping(model);
q = QueryFactory.parse(q, txt, null, Syntax.defaultQuerySyntax);
// from owlapi-parsers package:
OWLObjectRenderer renderer = new ManchesterOWLSyntaxOWLObjectRendererImpl();
// from ont-api (although it is a part of internal API, it is public):
InternalObjectFactory iof = new SimpleObjectFactory(manager.getOWLDataFactory());
// exec SPARQL query:
try (QueryExecution exec = QueryExecutionFactory.create(q, model)) {
ResultSet res = exec.execSelect();
while (res.hasNext()) {
QuerySolution qs = res.next();
List<Resource> vars = Iter.asStream(qs.varNames()).map(qs::getResource).collect(Collectors.toList());
if (vars.size() != 2)
throw new IllegalStateException("For the specified query and valid OWL must not happen");
// Resource (Jena) -> OntCE (ONT-API) -> ONTObject (ONT-API) -> OWLClassExpression (OWL-API)
OWLClassExpression ex = iof.getClass(vars.get(1).inModel(model).as(OntClass.class)).getOWLObject();
// format: 'class local name' ||| 'superclass string in ManSyn'
System.out.println(vars.get(0).getLocalName() + " ||| " + renderer.render(ex));
}
}
The output:
American ||| MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
AmericanHot ||| HotGreenPepperTopping or JalapenoPepperTopping or MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
Used env: ont-api:2.0.0, owl-api:5.1.11, jena-arq:3.13.1

How to choose a different query based on the subject of an object in SPARQL?

Let's say I have the following data
subject = david
predicate = knows
object1 = Amy
object2 = Brian
subject = Amy
predicate = gender
object = female
subject = Brian
predicate = gender
object = male
Now I want to find all the people david knows but perform different queries based upon their gender so the pseudocode would look something like this:
SELECT ?something
WHERE{
david rdf:knows ?person
if{?person rdf:gender "female"}
{ do this query}
else if {?person rdf:gender "male"}
{do this query}
}
From what I've seen SPARQL if statements can only print out information and cannot be used to make decisions on what query to execute.
If anyone knows how the above can be achieved I would be most grateful.
In this case, you could do something like:
select ?something where {
:David :knows ?person
optional {
?person :gender "female" .
#-- more query
}
optional {
?person :gender "male" .
#-- more query
}
}
Both of the optional parts are optional, and only the one with the matching gender will be able to match, so it's essentially a conditional query. Note that you'll do both if you have data like :person :gender "male", "female", and that you'll do neither if you don't have a gender provided.

Sparql issue on BIND clause

I'm currently trying to sort some clients by priority (those that have a running subscription first then the others.
To that effect I use a BIND clause in this query :
SELECT DISTINCT ?context ?priority ?label {
?s a my:Client .
?s rdfs:label ?label .
BIND ( IF(EXISTS {?s rdf:type my:Subscriber}, 1, 0) AS ?priority )
} ORDER BY DESC(?priority) ASC(?label)
Seems to me that the ?priority var should always be bound to either 0 or 1 but whenever I execute the query I get (along with the expected output result) unbound ?priority "rows" for those items that should get 1 for priority so I need to add FILTER (bound(?priority)) in my query to get what i expect.
Is that normal or am I missing something ?
Thanks in advance,
Max.
Edit :
=> filed the sort issue in the tracker
I edited the query to check that the prority is both bound and unbound on the same node.
Here's a sample output of the resultset I get back
?context = urn:graph:1772#844 , ?priority = 1^^http://www.w3.org/2001/XMLSchema#integer , ?sort1 = client 2#fr
?context = urn:graph:1772#1690 , ?priority = 1^^http://www.w3.org/2001/XMLSchema#integer , ?sort1 = client 1#fr
?context = urn:graph:1772#742 , ?priority = 0^^http://www.w3.org/2001/XMLSchema#integer , ?sort1 = client 4#fr
?context = urn:graph:1772#1010 , ?priority = 0^^http://www.w3.org/2001/XMLSchema#integer , ?sort1 = client 3#fr
?context = urn:graph:1772#1690 , ?sort1 = client 1#fr
?context = urn:graph:1772#844 , ?sort1 = client 2#fr
In the last two rows, the variable ?priority is not bound at all.
By the way, you'll note that the second ORDER clause is also not honored if the first clause is unbound
There was a bug with the use of EXISTS as a child expression of another expression that could lead to incorrect results as in your example.
This is now fixed in the source code and will be included in the next release

Dynamic PDO AND and OR

I have a problem with Yii's CDBCrtieria builder. I am trying to make a rather complex query while using the escaping and safe functions provided by PDO.
Here is the query I am basically trying to build:
SELECT * FROM tbl_audit_log
WHERE (model_id = 1 AND model = "Title") OR
(model_id = 1 AND model = "Product") //etc
This is being built dynamically in PHP like:
$model_ids = array(array($model->id, 'Title'));
foreach($model->products as $id => $product){
$model_ids[][] = $product->id;
$model_ids[][] = "Product";
}
So I don't know the values of the WHERE before I build the query. I must find an easy way to build:
WHERE (model_id = 1 AND model = "Title") OR
(model_id = 1 AND model = "Product") //etc
Dynamically.
I have looked through the documentation but the closest thing I see is addCondition which would require complex coding to get working properly.
Does Yii provide any easy way of achieving this without having to deal with writing complex code to name my params etc?
It is indeed a bit more complex, but here's a working solution:
$criteria = new CDbCriteria();
$param_id = 0;
// $model_ids is the one you built in your original code
foreach( $model_ids as $id_pair ) {
$criteria->addCondition( '( model_id = :id' . $param_id . ' AND model = :model' . $param_id . ' )', 'OR' );
$criteria->params[ ':id' . $param_id ] = $id_pair[0];
$criteria->params[ ':model' . $param_id ] = $id_pair[1];
$param_id++;
}
This will generate custom identifiers for each of your parameters so they will all be validated. Then you can just use $criteria in your query.