http://thewebsemantic.com http://jenabean.googlecode.com
Programming with JenaBeanSources for examples can be found @
http://jenabean.googlecode.com/svn/jenabean-lab1
Taylor Cowan
Travelocity
8982
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
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 .
7
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");
8
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
9
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");
10
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
11
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
12
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 .
13
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 .
14
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 .
15
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 .
16
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;}
17
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);
18
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> .
19
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)
20
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
21
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
3
4
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
22
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());
23
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
24
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…
25
http://thewebsemantic.com http://jenabean.googlecode.com
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
26
http://thewebsemantic.com http://jenabean.googlecode.com
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.
27
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
28
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.
29
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_();
}
30
http://thewebsemantic.com http://jenabean.googlecode.com
A fluent api + good IDE makes things fun
31
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);
32
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 .
33
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.
34
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.
35
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/
http://thewebsemantic.com http://jenabean.googlecode.com
Taylor Cowanhttp://thewebsemantic.com
http://twitter.com/tcowan