Semweb4j/filesQueries/step3
Up | Previous step | Next step
Contents |
[edit] Step 3: Finding statements
[edit] use case: peopleTag
We will now develop a little semantic web application which allows us to tag persons. Tagging is a special kind of statement adding: tag(a with b) should produce "a is tagged by b" or "a has tag b". We chose this implementation:
Inside the class:
private static Model model; private static URI hasTag;
In the main method, after initialization of model:
hasTag = model.createURI("http://example.com/relations#hasTag");
Inside the class:
public static void tag(Resource resource, Node tag) throws ModelRuntimeException {
model.addStatement(resource, hasTag, tag);
}
Our tag is a Node instance and therefore can be an URI or any kind of Literal.
[edit] the different node types
Let's see how RDF2Go managed URIs, Literals, etc.. The different node types are implemented as interfaces:
interface URI extends Resource, UriOrVariable interface PlainLiteral extends Literal interface LanguageTagLiteral extends Literal interface DatatypeLiteral extends Literal interface Literal extends Node interface BlankNode extends Resource interface Resource extends Node, ResourceOrVariable interface Node extends NodeOrVariable, Comparable<Node> interface UriOrVariable extends ResourceOrVariable interface ResourceOrVariable extends NodeOrVariable interface NodeOrVariable
Of course, using model.createURI(), you don't get an instance of the interface URI mentioned above but an instance of a URI class which implements this interface.
The special node
Variable.ANY
is a wildcard in triple pattern finding. It's the only instance of the class Variable, which looks like
class Variable implements Node, ResourceOrVariable, UriOrVariable, NodeOrVariable
and therefore can be used always if any of such interfaces are required in a method.
It has to be mentioned that using BlankNodes *can* cause several problems (in RDF, generally), so use them only if you know what you're doing.
[edit] example setup
Now we will use "peopleTag" to demonstrate finding with triple patterns. For finding, we need data to find.
First, we need something to tag - resources, identified by URIs:
URI max = model.createURI("http://xam.de/foaf.rdf.xml#i");
URI konrad = model.createURI("http://example.com/persons#konrad");
URI guido = model.createURI("http://example.com/persons#guido");
URI james = model.createURI("http://example.com/persons#james");
Now let's create some tags:
PlainLiteral tagJava = model.createPlainLiteral("Java");
PlainLiteral tagPython = model.createPlainLiteral("Python");
Tagging the resources is easy now, as we have the method tag(Resource, Node): (URIs are Resources and PlainLiterals are Nodes, as seen above)
tag(max, tagJava); tag(james, tagJava); tag(konrad, tagJava); tag(konrad, tagPython); tag(guido, tagPython);
[edit] ClosableIterators
ClosableIterators are special iterators which provide a it.close() method. Because ClosableIterators maintain database connections, the close() method must always be called when you don't need the iterator any longer. As long as a ClosableIterator is open, it drains server resources. There is auto-close-functionallity, so after iterating over all objects in the iterator, it will be closed. Make sure you call it.close() even after iterating over all objects because you may have had an exception and therefore not iterated over all objects.
ClosableIterables provide an iterator() method which returns a ClosableIterator. If you use ClosableIterables in for-each-loops, you don't have direct access to the ClosableIterator. If an exception breaks the for-each-loop, the iterator will never get closed. Because of this, for-each-loops with ClosableIterables should be used with care.
[edit] finding
Finding every statement "xyz tagged with Java" (or, more formally, ? hasTag "Java"):
ClosableIterable<? extends Statement> foundTaggedJava;
foundTaggedJava = model.findStatements(Variable.ANY, hasTag, tagJava);
System.out.println("Everything tagged 'Java':");
for(Statement s : foundTaggedJava) {
System.out.println(s.getSubject());
}
The ClosableIterable is from AIFBcommons:
import org.ontoware.aifbcommons.collection.ClosableIterable;
and implements an Iterable interface which closes the file/stream/connection after iteration.
model.findStatements(ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object);
returns a ClosableIterable of Statements, as you can see. If called with (Variable.ANY, Variable.ANY, Variable.ANY), you get all statements in this model.
[edit] finding with a triple pattern
Now we're looking for "xyz tagged with Python":
TriplePattern taggedAsPythonPattern = model.createTriplePattern(Variable.ANY, hasTag, tagPython);
ClosableIterable<? extends Statement> foundTaggedPython;
foundTaggedPython = model.findStatements(taggedAsPythonPattern);
System.out.println("Everything tagged 'Python':");
for(Statement s : foundTaggedPython) {
System.out.println(s.getSubject());
}
It's almost the same as above, findStatements can simply also be called with
model.findStatements(TriplePattern);
and a TriplePattern instance is created via
model.createTriplePattern(ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object);
If you're using the same pattern at different locations in your code, TriplePattern objects make managing your code easier.
[edit] output
Everything tagged 'Java': http://example.com/persons#konrad http://example.com/persons#james http://xam.de/foaf.rdf.xml#i Everything tagged 'Python': http://example.com/persons#guido http://example.com/persons#konrad