BeanClassRdfMapping

From Tupelo Wiki

Table of contents

Bean class RDF mappping particulars

To make a bean class RDF mapping (abbreviated to BCM), you may of course use the automated introspection tools. These simple take the class of the bean and examine it , generating a basic vocabulary. This works quite well but there are a few special things that might need to be done.

Tweaking a BCM

How BCMs are generated

A BCM can be created either directly by using the API or automatically Java introspection on a bean class. We will handle introspection from an existing Java class here. A property is deemed to exist when there are a pair of methods of the form setX and getX. The argument of the setter must be the same as the return type of the getter. The name of the property is assumed to be "X". So for example, the following class would follow this contract:

public class MyBean{
   public MyBean(){super();}
   String foo;
   public void setFoo(String foo){this.foo = foo;}
   public String getFoo(){return foo;}
}

Here there is one property named "foo" and it is a String. Only properties with setters and getters can be used in mappings. Other fields cannot be used.

A note on case in property names. We use the java bean specification for this, so generally the first letter of a property is lower case unless the rest of it is upper case. Hence here "foo" is out property, but something like "getURI" and "setURI" would yield a property named "URI" not "uRI".

A very useful way to use the machinery is to have the BCM autogenerated, then change any predicates you need. Generally an autogenerated predicate will be of the form

prefix/beanClassName#propertyName

for example,

http://java.sun.com/org.tupeloproject.kernel.CustomBean#Address

The prefix ("http://java.sun.com/" in this example) may be specified at runtime. Note that the class name is always traced back through inheritance and will be resolved according to:

  • The first interface in the inheritance where the property is defined (so both mutators must be present)
  • If there are multiple interfaces, then the first alphabetically
  • The first class (might be abstract) in the hierarchy where the property is defined.

This allows a reasonable model for tracking down property names. To get a collection of all the property names (as strings) that the mapping has, call

Collection<String> bcm.getPropertyNames();

and to change the predicate for a specific property call

bcm.setPropertyPredicate(String propertyName, Resource newPredicate);

Finally, be sure that you save any changes that you have made to a BCM in the context. This is accomplished by adding the triples for the BCM to the context:

context.addTriples(bcm.toTriples());

or by a call to the bean session:

beanSession.addBeanClassRdfMap(bcm);

Any changes to the BCM will require an explicit save. Be sure you save all BCMs you change.

Writing a BCM from scratch

Why might this be useful? Consider the case that there is data in RDF that a client needs access to. Perhaps writing a bean is unwarranted. A more useful approach might be to write a BCM and use that to make a bean proxy. Another case might be that the data was generated by a bean class to which you have no access. As our example, we will make the BCM from scratch for the following bean:

public class PersonBean {
   public PersonBean() {super();}

   String name;
   public String getName() {return this.name;}
   public void setName(String name) {this.name = name;}

   Collection<PersonBean> friends;
   public Collection<PersonBean> getFriends() {return this.friends;}
   public void setFriends(Collection<PersonBean> friends) {this.friends = friends;}
} 

This models a FOAF person. Our first task is to discuss the vocabulary.

Vocabularies

You will need to have a vocabulary if you are writing your own BCM. There are some that are already available (such as Foaf). Designing a good vocabulary takes time and effort and is well beyond the scope of this article.Fortunately here our needs are quite straightforward. We just need the built in FOAF vocabulary that is found in org.tupeloproject.rdf.Vocabulary.Foaf. This has the type (PERSON) and the two properties, NAME and KNOWS.


Creating the bean class mapping

To create the BCM we must perform the following steps:


  • Make a new instance of the bean class mapping
      BeanClassRdfMapping bcrm = new BeanClassRdfMapping();
  • Set the RDF subject (if we intend to store this mapping in a context for future use). The subject may may be either specified or given a random subject as we have done here.
       bcrm.setSubject(Resource.uriRef());
  • Set the RDF type for the bean. In this case it is a Foaf person
       bcrm.setRdfType(Vocabulary.Foaf.PERSON);
  • Set the name of the class. We do not require the class, just its name.
       bcrm.setJavaClassName(PersonBean.class.getName());
  • Set the properties. One can create the properties and their mutators in great detail, but it is easiest to use the convenience API. The first property is the Foaf name of the person. The type will be a string. The three arguments for this are the predicate, name of the property, which is used to create the mutator methods and the class of the property.

In this example, the predicate foaf:knows corresponds to a collection of people that this person knows. In the bean, they are the values of the "friends" property. The arguments for adding a collection property are identical to that of adding a property:

       bcrm.addProperty(Vocabulary.Foaf.NAME, "name", String.class);
       bcrm.addCollectionProperty(Vocabulary.Foaf.KNOWS, "friends", PersonBean.class);

In addition to single-valued and collection properties, array and map properties are also supported with the following API:

  • addArrayProperty (http://dlt-dev.ncsa.uiuc.edu/javadoc/t2/current/org/tupeloproject/kernel/beans/BeanClassRdfMapping.html#addArrayProperty(org.tupeloproject.rdf.Resource,%20java.lang.String,%20java.lang.Class)) which has identical arguments to the addProperty method. The difference being that and array of the given type will be managed
  • addMapProperty (http://dlt-dev.ncsa.uiuc.edu/javadoc/t2/current/org/tupeloproject/kernel/beans/BeanClassRdfMapping.html#addMapProperty(org.tupeloproject.rdf.Resource,%20java.lang.String,%20java.lang.Class,%20java.lang.Class,%20java.lang.Class)) for any map properties. This has 5 arguments, the predicate, the property name, the desired Map implementation (if you simply supply java.util.Map.class this instructs the system to use the default of java.util.HashMap) and two additional classes for the key and value parameters.

Saving the BCM

Don't forget to save your changes as indicated in the previous section, either by writing them to the context directly or via the bean session.