Programming with Jena Sources for examples can be found @ http://jenabean.googlecode.com/svn/jenabean-lab1 http://jenabean.googlecode.com/svn/jenaclass Taylor Cowan Travelocity http://thewebsemantic.com http://jenabean.googlecode.com.

Download Report

Transcript Programming with Jena Sources for examples can be found @ http://jenabean.googlecode.com/svn/jenabean-lab1 http://jenabean.googlecode.com/svn/jenaclass Taylor Cowan Travelocity http://thewebsemantic.com http://jenabean.googlecode.com.

Programming with Jena
Sources for examples can be found @
http://jenabean.googlecode.com/svn/jenabean-lab1
http://jenabean.googlecode.com/svn/jenaclass
Taylor Cowan
Travelocity
8982
http://thewebsemantic.com
http://jenabean.googlecode.com
2
[] a foaf:Person;
foaf:name Taylor Cowan;
foaf:weblog <http://thewebsemantic.com>;
foaf:workplaceHomepage <http://www.travelocity.com>;
foaf:holdsAccount <http://twitter.com/tcowan>;
foaf:currentProject <http://jenabean.googlecode.com>;
foaf:currentProject <http://geosparql.googlecode.com>;
foaf:currentProject <http://jo4neo.googlecode.com>;
http://thewebsemantic.com
http://jenabean.googlecode.com
Model m = ModelFactory.createDefaultModel();
Thing todaysTopic =
new Thing("http://jenabean.googlecode.com", m);
new Thing(m).isa(Foaf.Person.class)
.name("Taylor Cowan")
.weblog(URI.create("http://thewebsemantic.com"))
.holdsAccount(URI.create("http://twitter.com/tcowan"))
.currentProject(todaysTopic)
.currentProject(URI.create("http://jo4neo.googlecode.com"));
@see
Card.java in package
example.fluentwriter
http://thewebsemantic.com
http://jenabean.googlecode.com
3
4
AGENDA
>
>
>
>
>
Semantic Web Introduction
RDF basics
Coding Towards Jena’s Semantic Web Framework API
Java to Model Binding with JenaBean
Java to Model Binding with Fluent Interfaces
http://thewebsemantic.com
http://jenabean.googlecode.com
5
Why Not Microformats?
<xsl:choose>
<xsl:when test="(false() = not((.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and
contains(concat(' ',normalize-space(@class),' '),' fn ') and (local-name() = 'img' or local-name() =
'area')]/@alt) and (string-length(normalize-space(.//*[not(ancestor-or-self::*[local-name() =
'del']) = true() and contains(concat(' ',normalize-space(@class),' '),' fn ') and (local-name() =
'img' or local-name() = 'area')]/@alt)) = string-length(translate(normalize-space(.//*[not(ancestoror-self::*[local-name() = 'del']) = true() and contains(concat(' ',normalize-space(@class),' '),' fn
') and (local-name() = 'img' or local-name() = 'area')]/@alt),' ',''))))) or (false() =
not((.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and contains(concat(' ',normalizespace(@class),' '),' fn ') and (local-name() = 'abbr')]/@title) and (string-length(normalizespace(.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and contains(concat('
',normalize-space(@class),' '),' fn ') and (local-name() = 'abbr')]/@title)) = stringlength(translate(normalize-space(.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and
contains(concat(' ',normalize-space(@class),' '),' fn ') and (local-name() = 'abbr')]/@title),'
',''))))) or (false() = not((.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and
contains(concat(' ',normalize-space(@class),' '),' fn ') and not(local-name() = 'abbr' or localname() = 'img')]) and (string-length(normalize-space(.//*[not(ancestor-or-self::*[local-name() =
'del']) = true() and contains(concat(' ',normalize-space(@class),' '),' fn ') and not(local-name() =
'abbr' or local-name() = 'img' or local-name() = 'area')][1])) = string-length(translate(normalizespace(.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and contains(concat('
',normalize-space(@class),' '),' fn ') and not(local-name() = 'abbr' or local-name() = 'img')][1]),'
','')))))">
http://suda.co.uk/projects/microformats/hcard/xhtml2vcard.xsl
http://thewebsemantic.com
http://jenabean.googlecode.com
6
RDF != XML
“The site at http://www.travelocity.com,
also known as Travelocity, is an online
travel agency competing with
expedia.com”
http://thewebsemantic.com
http://jenabean.googlecode.com
7
Concepts as a Directed Graph
Travelocity
Travelocity.com
Online travel
agency
Expedia.com
http://thewebsemantic.com
http://jenabean.googlecode.com
8
Concepts Serialized as N3
:OnlineTravelAgency
a
owl:Class .
:hasCompetitor
a
rdf:Property .
<http://www.travelocity.com>
a
:OnlineTravelAgency ;
rdfs:label "Travelocity"@en ;
:hasCompetitor <http://www.expedia.com> .
http://thewebsemantic.com
http://jenabean.googlecode.com
9
Concepts Serialized as RDF/XML
<rdf:RDF …>
<owl:Class rdf:about="http://foo#OnlineTravelAgency"/>
<rdf:Property rdf:about="http://foo#hasCompetitor"/>
<OnlineTravelAgency rdf:about="http://www.travelocity.com">
<hasCompetitor rdf:resource="http://www.expedia.com"/>
<rdfs:label xml:lang="en">Travelocity</rdfs:label>
</OnlineTravelAgency>
</rdf:RDF>
http://thewebsemantic.com
http://jenabean.googlecode.com
10
As N-Triples (Most Canonical or Normalized)
<hasCompetitor>
<rdf:type>
<rdf:Property> .
<http://travelocity.com> <hasCompetitor> <http://expedia.com>.
<http://travelocity.com> <rdfslabel>
"Travelocity"@en
<http://travelocity.com> <rdf:type>
<OnlineTravelAgency> .
<OnlineTravelAgency>
<owl:Class> .
<rdf:type>
Subject, Verb, Object = a triple
http://thewebsemantic.com
http://jenabean.googlecode.com
11
As Java Code, using the Jena API
OntModel m = ModelFactory.createOntologyModel();
OntClass ota = m.createClass("OnlineTravelAgency");
Individual tvly =
ota.createIndividual("http://www.travelocity.com");
tvly.setLabel("Travelocity", "en");
OntProperty p = m.createOntProperty("hasCompetitor");
tvly.setPropertyValue(p,
m.createResource("http://www.expedia.com"));
http://thewebsemantic.com
http://jenabean.googlecode.com
12
Creating a Model
1: Model m = ModelFactory.createDefaultModel();
2: m.setNsPrefix("foaf", FOAF.NS);
3: Resource jazoon = m.createResource("http://jazoon.com/");
4: Resource java = m.createResource(
5: "http://dbpedia.org/resource/Java_(software_platform)");
6: jazoon.addProperty(FOAF.primaryTopic, java);
7: m.write(System.out, "N3");
<http://jazoon.com/>
foaf:primaryTopic
<http://dbpedia.org/resource/Java_(software_platform)> .
http://thewebsemantic.com
http://jenabean.googlecode.com
13
Assertion
foaf:primaryTopic
jazoon.com
http://thewebsemantic.com
java
http://jenabean.googlecode.com
14
Creating an Inferencing Model
OntModel infModel = ModelFactory.createOntologyModel(
OntModelSpec.OWL_MEM_MICRO_RULE_INF, m);
infModel.read("http://xmlns.com/foaf/spec/index.rdf");
infModel.writeAll(System.out, "N3",null);
In addition to known data, a new triple is
inferred…
<http://dbpedia.org/resource/Java_(software_platform)>
foaf:isPrimaryTopicOf
<http://jazoon.com/>
http://thewebsemantic.com
http://jenabean.googlecode.com
15
Knowledge after Inference
foaf:Document
Is a
foaf:primaryTopic
jazoon.com
java
foaf:isPrimaryTopicOf
http://thewebsemantic.com
http://jenabean.googlecode.com
16
The Semantic Web is Property focused
> Properties have Classes, not vice versa
> Don’t read “the domain of foaf:knows is a foaf:Person”, but instead
“anything with foaf:knows relationship is a foaf:Person”
> Properties can extend other properties
> Properties can be declared as inverse, symmetric, and transitive, all
resulting in new inferences.
http://thewebsemantic.com
http://jenabean.googlecode.com
17
List All Classes from an Ontology
OntModel model = ModelFactory.createOntologyModel();
model.read("http://xmlns.com/foaf/spec/index.rdf");
ExtendedIterator<OntClass> it = model.listClasses();
while(it.hasNext()) {
OntClass cls = it.next();
if (cls.getNameSpace().equals(FOAF.NS))
System.out.println(cls.getURI());
}
http://thewebsemantic.com
http://jenabean.googlecode.com
18
Models Can be Populated from URL, Either Public
or Local
OntModel model = ModelFactory.createOntologyModel();
// read from URL
model.read("http://xmlns.com/foaf/spec/index.rdf");
model.read("file:mydata.n3","N3");
http://thewebsemantic.com
http://jenabean.googlecode.com
19
Models can be Populated from Other Models
Model modelA = ModelFactory.createDefaultModel();
Model modelB = ModelFactory.createDefaultModel();
…
//Add all statements from modelB to modelA
modelA.add(modelB);
http://thewebsemantic.com
http://jenabean.googlecode.com
20
Some example foaf:
<http://www.ibm.com/developerworks/xml/library/j-jena/>
a dc:Article ;
dc:creator "Philip McCarthy"^^xsd:string ;
dc:subject "jena, rdf, java, semantic web"^^xsd:string ;
dc:title "Introduction to Jena"^^xsd:string .
http://thewebsemantic.com
http://jenabean.googlecode.com
21
Equivalent Raw Jena API Client Code
String NS = "http://purl.org/dc/elements/1.1/";
OntModel m = ModelFactory.createOntologyModel();
OntClass articleCls = m.createClass(NS +"Article");
Individual i = articleCls.createIndividual(
"http://www.ibm.com/developerworks/xml/library/j-jena/");
Property title = m.getProperty(NS + "title");
Literal l = m.createTypedLiteral("Introduction to Jena");
i.setPropertyValue(title,l);
Property creator = m.getProperty(NS + "creator");
l = m.createTypedLiteral("Philip McCarthy");
i.setPropertyValue(creator,l);
Property subject = m.getProperty(NS + "subject");
l = m.createTypedLiteral("jena, rdf, java, semantic web");
i.setPropertyValue(subject,l);
m.write(System.out, "N3");
http://thewebsemantic.com
http://jenabean.googlecode.com
22
Pain Points of Raw Jena API Programming
>
>
>
>
You need to create unique URI’s for every entity.
You must specify the type of each primitive value.
Properties must be created for each bean property.
The impedance mismatch is similar to what we had with RDBMS
http://thewebsemantic.com
http://jenabean.googlecode.com
23
Creating The Same Assertions with JenaBean
Model m = ModelFactory.createDefaultModel();
Bean2RDF writer = new Bean2RDF(m);
Article article = new Article(
"http://www.ibm.com/developerworks/xml/library/j-jena/");
article.setCreator("Philip McCarthy");
article.setTitle("Introduction to Jena");
article.setSubject("jena, rdf, java, semantic web");
writer.save(article);
m.write(System.out, "N3");
http://thewebsemantic.com
http://jenabean.googlecode.com
24
The JenaBean Project
>
>
>
>
>
Hosted at Google code
Bean binding, not code generation
Doesn’t use byte code interweaving
Doesn’t require implementing an interface
http://jenabean.googlecode.com
http://thewebsemantic.com
http://jenabean.googlecode.com
25
Programming with JenaBean is Simple
> Bean2RDF writes objects
> RDF2Bean reads objects
> 3 Annotations
– @Id specifies unique field
– @Namespace provides a domain
– @RdfProperty maps java properties to RDF properties
http://thewebsemantic.com
http://jenabean.googlecode.com
26
The Simplest Possible Example
package examples.model;
import thewebsemantic.Id;
public class Person {
@Id
private String email;
public String getEmail() { return email;}
public void setEmail(String email) {
this.email = email;}
}
<http://examples.model/Person>
a
<http://www.w3.org/2000/01/rdf-schema#Class> ;
<http://thewebsemantic.com/javaclass> "examples.model.Person" .
<http://examples.model/Person/[email protected]>
a
<http://examples.model/Person> ;
<http://examples.model/email>
"[email protected]"^^xsd:string .
http://thewebsemantic.com
http://jenabean.googlecode.com
27
Saving an Instance of Person
Model m = ModelFactory.createOntologyModel();
Bean2RDF writer = new Bean2RDF(m);
Person p = new Person();
p.setEmail("[email protected]");
writer.save(p);
m.write(System.out, "N3");
…
<http://example/Person> a owl:Class ;
<http://thewebsemantic.com/javaclass> "example.Person" .
<http://example/Person/[email protected]> a <http://example/Person> ;
<http://example/email> "[email protected]"^^xsd:string .
http://thewebsemantic.com
http://jenabean.googlecode.com
28
Overriding the Default Namespace
package examples.model;
import thewebsemantic.Id;
import thewebsemantic.Namespace;
@Namespace("http://mydomain#")
public class Person { … }
<http://mydomain#Person>
a
<http://www.w3.org/2000/01/rdf-schema#Class> ;
<http://thewebsemantic.com/javaclass>
"examples.model.Person" .
<http://mydomain#Person/[email protected]>
a
<http://mydomain#Person> ;
<http://mydomain#email>
"[email protected]"^^xsd:string .
http://thewebsemantic.com
http://jenabean.googlecode.com
29
Overriding the Default Property Bindings
@Namespace(“http://mydomain#”)
public class Person {
private String email;
@RdfProperty(FOAF.NS + "name")
private String name;
<http://mydomain#Person>
a
<http://www.w3.org/2000/01/rdf-schema#Class> ;
<http://thewebsemantic.com/javaclass> "examples.model.Person" .
<http://mydomain#Person/[email protected]>
a
<http://mydomain#Person> ;
<http://xmlns.com/foaf/0.1/name> "Taylor Cowan"^^xsd:string .
http://thewebsemantic.com
http://jenabean.googlecode.com
30
Extending Person to Support Friendship
public Collection<Person> friends = new
LinkedList<Person>();
@RdfProperty("http://xmlns.com/foaf/0.1/knows")
public Collection<Person> getFriends() { return friends;}
http://thewebsemantic.com
http://jenabean.googlecode.com
31
Loading Beans from a Model
RDF2Bean reader = new RDF2Bean(m);
Person p = reader.load(Person.class,"[email protected]");
Collection<Person> allPeople = reader.load(Person.class);
http://thewebsemantic.com
http://jenabean.googlecode.com
32
JenaBean Support for OWL Entailments
public class Location {
@Id
public String id;
public String name;
@RdfProperty(transitive=true)
public Collection<Location> within;
@RdfProperty(inverseOf="within")
public Collection<Location> contains;
…
<http://example.transitive/within>
a
rdf:Property , owl:TransitiveProperty .
<http://example.transitive/contains>
a
rdf:Property ;
owl:inverseOf <http://example.transitive/within> .
http://thewebsemantic.com
http://jenabean.googlecode.com
33
Reading Existing RDF/OWL
> Up till this point we were generating the triples
> JenaBean + annotations controlled the URI’s
> The model knew the provenance of all data (the originating java
class)
http://thewebsemantic.com
http://jenabean.googlecode.com
34
Example Geonames “feature” entry
Jenabean will bind to
existing URI’s
<Feature rdf:about="http://sws.geonames.org/3333156/">
<name>London Borough of Islington</name>
<alternateName xml:lang="fr">Islington</alternateName>
<inCountry rdf:resource="http://www.geonames.org/countries/#GB"/>
<population>185500</population>
<wgs84_pos:lat>51.5333333</wgs84_pos:lat>
<wgs84_pos:long>-0.1333333</wgs84_pos:long>
</Feature>
35
Crafting beans for existing RDF requires care
@Namespace("http://www.geonames.org/ontology#")
1
public class Feature {
2
@Id
3 private URI uri;
4
@RdfProperty("http://www.w3.org/2003/01/geo/wgs84_pos#lat")
public double lat;
1.
2.
3.
4.
Namespace must accurately match
Your java’s classname must match the Ontology class
Your @Id must be of type java.net.URI
All property URI’s must match the Ontology property
http://thewebsemantic.com
http://jenabean.googlecode.com
36
JenaBean can auto discover JenaBeans, provided
it knows the package(s)
1:
2:
3:
4:
Model m = ModelFactory.createDefaultModel();
m.read("http://ws.geonames.org/search?q=london&type=rdf");
RDF2Bean reader = new RDF2Bean(m);
reader.bindAll("com.foo", "com.bar");
// type safe binding by class
reader.bind(Feature.class);
// or package
reader.bind(Feature.class.getPackage());
http://thewebsemantic.com
http://jenabean.googlecode.com
37
JenaBean tip: handling lang encoded strings
If your data has something like this:
<alternateName xml:lang="es">Londres</alternateName>
Then use JenaBean‘s special type “LocalizedString“
public Collection<LocalizedString> alternateName;
example.geonames
http://thewebsemantic.com
http://jenabean.googlecode.com
38
Query Support
> Most most practical purposes there’s no need to utilize anything
other than Jena’s ARQ api to query. JenaBean’s reader
(RDF2Bean) can transform a node given it’s URI or it’s
representation as a jena Resource…
// load using a Jena Resource
reader.load(Human.class, jenaResource);
// load any node using it’s URI
reader.load(Human.class, "http://any.uri");
http://thewebsemantic.com
http://jenabean.googlecode.com
39
thewebsemantic.Sparql Util
String query =
"prefix ntn: <http://semanticbible.org/ns/2006/NTNames#>\n" +
"SELECT ?s WHERE { ?s a ntn:Woman }";
Model m = ModelFactory.createOntologyModel();
m.read("file:NTNames.owl");
m.read("file:NTN-individuals.owl");
RDF2Bean reader = new RDF2Bean(m);
reader.bindAll("example.query");
Collection<Woman> women = Sparql.exec(m, Woman.class, query);
for (Human human : women)
System.out.println(human.label + ":" + human.comment);
example.query
http://thewebsemantic.com
http://jenabean.googlecode.com
40
Summary
@Namespace(“http://yournamespace.goes.here”)
Applies to class declaration
@Id
Applies to field or getter method
Should be a String or primitive type, or wrapper type
type java.net.URI is special
@RdfProperty(“http://specific.property.uri”)
Applies to field or getter method
Remember: by definition, JavaBeans must have a default constructor.
http://thewebsemantic.com
http://jenabean.googlecode.com
41
Summary
writer.save(mybean)
writer.saveDeep(mybean)
Save this and all related objects
reader.load(Class.class, key);
reader.loadDeep(…);
take care, could place entire graph into memory.
reader.bindAll(package, package, …);
Makes jenabean aware of your beans
http://thewebsemantic.com
http://jenabean.googlecode.com
42
JenaBean Fluent Programming API
>
>
>
>
>
>
>
AKA method chaining, foo.this().that().bar();
A “Fluent Interface” aims to provide more readable code
A significant departure from JavaBeans
Is always connected to the jena graph
Entirely interface (not class) driven
Allows Individuals to morph into their various classes
Allows use of vocabulary terms against any Individual regardless
of classification.
http://thewebsemantic.com
http://jenabean.googlecode.com
Example: wgs84 geo vocabulary
import thewebsemantic.As;
import thewebsemantic.Functional;
import thewebsemantic.Namespace;
@Namespace("http://www.w3.org/2003/01/geo/wgs84_pos#")
public interface Geo extends As {
interface Point extends Geo{}
@Functional
Geo lat(float l);
Float lat();
@Functional
Geo long_(float l);
Float long_();
}
http://thewebsemantic.com
http://jenabean.googlecode.com
43
44
A fluent api + good IDE makes things fun
http://thewebsemantic.com
http://jenabean.googlecode.com
45
Create a new anonymous iCal event.
Ical t =
new Thing(m).isa(Ical.Vevent.class);
Create a new iCal event with URI
Ical t =
new Thing(“http://uri”, m).
isa(Ical.Vevent.class);
http://thewebsemantic.com
http://jenabean.googlecode.com
46
Full Example: Creating an iCal event for the
meetup
1: Ical.Vevent t = new Thing(m).isa(Ical.Vevent.class);
2: t.uid("[email protected]").
3:
dtstart("20100124T200000Z").
4:
dtend("20100124T220000Z").
5:
summary("Jena Semantic Web…").
6:
location("Parisoma - …")
7: .as(Geo.class).
8:
lat(37.77f).
9:
long_(-122.41f);
[]
http://thewebsemantic.com
a
ical:Vevent ;
ical:dtend "20100124T220000Z" ;
ical:dtstart "20100124T200000Z" ;
ical:location "Parisoma - " ;
ical:summary "Jena Semantic Web…" ;
ical:uid "[email protected]" ;
geo:lat "37.77"^^xsd:float ;
geo:long "-122.41"^^xsd:float .
http://jenabean.googlecode.com
47
JenaBean comes with a few common vocabulary
interfaces
>
>
>
>
>
>
>
>
>
thewebsemantic.vocabulary.Foaf
Geo
Ical
DCTerms
Sioc
Skos
Rdfs
ReviewVocab
You may want to copy and modify in some cases.
http://thewebsemantic.com
http://jenabean.googlecode.com
48
Fluent API summary:
> Your interface should extend thewebsemantic.As
> Provides polymorphic “as(Class)” to other vocabs.
> Provides easy type declaration with “isa(Class)”
> Use the @Namespace annotation to bind to the vocabulary
> Name setters according to vocab, taking either an Object (literal) or
anther Thing (relationship to other Individuals)
> Name getters according to vocab, returning the same vocabulary type
and taking no arguments.
> If the vocabulary term collides with reserved term (as with long), append
a dash.
> Plural properties should return a Collection.
http://thewebsemantic.com
http://jenabean.googlecode.com
49
Project Ideas
> Create your own foaf document using
the fluent interface.
> Integrate Jena/JenaBean with restlets
– restlets.org
> Use your favorite framework (struts,
stripes, spring mvc) and create a user
registration screen.
> Write JenaBeans that bind to jamendo
or other music ontology at
http://dbtune.org
> Write a foaf crawler beginning with
Berners-Lee that traverses his social
graph.
http://thewebsemantic.com
cc nickjohnson http://flickr.com/photots/npj/
http://jenabean.googlecode.com
50
Open Source Tools For Java Devs
> Java Triple Stores
– Jena (HP Labs)
– Sesame OpenRDF (Aduna)
– Mulgara
> Java Binding tools
– JenaBean (Jena)
– Jastor (Jena)
–
–
–
Owl2Java (Jena)
Elmo (Sesame)
Empire
http://thewebsemantic.com
cc nickjohnson http://flickr.com/photots/npj/
http://jenabean.googlecode.com
Taylor Cowan
http://thewebsemantic.com
http://twitter.com/tcowan
Travelocity
[email protected]
http://thewebsemantic.com
http://jenabean.googlecode.com