programming with jena
DESCRIPTION
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. [] a foaf:Person ; foaf:name Taylor Cowan; foaf:weblog ; - PowerPoint PPT PresentationTRANSCRIPT
http://thewebsemantic.com http://jenabean.googlecode.com
Programming with Jena
Sources for examples can be found @
http://jenabean.googlecode.com/svn/jenabean-lab1http://jenabean.googlecode.com/svn/jenaclass
Taylor CowanTravelocity8982
2
http://thewebsemantic.com http://jenabean.googlecode.com
[] 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>;
3
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
4
http://thewebsemantic.com http://jenabean.googlecode.com
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
5
http://thewebsemantic.com http://jenabean.googlecode.com
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(ancestor-or-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(' ',normalize-space(@class),' '),' fn ') and (local-name() = 'abbr')]/@title) and (string-length(normalize-space(.//*[not(ancestor-or-self::*[local-name() = 'del']) = true() and contains(concat(' ',normalize-space(@class),' '),' fn ') and (local-name() = 'abbr')]/@title)) = string-length(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 local-name() = '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(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')][1]),' ','')))))">
http://suda.co.uk/projects/microformats/hcard/xhtml2vcard.xsl
6
http://thewebsemantic.com http://jenabean.googlecode.com
RDF != XML
“The site at http://www.travelocity.com, also known as Travelocity, is an online travel agency competing with expedia.com”
7
http://thewebsemantic.com http://jenabean.googlecode.com
Concepts as a Directed Graph
Travelocity.com Travelocity
Online travel agency
Expedia.com
8
http://thewebsemantic.com http://jenabean.googlecode.com
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> .
9
http://thewebsemantic.com http://jenabean.googlecode.com
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>
10
http://thewebsemantic.com http://jenabean.googlecode.com
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> <rdf:type> <owl:Class> .
Subject, Verb, Object = a triple
11
http://thewebsemantic.com http://jenabean.googlecode.com
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"));
12
http://thewebsemantic.com http://jenabean.googlecode.com
Creating a Model1: 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)> .
13
http://thewebsemantic.com http://jenabean.googlecode.com
Assertion
jazoon.com java
foaf:primaryTopic
14
http://thewebsemantic.com http://jenabean.googlecode.com
Creating an Inferencing ModelOntModel 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);
<http://dbpedia.org/resource/Java_(software_platform)> foaf:isPrimaryTopicOf <http://jazoon.com/>
In addition to known data, a new triple is inferred…
15
http://thewebsemantic.com http://jenabean.googlecode.com
Knowledge after Inference
jazoon.com
java
foaf:primaryTopic
foaf:isPrimaryTopicOf
foaf:DocumentIs a
16
http://thewebsemantic.com http://jenabean.googlecode.com
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.
17
http://thewebsemantic.com http://jenabean.googlecode.com
List All Classes from an OntologyOntModel 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());
}
18
http://thewebsemantic.com http://jenabean.googlecode.com
Models Can be Populated from URL, Either Public or LocalOntModel model = ModelFactory.createOntologyModel();// read from URLmodel.read("http://xmlns.com/foaf/spec/index.rdf");
model.read("file:mydata.n3","N3");
19
http://thewebsemantic.com http://jenabean.googlecode.com
Models can be Populated from Other Models
Model modelA = ModelFactory.createDefaultModel();Model modelB = ModelFactory.createDefaultModel();…//Add all statements from modelB to modelAmodelA.add(modelB);
20
http://thewebsemantic.com http://jenabean.googlecode.com
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 .
21
http://thewebsemantic.com http://jenabean.googlecode.com
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");
22
http://thewebsemantic.com http://jenabean.googlecode.com
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
23
http://thewebsemantic.com http://jenabean.googlecode.com
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");
24
http://thewebsemantic.com http://jenabean.googlecode.com
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
25
http://thewebsemantic.com http://jenabean.googlecode.com
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
26
http://thewebsemantic.com http://jenabean.googlecode.com
The Simplest Possible Examplepackage 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 .
27
http://thewebsemantic.com http://jenabean.googlecode.com
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 .
28
http://thewebsemantic.com http://jenabean.googlecode.com
Overriding the Default Namespacepackage 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 .
29
http://thewebsemantic.com http://jenabean.googlecode.com
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 .
30
http://thewebsemantic.com http://jenabean.googlecode.com
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;}
31
http://thewebsemantic.com http://jenabean.googlecode.com
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);
32
http://thewebsemantic.com http://jenabean.googlecode.com
JenaBean Support for OWL Entailments
public class Location {@Idpublic 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> .
33
http://thewebsemantic.com http://jenabean.googlecode.com
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)
34
Example Geonames “feature” entry
<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>
Jenabean will bind to existing URI’s
35
http://thewebsemantic.com http://jenabean.googlecode.com
Crafting beans for existing RDF requires care
@Namespace("http://www.geonames.org/ontology#")public class Feature {
@Id private URI uri;
@RdfProperty("http://www.w3.org/2003/01/geo/wgs84_pos#lat") public double lat;
12
34
1. Namespace must accurately match2. Your java’s classname must match the Ontology class3. Your @Id must be of type java.net.URI4. All property URI’s must match the Ontology property
36
http://thewebsemantic.com http://jenabean.googlecode.com
JenaBean can auto discover JenaBeans, provided it knows the package(s) 1: Model m = ModelFactory.createDefaultModel();2: m.read("http://ws.geonames.org/search?q=london&type=rdf");3: RDF2Bean reader = new RDF2Bean(m);4: reader.bindAll("com.foo", "com.bar");
// type safe binding by classreader.bind(Feature.class);
// or packagereader.bind(Feature.class.getPackage());
37
http://thewebsemantic.com http://jenabean.googlecode.com
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
38
http://thewebsemantic.com http://jenabean.googlecode.com
Query Support
// load using a Jena Resourcereader.load(Human.class, jenaResource);
// load any node using it’s URIreader.load(Human.class, "http://any.uri");
> 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…
39
http://thewebsemantic.com http://jenabean.googlecode.com
thewebsemantic.Sparql UtilString 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
40
http://thewebsemantic.com http://jenabean.googlecode.com
Summary
@Namespace(“http://yournamespace.goes.here”)Applies to class declaration
@IdApplies to field or getter methodShould be a String or primitive type, or wrapper typetype 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.
41
http://thewebsemantic.com http://jenabean.googlecode.com
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
42
http://thewebsemantic.com http://jenabean.googlecode.com
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.
43
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_();
}
44
http://thewebsemantic.com http://jenabean.googlecode.com
A fluent api + good IDE makes things fun
45
http://thewebsemantic.com http://jenabean.googlecode.com
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);
46
http://thewebsemantic.com http://jenabean.googlecode.com
Full Example: Creating an iCal event for the meetup1: 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);
[] 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 .
47
http://thewebsemantic.com http://jenabean.googlecode.com
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.
48
http://thewebsemantic.com http://jenabean.googlecode.com
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.
49
http://thewebsemantic.com http://jenabean.googlecode.com
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.
cc nickjohnson http://flickr.com/photots/npj/
50
http://thewebsemantic.com http://jenabean.googlecode.com
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
cc nickjohnson http://flickr.com/photots/npj/
http://thewebsemantic.com http://jenabean.googlecode.com
Taylor Cowanhttp://thewebsemantic.com
http://twitter.com/[email protected]