- From: Henry Story <henry.story@bblfish.net>
- Date: Thu, 25 Aug 2005 00:10:25 +0200
- To: bloged <users@bloged.dev.java.net>, semanticweb@sun.com, SWIG <semantic-web@w3.org>
I have been wanting to think more carefully about using annotations
recently. As this
topic is making headlines in the blogosphere [1][2] I thought I'd
consider this
here now, and use this as a basis to enter the discussion. I have
already implemented
this in the current BlogEd using a ad-hoc annotation scheme, so this
clearly will work.
If I can put it really concisely, the semantic web is a mathematical
structure based
on graph theory. It has many serializations. One of these is Java. OWL
[3] gives us a
vocabulary to describe object oriented structures such as those given
by java. It is
not obvious from reading the OWL specs, but with annotations it will
become so.
Here is a first attempt at annotation the AtomPerson class
@OWL(AtomPerson.BASE+"Person")
public interface AtomPerson {
String BASE = "https://bloged.dev.java.net/Ontologies/Atom/
2005-01-03/"
@OWL(BASE+"name")
public void setName(String name);
public String getName();
@OWL(BASE+"email")
public void addEmail(URI email); //should be mailto uri?
public Collection<URI> getEmails();
@OWL(BASE+"dateOfBirth")
public void setDateOfBirth(Date birth);
public Date getDateOfBirth();
}
So here we annotate the class and the bean methods with URIs. The
nice thing
is that any instance of this bean can then automatically be
serialized to RDF/XML
or any of the other RDF formats (once one agrees to the correct
serializations for
some of the primitive java types, such as int, or Date)
The above gives us the semantics for RDFS [3.5]. To get OWL we just
need the further
annotation types [4] such as:
- functional: if A rel B and A rel C the A == C
- inverse functional: if A rel C and B rel C then A == B)
- the max number of values for an instance and the min number
(useful for the add... type beans) [4] (the setXXX methods
clearly
have at most one value)
- transitivity (if A rel B rel C then A rel C)
- symmetricity (if A rel B then B rel A)
so for example
@OWL(AtomPerson.BASE+"Person")
public interface AtomPerson {
String BASE = "https://bloged.dev.java.net/Ontologies/Atom/
2005-01-03/"
@OWL(BASE+"name")
public void setName(String name);
public String getName();
@OWL(BASE+"email") @OwlInverseFunctional
public void addEmail(URI email);
public Collection<URI> getEmails();
@OWL(BASE+"dateOfBirth") @OwlMaxCardinality(1) @OwlMinCardinality
(1)
public void setDateOfBirth(Date birth);
public Date getDateOfBirth();
@OWL(BASE+"sibling") @OwlSymmetric @OwlTransitive
public void addSibling(Person sibling);
public Collection<Person> getAllSiblings();
}
So the sibling relation (uniquely identified by the <https://
bloged.dev.java.net/Ontologies/Atom/2005-01-03/sibling> uri
and by the addSibling and getSibling methods) is clearly
-symmetric: because if Christina is my sibling then I am her sibling
-transitive: because if Alex is a sibling of Christina then Alex
is also my sibling
There we have it. We now have written RDF/OWL in java.
What does it give us?
---------------------
- For one we can see how easy it is to understand OWL :-)
- Using URIs for beans is a lot better than using table names. URIs
are *Universal*.
SQL tables layouts are different from one database to the next. It
should be
up to the database administrator only to set the mapping from RDF
into his private
internal scheme. We have done here all the mapping that needs to
be done.
- We can implement our beans by using dynamic proxies or other aspect
oriented
techniques to have our classes mirror an RDF or any normal
relational (SQL)
database
- The above now maps very easily into UML class diagrams (which are
just another
notation for OWL)
- We can annotate normal classes too (with some questions as to how
the behavior is to be
understood)
- others?
Backward compatibility
----------------------
All java beans by default already work this way. All we need to do is
give
every java class a URI. So let us invent a URI scheme for java classes:
<java:com.sun.labs.tools.blog.AtomPerson,1.2>
would be the URI of the current class [6] and the name relation could
be reached
via the URI
<java:com.sun.labs.tools.blog.AtomPerson,1.2/name>
So any java bean can already be transformed into OWL. The OWL
annotation could then
be seen to enable us to override the default URI for the class,
interface or property.
Improvements
------------
In the above I have only annotated the setter method. One could also
annotate the getter,
adder, getAll methods or even a field. This ends up creating too many
places for annotations
I think. Is there a standard solution for this? One of these [7]
would be to just annotate
the variable
@OWL(AtomPerson.BASE+"Person")
public interface AtomPerson {
@Property(read | write) @OWL(BASE+"name")
@OwlMaxCardinality(1) String name;
@Property(read | write) @OWL(BASE+"email")
@OwlInverseFunctional URI email;
@Property(read | write) @OWL(BASE+"dateOfBirth")
@OwlMaxCardinality(1) @OwlMinCardinality(1)
Date birth;
@Property(read | write) @OWL(BASE+"sibling")
@OwlSymmetric @OwlTransitive Person sibling;
}
And apparently we can then use apt[8] to then create the getters,
setters, adders, etc...
Does anyone have any feedback on this? Any ideas where this could be
most usefully discussed?
Henry Story
[1] http://www.softwarereality.com/programming/annotations.jsp
[2] http://members.capmac.org/~orb/blog.cgi/tech/java/
Annotations_are_the.html
[3] http://www.w3.org/2001/sw/WebOnt/
[3.5] http://www.w3.org/TR/rdf-schema/
[4] in the spirit of the article at
http://java.sun.com/developer/technicalArticles/J2SE/
constraints/annotations.html
[5] it seems clear to me that setters and getters don't give us quite
all that
we want. It would be really nice if java beans also had addXXX
and getAllXXX.
[6] https://bloged.dev.java.net/source/browse/bloged/src/com/sun/labs/
tools/blog/AtomPerson.java
[7] see section "Constraints as Part of a Property Annotation" of [4]
[8] http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
Received on Wednesday, 24 August 2005 22:10:39 UTC