| 1 |
9486 |
james_leigh |
----------------------------------------
|
| 2 |
|
james_leigh |
Object Repository
|
| 3 |
|
james_leigh |
----------------
|
| 4 |
|
james_leigh |
James Leigh
|
| 5 |
|
james_leigh |
----------------
|
| 6 |
11597 |
james_leigh |
Feb 2012
|
| 7 |
9423 |
james_leigh |
|
| 8 |
9486 |
james_leigh |
|
| 9 |
9419 |
james_leigh |
Object Repository
|
| 10 |
|
james_leigh |
|
| 11 |
|
james_leigh |
The Object Repository is an extension to the Sesame RDF Repository that
|
| 12 |
|
james_leigh |
allows an RDF store to function as an object store. It maps Java objects
|
| 13 |
|
james_leigh |
to and from RDF resources and OWL classes to Java classes in a
|
| 14 |
|
james_leigh |
non-intrusive manner that enables developers to work with resources
|
| 15 |
11450 |
james_leigh |
stored in an RDF Repository as objects. The Object Repository may also
|
| 16 |
|
james_leigh |
optionally be configured with a BLOB store, to store information-resources.
|
| 17 |
9419 |
james_leigh |
|
| 18 |
|
james_leigh |
Sesame Repositories can be created using the console. Use the connect
|
| 19 |
|
james_leigh |
command to set the data directory before creating a repository using the
|
| 20 |
|
james_leigh |
create command. Once the repository has been created it can be accessed
|
| 21 |
|
james_leigh |
in Java through the RepositoryProvider's getRepositoryManager(dataDir)
|
| 22 |
11769 |
james_leigh |
method, which takes the directory location that was used in
|
| 23 |
9419 |
james_leigh |
the connect command of the console. Then the repository can be accessed
|
| 24 |
|
james_leigh |
using the getRepository(id) method of the returned RepositoryManager.
|
| 25 |
|
james_leigh |
|
| 26 |
|
james_leigh |
The ObjectRepository must be created through the
|
| 27 |
|
james_leigh |
ObjectRepositoryFactory, using the createRepository method, passing an
|
| 28 |
|
james_leigh |
existing Repository. Once the ObjectRepository is created it is like
|
| 29 |
11797 |
james_leigh |
other Sesame RDF Repositories, with full triple access, but it returns an
|
| 30 |
9419 |
james_leigh |
ObjectConnection in the getConnection method. The ObjectConnection is an
|
| 31 |
|
james_leigh |
extension of the RepositoryConnection and includes additional methods
|
| 32 |
12043 |
james_leigh |
for working with objects and information-resources. These objects are actually
|
| 33 |
|
james_leigh |
just proxies to the ObjectConnection that returned them. However, before
|
| 34 |
|
james_leigh |
objects can be returned, object classes must first be created and registered.
|
| 35 |
9419 |
james_leigh |
|
| 36 |
11487 |
james_leigh |
To create classes for the ObjectRepository add the @Iri annotation to
|
| 37 |
9974 |
james_leigh |
all classes and fields (or interfaces and property methods)
|
| 38 |
|
james_leigh |
that should be stored in the repository. Then
|
| 39 |
9419 |
james_leigh |
create an empty 'META-INF/org.openrdf.concepts' file in the root
|
| 40 |
9434 |
james_leigh |
directory (or JAR) of the annotated classes. Once the
|
| 41 |
9421 |
james_leigh |
classes have been created, as shown in Figure 5,
|
| 42 |
9419 |
james_leigh |
they can be used with new ObjectRepositories.
|
| 43 |
|
james_leigh |
|
| 44 |
|
james_leigh |
<<Figure 5. A Class Compatible with the ObjectRepository>>
|
| 45 |
|
james_leigh |
|
| 46 |
|
james_leigh |
+--
|
| 47 |
|
james_leigh |
// Document.java
|
| 48 |
11486 |
james_leigh |
import org.openrdf.annotations.Iri;
|
| 49 |
9419 |
james_leigh |
|
| 50 |
11487 |
james_leigh |
@Iri(Document.NS + "Document")
|
| 51 |
9419 |
james_leigh |
public class Document {
|
| 52 |
11769 |
james_leigh |
public static final String NS = "http://example.com/rdf/2012/gs#";
|
| 53 |
9434 |
james_leigh |
|
| 54 |
11487 |
james_leigh |
@Iri(NS + "title") String title;
|
| 55 |
9434 |
james_leigh |
|
| 56 |
|
james_leigh |
public String getTitle() {
|
| 57 |
|
james_leigh |
return title;
|
| 58 |
|
james_leigh |
}
|
| 59 |
|
james_leigh |
public void setTitle(String title) {
|
| 60 |
|
james_leigh |
this.title = title;
|
| 61 |
|
james_leigh |
}
|
| 62 |
9419 |
james_leigh |
}
|
| 63 |
|
james_leigh |
+--
|
| 64 |
|
james_leigh |
|
| 65 |
|
james_leigh |
To add an object to the ObjectRepository, create an ObjectConnection and
|
| 66 |
11769 |
james_leigh |
call the addObject method (as shown in Figure 6). This method will recursively
|
| 67 |
|
james_leigh |
add all other objects referenced from annotated fields. The addObject method can
|
| 68 |
9419 |
james_leigh |
either automatically create a unique identifier for the object (that
|
| 69 |
|
james_leigh |
might change over time), or add the object using a provided identifier,
|
| 70 |
11769 |
james_leigh |
called a URI. If the object implements the interface RDFObject, the identifier
|
| 71 |
|
james_leigh |
can also be provided using the getResource method. Note that the getConnection
|
| 72 |
|
james_leigh |
method of RDFObject can simple return null by default since it will be
|
| 73 |
|
james_leigh |
overridden when retrieved from the store.
|
| 74 |
|
james_leigh |
|
| 75 |
|
james_leigh |
It is recommended to use a URI for any object that might
|
| 76 |
|
james_leigh |
need to be referenced directly or has a conceptual identity. For all
|
| 77 |
10951 |
james_leigh |
other objects, such as anonymous collections, an automatic identifier
|
| 78 |
|
james_leigh |
may be good enough.
|
| 79 |
9419 |
james_leigh |
|
| 80 |
|
james_leigh |
To retrieve an existing object, use the getObject(Class, Resource)
|
| 81 |
|
james_leigh |
method of the ObjectConnection. The method accepts a URI or an anonymous
|
| 82 |
|
james_leigh |
identifier. An anonymous identifier maybe different for different
|
| 83 |
|
james_leigh |
ObjectConnections and should only be used within a single
|
| 84 |
12043 |
james_leigh |
ObjectConnection. A URI, however, will never change and can be used in any
|
| 85 |
|
james_leigh |
connection. Once the ObjectConnection is closed, the objects it returned
|
| 86 |
|
james_leigh |
must be discarded.
|
| 87 |
9419 |
james_leigh |
|
| 88 |
|
james_leigh |
Removing an object is more difficult, as every property of the object
|
| 89 |
|
james_leigh |
will need to be removed, by setting the fields or properties to null.
|
| 90 |
|
james_leigh |
Furthermore, the type of the object must also be removed from the
|
| 91 |
|
james_leigh |
repository, this can be done using the removeDesignation method of the
|
| 92 |
|
james_leigh |
ObjectConnection.
|
| 93 |
|
james_leigh |
|
| 94 |
|
james_leigh |
<<Figure 6. Using an ObjectConnection>>
|
| 95 |
|
james_leigh |
|
| 96 |
|
james_leigh |
+--
|
| 97 |
|
james_leigh |
// create a Document
|
| 98 |
|
james_leigh |
Document doc = new Document();
|
| 99 |
|
james_leigh |
doc.setTitle("Getting Started");
|
| 100 |
|
james_leigh |
|
| 101 |
|
james_leigh |
// add a Document to the repository
|
| 102 |
|
james_leigh |
ObjectConnection con = repository.getConnection();
|
| 103 |
|
james_leigh |
ValueFactory vf = con.getValueFactory();
|
| 104 |
11769 |
james_leigh |
URI id = vf.createURI("http://example.com/data/2012/getting-started");
|
| 105 |
9970 |
james_leigh |
con.addObject(id, doc);
|
| 106 |
9419 |
james_leigh |
|
| 107 |
|
james_leigh |
// retrieve a Document by id
|
| 108 |
|
james_leigh |
Document doc = con.getObject(Document.class, id);
|
| 109 |
|
james_leigh |
|
| 110 |
|
james_leigh |
// remove a Document from the repository
|
| 111 |
|
james_leigh |
Document doc = con.getObject(Document.class, id);
|
| 112 |
|
james_leigh |
doc.setTitle(null);
|
| 113 |
9970 |
james_leigh |
con.removeDesignation(doc, Document.class);
|
| 114 |
9434 |
james_leigh |
+--
|
| 115 |
|
james_leigh |
|
| 116 |
|
james_leigh |
Objects can also be retrieved by their type using the getObjects(Class)
|
| 117 |
|
james_leigh |
method, which includes subclasses. More fine grained queries can be
|
| 118 |
11496 |
james_leigh |
created using the @Sparql annotation. This annotation should be placed
|
| 119 |
|
james_leigh |
on public or protected methods that have a @Bind annotation on their parameters and have
|
| 120 |
9434 |
james_leigh |
a return type and parameters types of registered concepts or datatypes.
|
| 121 |
|
james_leigh |
The return type may also be a java.util.Set or Result of a concept or
|
| 122 |
9624 |
james_leigh |
datatype and may also be Model and any query result, such as GraphQueryResult,
|
| 123 |
10835 |
james_leigh |
TupleQueryResult, or boolean. Public and protected methods with this annotation will be
|
| 124 |
9434 |
james_leigh |
overridden with an optimized object query execution. The parameters with
|
| 125 |
11769 |
james_leigh |
a @Bind annotation will be available in the query in the variable name
|
| 126 |
|
james_leigh |
provided. The target resource is available in the query using the
|
| 127 |
|
james_leigh |
variable "$this".
|
| 128 |
9419 |
james_leigh |
|
| 129 |
9434 |
james_leigh |
Dynamic queries can be constructed using the prepareObjectQuery method
|
| 130 |
|
james_leigh |
or one of the other prepareQuery methods. The prepareObjectQuery method
|
| 131 |
|
james_leigh |
returns an ObjectQuery that allows objects and their type to be assigned to
|
| 132 |
|
james_leigh |
variables within the query before execution.
|
| 133 |
|
james_leigh |
|
| 134 |
|
james_leigh |
<<Figure 7. Executing Queries>>
|
| 135 |
|
james_leigh |
|
| 136 |
|
james_leigh |
+--
|
| 137 |
|
james_leigh |
|
| 138 |
9419 |
james_leigh |
// retrieve all Documents
|
| 139 |
|
james_leigh |
Result<Document> result = con.getObjects(Document.class);
|
| 140 |
|
james_leigh |
while (result.hasNext()) {
|
| 141 |
|
james_leigh |
out.println(result.next().getTitle());
|
| 142 |
|
james_leigh |
}
|
| 143 |
|
james_leigh |
|
| 144 |
11597 |
james_leigh |
import org.openrdf.annotations.Sparql;
|
| 145 |
|
james_leigh |
import org.openrdf.annotations.Bind;
|
| 146 |
|
james_leigh |
|
| 147 |
9596 |
james_leigh |
// retrieve a Document by title using a named query
|
| 148 |
11769 |
james_leigh |
@Sparql("PREFIX gs:<http://example.com/rdf/2012/gs#>\n"+
|
| 149 |
9434 |
james_leigh |
"SELECT ?doc WHERE {?doc gs:title $title}")
|
| 150 |
11496 |
james_leigh |
public Document findDocumentByTitle(@Bind("title") String title) {
|
| 151 |
9434 |
james_leigh |
return null;
|
| 152 |
|
james_leigh |
}
|
| 153 |
|
james_leigh |
|
| 154 |
11769 |
james_leigh |
|
| 155 |
11450 |
james_leigh |
// retrieve a Document by title using a named query
|
| 156 |
|
james_leigh |
ValueFactory vf = con.getRepository().getValueFactory();
|
| 157 |
11769 |
james_leigh |
URI myQueryID = vf.createURI("http://example.com/rdf/2012/my-query");
|
| 158 |
|
james_leigh |
|
| 159 |
11450 |
james_leigh |
NamedQuery named = con.getRepository().createNamedQuery(myQueryID,
|
| 160 |
11769 |
james_leigh |
"PREFIX gs:<http://example.com/rdf/2012/gs#>\n"+
|
| 161 |
11450 |
james_leigh |
"SELECT ?doc WHERE {?doc gs:title ?title}");
|
| 162 |
|
james_leigh |
|
| 163 |
|
james_leigh |
ObjectQuery query = con.prepareObjectQuery(named.getQueryString());
|
| 164 |
|
james_leigh |
query.setObject("title", "Getting Started");
|
| 165 |
11496 |
james_leigh |
Document doc = query.evaluate(Document.class).singleResult();
|
| 166 |
11450 |
james_leigh |
|
| 167 |
11769 |
james_leigh |
|
| 168 |
9434 |
james_leigh |
// retrieve a Document by title using a dynamic query
|
| 169 |
9419 |
james_leigh |
ObjectQuery query = con.prepareObjectQuery(
|
| 170 |
11769 |
james_leigh |
"PREFIX gs:<http://example.com/rdf/2012/gs#>\n"+
|
| 171 |
9419 |
james_leigh |
"SELECT ?doc WHERE {?doc gs:title ?title}");
|
| 172 |
|
james_leigh |
query.setObject("title", "Getting Started");
|
| 173 |
11496 |
james_leigh |
Document doc = query.evaluate(Document.class).singleResult();
|
| 174 |
9419 |
james_leigh |
+--
|
| 175 |
9434 |
james_leigh |
|
| 176 |
11769 |
james_leigh |
Concepts
|
| 177 |
|
james_leigh |
|
| 178 |
|
james_leigh |
Concepts are a hierarchical model of resource classes, that include a
|
| 179 |
|
james_leigh |
description of supported operations on a type, including syntax and semantics.
|
| 180 |
|
james_leigh |
A concept defines the properties and methods available to objects retrieved from
|
| 181 |
|
james_leigh |
the store.
|
| 182 |
|
james_leigh |
|
| 183 |
|
james_leigh |
Concepts are Java classes or interfaces that are mapped to an IRI
|
| 184 |
|
james_leigh |
(Internationalized Resource Identifier). Concepts can be mapped via an @Iri
|
| 185 |
|
james_leigh |
annotation, assigned explicitly in a META-INF/org.openrdf.concepts, or
|
| 186 |
11797 |
james_leigh |
at runtime in an ObjectRepositoryConfig passed to an ObjectRepositoryFactory.
|
| 187 |
11769 |
james_leigh |
If META-INF/org.openrdf.concepts is empty, the path is searched for Concepts
|
| 188 |
|
james_leigh |
with an @Iri annotation. If the file includes a list of class names, only those
|
| 189 |
|
james_leigh |
Concepts will be mapped to the value of their @Iri annotation value. If the file
|
| 190 |
|
james_leigh |
is a Java properties file that maps Concept class names to one or more IRI, the
|
| 191 |
|
james_leigh |
Concepts are mapped to their @Iri value (if present) and its IRIs in the files.
|
| 192 |
|
james_leigh |
|
| 193 |
|
james_leigh |
RDF objects retrieved from the store implement all the concepts that map to one
|
| 194 |
|
james_leigh |
of the URI/IRI rdf:type values of the RDF resource. Any Java field, getter
|
| 195 |
|
james_leigh |
method, or setter method, on a concept, that includes an @Iri annotation will
|
| 196 |
|
james_leigh |
be mapped to an RDF property using the given predicate.
|
| 197 |
|
james_leigh |
|
| 198 |
|
james_leigh |
Mixin Behaviours
|
| 199 |
|
james_leigh |
|
| 200 |
|
james_leigh |
Behaviours are implementations that are mixed into objects, retrieved from the
|
| 201 |
|
james_leigh |
store. By using behaviours, code can be organized by what it does, not just by
|
| 202 |
|
james_leigh |
what it operations on. All methods and interfaces implemented in a Mixin
|
| 203 |
|
james_leigh |
Behaviour are inherited by the relevant objects retrieved from the store. Mixin
|
| 204 |
|
james_leigh |
Behaviours may extend other Mixin Behaviours to inherit and possibly override
|
| 205 |
|
james_leigh |
the super class method implementations.
|
| 206 |
|
james_leigh |
|
| 207 |
|
james_leigh |
Behaviours are Java classes that are mapped to a Concept. Behaviours can be
|
| 208 |
|
james_leigh |
mapped by implementing a Concept interface, assigned to a Concept IRI in a
|
| 209 |
11797 |
james_leigh |
META-INF/org.openrdf.behaviours file, or at runtime in an ObjectRepositoryConfig.
|
| 210 |
11769 |
james_leigh |
If META-INF/org.openrdf.behaviours is empty, the path is searched for Behaviours
|
| 211 |
|
james_leigh |
that implement a Concept with an @Iri annotation. If the file includes a list
|
| 212 |
|
james_leigh |
of class names, only those Behaviours will be mapped to the value of their
|
| 213 |
|
james_leigh |
implementing Concept @Iri annotation value. If the file is a Java properties
|
| 214 |
|
james_leigh |
file that maps Behaviours class names to one or more IRI, the
|
| 215 |
|
james_leigh |
Behaviours are mapped to its IRIs in the files.
|
| 216 |
|
james_leigh |
|
| 217 |
|
james_leigh |
Behaviours need not be concrete classes, they can be abstract. Abstract methods
|
| 218 |
|
james_leigh |
can be called from within a Behaviour to call methods on the proxy object
|
| 219 |
|
james_leigh |
retrieved from the store. Method
|
| 220 |
|
james_leigh |
implementations, of large Concept interfaces, can be organized into multiple
|
| 221 |
|
james_leigh |
abstract Behaviour classes that implement only particular methods. Concept's
|
| 222 |
|
james_leigh |
getter and setter methods, with @Iri annotations, need not be implemented at all.
|
| 223 |
|
james_leigh |
|
| 224 |
|
james_leigh |
Behaviours have the same life cycle as concrete Concepts. They are created
|
| 225 |
|
james_leigh |
within an ObjectConnection for a unique object instance. The object instance
|
| 226 |
|
james_leigh |
is a proxy for the behaviour assigned to a particular resource in the store.
|
| 227 |
|
james_leigh |
The object instance should not be used once the ObjectConnection is closed,
|
| 228 |
|
james_leigh |
and multiple object instances maybe created to proxy behaviour for the same
|
| 229 |
|
james_leigh |
resource of the store within the same ObjectConnection.
|
| 230 |
|
james_leigh |
|
| 231 |
10476 |
james_leigh |
Implementing Inverse Properties
|
| 232 |
|
james_leigh |
|
| 233 |
11496 |
james_leigh |
To simulate inverse properties in Java use named SPARQL queries for the Java getter and setter.
|
| 234 |
10951 |
james_leigh |
|
| 235 |
10476 |
james_leigh |
<<Figure 8. Inverse Property>>
|
| 236 |
|
james_leigh |
|
| 237 |
|
james_leigh |
+--
|
| 238 |
11487 |
james_leigh |
@Iri(FOAF + "Person")
|
| 239 |
10476 |
james_leigh |
public interface Person {
|
| 240 |
11487 |
james_leigh |
@Iri(FOAF + "depiction")
|
| 241 |
10476 |
james_leigh |
Image getDepiction();
|
| 242 |
|
james_leigh |
|
| 243 |
11487 |
james_leigh |
@Iri(FOAF + "depiction")
|
| 244 |
10476 |
james_leigh |
void setDepiction(Image depiction);
|
| 245 |
|
james_leigh |
}
|
| 246 |
|
james_leigh |
|
| 247 |
11487 |
james_leigh |
@Iri(FOAF + "Image")
|
| 248 |
10476 |
james_leigh |
public interface Image {
|
| 249 |
11496 |
james_leigh |
@Sparql(PREFIX + "SELECT ?person { ?person foaf:depiction $this }")
|
| 250 |
10476 |
james_leigh |
Person getDepicts();
|
| 251 |
|
james_leigh |
|
| 252 |
11870 |
james_leigh |
@Sparql(PREFIX + "DELETE { ?p foaf:depiction $this } WHERE { ?p foaf:depiction $this } ;\n"+
|
| 253 |
11496 |
james_leigh |
"INSERT { $person foaf:depiction $this } WHERE {} ")
|
| 254 |
|
james_leigh |
void setDepicts(@Bind("person") Person person);
|
| 255 |
10476 |
james_leigh |
}
|
| 256 |
|
james_leigh |
+--
|
| 257 |
|
james_leigh |
|
| 258 |
11597 |
james_leigh |
Collections
|
| 259 |
|
james_leigh |
|
| 260 |
|
james_leigh |
In RDF the most natural collection is an unordered set, or non-functional
|
| 261 |
|
james_leigh |
property. Sets are triples that share the same subject and predicate.
|
| 262 |
|
james_leigh |
these non-functional properties should have a java.util.Set property type in
|
| 263 |
|
james_leigh |
Java.
|
| 264 |
|
james_leigh |
|
| 265 |
|
james_leigh |
Ordered collections in RDF include rdf:List, rdfs:Container, rdf:Seq, rdf:Alt,
|
| 266 |
|
james_leigh |
and rdf:Bag. AliBaba provides a java.util.List interface for each of these
|
| 267 |
|
james_leigh |
resource types. However, all ordered collections in the RDF store must include
|
| 268 |
|
james_leigh |
an rdf:type on the root node. Often RDF formats that include syntax sugar for
|
| 269 |
|
james_leigh |
rdf:List do not include a rdf:type and may not be readable in AliBaba. To add
|
| 270 |
|
james_leigh |
the missing add the triple rdf:type rdf:List using the add statement method of
|
| 271 |
|
james_leigh |
the ObjectConnection. Other Java collections that implement java.util.List are
|
| 272 |
|
james_leigh |
mapped to rdfs:Container when merged into the store.
|
| 273 |
|
james_leigh |
|
| 274 |
|
james_leigh |
Most RDF stores (like SQL databases) are not optimized for generic ordered
|
| 275 |
|
james_leigh |
collections. Developers will find unordered collections have significantly
|
| 276 |
|
james_leigh |
reduce I/O and better performance. If the elements of an ordered collection
|
| 277 |
|
james_leigh |
will only exist in (at most) one ordered collection, it is recommended instead
|
| 278 |
11797 |
james_leigh |
to use a typed unordered collection (non-functional property) and included a
|
| 279 |
11597 |
james_leigh |
functional index member property on the elements. The elements can then be
|
| 280 |
|
james_leigh |
sorted in memory when necessary.
|
| 281 |
|
james_leigh |
|
| 282 |
|
james_leigh |
Figure 9 show an example of using an unordered collection with an explicit
|
| 283 |
|
james_leigh |
result order. The method getOrderedChildren() will order the nodes in the RDF
|
| 284 |
|
james_leigh |
store (often in memory), while the method getSortedChildren() will sort them in
|
| 285 |
|
james_leigh |
Java. In both cases calling java.util.List#add(Object) has no effect on the RDF
|
| 286 |
|
james_leigh |
store.
|
| 287 |
|
james_leigh |
|
| 288 |
|
james_leigh |
<<Figure 9. Unordered Collection with element index>>
|
| 289 |
|
james_leigh |
|
| 290 |
|
james_leigh |
+--
|
| 291 |
|
james_leigh |
import org.openrdf.annotations.Iri;
|
| 292 |
|
james_leigh |
|
| 293 |
|
james_leigh |
@Iri(NS + "Node")
|
| 294 |
|
james_leigh |
public interface Node {
|
| 295 |
|
james_leigh |
@Iri(NS + "child")
|
| 296 |
|
james_leigh |
Set<Node> getChildren();
|
| 297 |
|
james_leigh |
|
| 298 |
|
james_leigh |
@Iri(NS + "child")
|
| 299 |
|
james_leigh |
void setChildren(Set<Node> children);
|
| 300 |
|
james_leigh |
|
| 301 |
|
james_leigh |
@Iri(NS + "position")
|
| 302 |
|
james_leigh |
Integer getPosition();
|
| 303 |
|
james_leigh |
|
| 304 |
|
james_leigh |
@Iri(NS + "position")
|
| 305 |
|
james_leigh |
void setPosition(Integer position);
|
| 306 |
|
james_leigh |
|
| 307 |
|
james_leigh |
@Sparql(PREFIX
|
| 308 |
|
james_leigh |
+ "SELECT ?child { $this ex:child ?child . ?child ex:position ?position }\n"
|
| 309 |
|
james_leigh |
+ "ORDER BY ?position")
|
| 310 |
|
james_leigh |
List<Node> getOrderedChildren();
|
| 311 |
|
james_leigh |
|
| 312 |
|
james_leigh |
List<Node> getSortedChildren();
|
| 313 |
|
james_leigh |
}
|
| 314 |
|
james_leigh |
|
| 315 |
|
james_leigh |
public abstract class NodeSupport implements Node {
|
| 316 |
|
james_leigh |
public List<Node> getSortedChildren() {
|
| 317 |
|
james_leigh |
Set<Node> live = getChildren();
|
| 318 |
|
james_leigh |
List<Node> memory = new ArrayList<Node>(live);
|
| 319 |
|
james_leigh |
Collections.sort(memory, new Comparator<Node>() {
|
| 320 |
|
james_leigh |
public int compare(Node o1, Node o2) {
|
| 321 |
|
james_leigh |
Integer p1 = o1.getPosition();
|
| 322 |
|
james_leigh |
Integer p2 = o2.getPosition();
|
| 323 |
|
james_leigh |
if (p1 == p2)
|
| 324 |
|
james_leigh |
return 0;
|
| 325 |
|
james_leigh |
if (p1 == null)
|
| 326 |
|
james_leigh |
return -1;
|
| 327 |
|
james_leigh |
if (p2 == null)
|
| 328 |
|
james_leigh |
return 1;
|
| 329 |
|
james_leigh |
return p1.compareTo(p2);
|
| 330 |
|
james_leigh |
}
|
| 331 |
|
james_leigh |
});
|
| 332 |
|
james_leigh |
return memory;
|
| 333 |
|
james_leigh |
}
|
| 334 |
|
james_leigh |
}
|
| 335 |
|
james_leigh |
+--
|
| 336 |
|
james_leigh |
|
| 337 |
11769 |
james_leigh |
Aspect Behaviours
|
| 338 |
10951 |
james_leigh |
|
| 339 |
|
james_leigh |
AliBaba allows any method call (including getters and setters) to be used as
|
| 340 |
11769 |
james_leigh |
join-points. Figure 11 show the Concept interface
|
| 341 |
|
james_leigh |
Person (with an @Iri annotation) which defines a join-point (i.e. declared method)
|
| 342 |
|
james_leigh |
execution(void setDepiction(Image)) and the abstract Behaviour class PersonSupport
|
| 343 |
|
james_leigh |
(implements a Concept interface) defines an aspect for that join-point by using
|
| 344 |
|
james_leigh |
the same method name, parameter types, and return type.
|
| 345 |
|
james_leigh |
|
| 346 |
|
james_leigh |
Multiple aspects may each have their own implementations for the same
|
| 347 |
|
james_leigh |
join-point and, if so, they would be executed serially until all are executed
|
| 348 |
|
james_leigh |
or a non-null (nor primitive 0 nor boolean false) response is given. For more
|
| 349 |
|
james_leigh |
control over the execution order of aspects, AliBaba
|
| 350 |
11496 |
james_leigh |
provides the annotation @Precedes, which can be placed on a behaviour class
|
| 351 |
10951 |
james_leigh |
with a list of other behaviour classes, who's aspects should not be executed
|
| 352 |
11769 |
james_leigh |
before the aspects of this annotated behaviour class.
|
| 353 |
|
james_leigh |
|
| 354 |
|
james_leigh |
Aspects can also intercept
|
| 355 |
11797 |
james_leigh |
method executions by using the annotation @ParameterTypes when declaring a
|
| 356 |
|
james_leigh |
method. The annotation should list the parameter types of the join-point, while
|
| 357 |
|
james_leigh |
the method parameter type is one of ObjectMessage, BooleanMessage, ByteMessage,
|
| 358 |
10951 |
james_leigh |
CharacterMessage, DoubleMessage, FloatMessage, IntegerMessage, LongMessage,
|
| 359 |
|
james_leigh |
ShortMessage, and VoidMessage corresponding to the object or primitive return type of the
|
| 360 |
11797 |
james_leigh |
method/join-point. When the method is executed the parameters of the method
|
| 361 |
11769 |
james_leigh |
call (thus far) and the return type are available through one of the previously
|
| 362 |
11597 |
james_leigh |
listed message interfaces. Figure 11 shows an example of an aspect, which
|
| 363 |
10951 |
james_leigh |
conditionally changes the response of a method call to ensure it is never null.
|
| 364 |
|
james_leigh |
|
| 365 |
11769 |
james_leigh |
Aspect Behaviours have the same life cycle as Mixin Behaviours and are mapped
|
| 366 |
|
james_leigh |
to a Concept in the same way. Like Mixin Behaviours, Aspect Behaviour can be
|
| 367 |
|
james_leigh |
abstract, and any interface they implement will also be implemented by the
|
| 368 |
|
james_leigh |
relevant objects retrieved from the store. The use of @PameterTypes and/or
|
| 369 |
|
james_leigh |
@Precedes annotations distinguish an Aspect Behaviour class from a Mixin
|
| 370 |
|
james_leigh |
Behaviour class.
|
| 371 |
|
james_leigh |
|
| 372 |
11597 |
james_leigh |
<<Figure 11. Intercept method call>>
|
| 373 |
10951 |
james_leigh |
|
| 374 |
|
james_leigh |
+--
|
| 375 |
11487 |
james_leigh |
@Iri(FOAF + "Person")
|
| 376 |
10951 |
james_leigh |
public interface Person {
|
| 377 |
11487 |
james_leigh |
@Iri(FOAF + "depiction")
|
| 378 |
10951 |
james_leigh |
Image getDepiction();
|
| 379 |
|
james_leigh |
|
| 380 |
11487 |
james_leigh |
@Iri(FOAF + "depiction")
|
| 381 |
10951 |
james_leigh |
void setDepiction(Image depiction);
|
| 382 |
|
james_leigh |
}
|
| 383 |
|
james_leigh |
|
| 384 |
|
james_leigh |
public abstract class PersonSupport implements Person, RDFObject {
|
| 385 |
11496 |
james_leigh |
@ParameterTypes({})
|
| 386 |
|
james_leigh |
public Image getDepiction(ObjectMessage msg) throws RepositoryException {
|
| 387 |
10951 |
james_leigh |
Image depiction = (Image) msg.proceed();
|
| 388 |
|
james_leigh |
if (depiction == null) {
|
| 389 |
|
james_leigh |
return (Image) getObjectConnection().getObject(DEFAULT_IMAGE_URI);
|
| 390 |
|
james_leigh |
}
|
| 391 |
|
james_leigh |
return depiction;
|
| 392 |
|
james_leigh |
}
|
| 393 |
11597 |
james_leigh |
|
| 394 |
|
james_leigh |
void setDepiction(Image depiction) {
|
| 395 |
11725 |
james_leigh |
// When @ParameterTypes is not used, proceed() is automatically called
|
| 396 |
11597 |
james_leigh |
System.out.println("setDepiction called with: " + depiction);
|
| 397 |
|
james_leigh |
}
|
| 398 |
10951 |
james_leigh |
}
|
| 399 |
|
james_leigh |
+--
|
| 400 |
|
james_leigh |
|
| 401 |
11769 |
james_leigh |
Advice
|
| 402 |
|
james_leigh |
|
| 403 |
|
james_leigh |
Advice is code that is executed around a method execution. Unlike Aspect
|
| 404 |
|
james_leigh |
Behaviours, Advice has a static life cycle. It is reused for multiple proxy
|
| 405 |
11797 |
james_leigh |
object instances across multiple ObjectConnections. Advice allows the
|
| 406 |
11769 |
james_leigh |
implementation of concerns that crosscut many different methods.
|
| 407 |
|
james_leigh |
|
| 408 |
|
james_leigh |
Advice is mapped to method executions based on the retained annotation types
|
| 409 |
|
james_leigh |
declared on the method. For example, the Advice in Figure 12 check that the
|
| 410 |
|
james_leigh |
caller's code source has permission to call the method.
|
| 411 |
|
james_leigh |
|
| 412 |
|
james_leigh |
List the full class name of an AdviceProvider in the provider services file to
|
| 413 |
|
james_leigh |
assign an AdviceFactory to an retained annotation type. The AdviceFactory
|
| 414 |
|
james_leigh |
assigns Advice to declared methods, with that annotation type, in objects
|
| 415 |
|
james_leigh |
retrieved from the store.
|
| 416 |
|
james_leigh |
|
| 417 |
|
james_leigh |
<<Figure 12. Advice Security>>
|
| 418 |
|
james_leigh |
|
| 419 |
|
james_leigh |
+--
|
| 420 |
|
james_leigh |
@Retention(RetentionPolicy.RUNTIME)
|
| 421 |
|
james_leigh |
@Target(ElementType.METHOD)
|
| 422 |
|
james_leigh |
public @interface ProtectedBy {
|
| 423 |
|
james_leigh |
String value();
|
| 424 |
|
james_leigh |
}
|
| 425 |
|
james_leigh |
|
| 426 |
|
james_leigh |
@Iri(FOAF + "Person")
|
| 427 |
|
james_leigh |
public interface Person {
|
| 428 |
|
james_leigh |
@ProtectedBy("somethingImportantPermission")
|
| 429 |
|
james_leigh |
void doSomethingImportant();
|
| 430 |
|
james_leigh |
}
|
| 431 |
|
james_leigh |
|
| 432 |
|
james_leigh |
public class ProtectedAdvice implements Advice {
|
| 433 |
|
james_leigh |
private SecurityManager sm;
|
| 434 |
|
james_leigh |
private String directive;
|
| 435 |
|
james_leigh |
public ProtectedAdvice(SecurityManager sm, String directive) {
|
| 436 |
|
james_leigh |
this.sm = sm;
|
| 437 |
|
james_leigh |
this.directive = directive;
|
| 438 |
|
james_leigh |
}
|
| 439 |
|
james_leigh |
|
| 440 |
|
james_leigh |
public Object intercept(ObjectMessage msg) throws Exception {
|
| 441 |
|
james_leigh |
sm.checkSecurityAccess(directive);
|
| 442 |
|
james_leigh |
return msg.proceed();
|
| 443 |
|
james_leigh |
}
|
| 444 |
|
james_leigh |
}
|
| 445 |
|
james_leigh |
|
| 446 |
|
james_leigh |
public static class ProtectedAdviceFactory implements AdviceFactory, AdviceProvider {
|
| 447 |
|
james_leigh |
private SecurityManager sm = System.getSecurityManager();
|
| 448 |
|
james_leigh |
public AdviceFactory getAdviserFactory(Class<?> annotationType) {
|
| 449 |
|
james_leigh |
if (sm != null && ProtectedBy.class.equals(annotationType))
|
| 450 |
|
james_leigh |
return this;
|
| 451 |
|
james_leigh |
return null;
|
| 452 |
|
james_leigh |
}
|
| 453 |
11812 |
james_leigh |
public Advice createAdvice(Method method) {
|
| 454 |
11769 |
james_leigh |
ProtectedBy ann = method.getAnnotation(ProtectedBy.class);
|
| 455 |
|
james_leigh |
return new ProtectedAdvice(sm, ann.value());
|
| 456 |
|
james_leigh |
}
|
| 457 |
|
james_leigh |
}
|
| 458 |
|
james_leigh |
|
| 459 |
|
james_leigh |
# META-INF/services/org.openrdf.repository.object.advice.AdviceProvider
|
| 460 |
|
james_leigh |
ProtectedAdviceFactory
|
| 461 |
|
james_leigh |
+--
|
| 462 |
|
james_leigh |
|
| 463 |
11450 |
james_leigh |
Information Resources (BLOBs)
|
| 464 |
|
james_leigh |
|
| 465 |
11769 |
james_leigh |
The method getBlobObject can be used to retrieve a FileObject interface of an
|
| 466 |
11450 |
james_leigh |
information resource by URI. The FileObject interface includes methods to open
|
| 467 |
|
james_leigh |
an InputStream and an OutputStream and will be stored by URI to the configured
|
| 468 |
|
james_leigh |
directory. Changes to the blobs will be isolated from other connections until
|
| 469 |
|
james_leigh |
the changes are committed (if not in autoCommit mode).
|
| 470 |
|
james_leigh |
|
| 471 |
|
james_leigh |
The delegate BlobStore can be set using the setBlobStore method of the
|
| 472 |
|
james_leigh |
ObjectRepository before use. BlobStores are created using the BlobStoreFactory
|
| 473 |
|
james_leigh |
openBlobStore(File) method.
|
| 474 |
|
james_leigh |
|
| 475 |
9434 |
james_leigh |
Generating Concepts
|
| 476 |
9419 |
james_leigh |
|
| 477 |
|
james_leigh |
Compatible class files can be created from RDFS/OWL files, for use with
|
| 478 |
|
james_leigh |
the ObjectRepository in Java, by using the provided owl-compiler.sh (or
|
| 479 |
|
james_leigh |
.bat) file, with main class
|
| 480 |
|
james_leigh |
org.openrdf.repository.object.compiler.Compiler. Use the '-h' option to
|
| 481 |
|
james_leigh |
review the available command line options.
|
| 482 |
|
james_leigh |
|
| 483 |
11769 |
james_leigh |
When precompiled concept interfaces files are not needed in advance, the
|
| 484 |
9419 |
james_leigh |
ObjectRepository can compile them itself. When the AliBaba JARs are
|
| 485 |
|
james_leigh |
added to the console, additional repository templates are included to
|
| 486 |
|
james_leigh |
facilitate creating the ObjectRepository. These include object-memory
|
| 487 |
|
james_leigh |
and object-native (among others). When creating the repository with the
|
| 488 |
|
james_leigh |
console, it will prompt for an OWL Ontology file that should contain the
|
| 489 |
|
james_leigh |
classes and properties needed and/or reference them using owl:imports
|
| 490 |
|
james_leigh |
statements within the file.
|
| 491 |
|
james_leigh |
|
| 492 |
11769 |
james_leigh |
<<Figure 13. Creating ObjectRepository from the Console>>
|
| 493 |
9419 |
james_leigh |
|
| 494 |
|
james_leigh |
+--
|
| 495 |
|
james_leigh |
Commands end with '.' at the end of a line
|
| 496 |
|
james_leigh |
Type 'help.' for help
|
| 497 |
9590 |
james_leigh |
> connect data.
|
| 498 |
9419 |
james_leigh |
Disconnecting from default data directory
|
| 499 |
9590 |
james_leigh |
Connected to data
|
| 500 |
9419 |
james_leigh |
> create object-native.
|
| 501 |
|
james_leigh |
Please specify values for the following variables:
|
| 502 |
|
james_leigh |
Repository ID [native]: foaf
|
| 503 |
|
james_leigh |
Repository title [Native store]: FOAF Store
|
| 504 |
10691 |
james_leigh |
Rollback if multiple states observed (enforce snapshot)? (false|true) [false]:
|
| 505 |
|
james_leigh |
Rollback if outdated state observed (enforce serializable)? (false|true) [false]:
|
| 506 |
|
james_leigh |
Changeset namespace [urn:trx:localhost:]:
|
| 507 |
10840 |
james_leigh |
Archive all removed data (false|true) [false]:
|
| 508 |
|
james_leigh |
If not, archive transactions with removed triples less than [100]:
|
| 509 |
10691 |
james_leigh |
Minimum recent transactions [100]:
|
| 510 |
|
james_leigh |
Maximum recent transactions [1000]:
|
| 511 |
|
james_leigh |
Triple indexes [spoc,posc]:
|
| 512 |
|
james_leigh |
Max Query Time [0]:
|
| 513 |
|
james_leigh |
Default Query Language [SPARQL]:
|
| 514 |
9419 |
james_leigh |
Ontology [http://www.w3.org/2002/07/owl]: http://xmlns.com/foaf/spec/index.rdf
|
| 515 |
9596 |
james_leigh |
Read Schema from Repository [false]:
|
| 516 |
9419 |
james_leigh |
Repository created
|
| 517 |
10691 |
james_leigh |
|
| 518 |
9419 |
james_leigh |
> quit.
|
| 519 |
9590 |
james_leigh |
Disconnecting from data
|
| 520 |
9419 |
james_leigh |
Bye
|
| 521 |
|
james_leigh |
+--
|
| 522 |
|
james_leigh |
|
| 523 |
|
james_leigh |
Scripts can be streamlined by allowing the ObjectRepository to compile
|
| 524 |
11769 |
james_leigh |
the ontology. Shown in Figure 14 is jrunscript (in
|
| 525 |
9419 |
james_leigh |
JavaScript) that outputs a new FOAF file, demonstrating how RDF/Objects
|
| 526 |
|
james_leigh |
can be used without compiling Java files.
|
| 527 |
|
james_leigh |
|
| 528 |
11769 |
james_leigh |
<<Figure 14. JRunScript and ObjectRepository>>
|
| 529 |
9419 |
james_leigh |
|
| 530 |
|
james_leigh |
+--
|
| 531 |
9974 |
james_leigh |
$ jrunscript -J-Djava.ext.dirs=lib:dist
|
| 532 |
9590 |
james_leigh |
js> var rm = org.openrdf.repository.manager.RepositoryProvider.getRepositoryManager("data")
|
| 533 |
9419 |
james_leigh |
js> var repo = rm.getRepository("foaf")
|
| 534 |
|
james_leigh |
js> var con = repo.getConnection()
|
| 535 |
10691 |
james_leigh |
js> con.setAutoCommit(false)
|
| 536 |
|
james_leigh |
js> var Person = "http://xmlns.com/foaf/0.1/Person"
|
| 537 |
|
james_leigh |
js> var base = "http://example.com/person/"
|
| 538 |
|
james_leigh |
js> var james = con.addDesignation(con.getObject(base+"james"), Person)
|
| 539 |
9977 |
james_leigh |
js>
|
| 540 |
11496 |
james_leigh |
js> james.foafFirstName.add("James")
|
| 541 |
|
james_leigh |
js> james.foafSurname.add("Leigh")
|
| 542 |
|
james_leigh |
js> james.foafInterest.add("RDF")
|
| 543 |
10691 |
james_leigh |
js> var arjohn = con.addDesignation(con.getObject(base+"arjohn"), Person)
|
| 544 |
11496 |
james_leigh |
js> arjohn.foafFirstName.add("Arjohn")
|
| 545 |
9434 |
james_leigh |
js> james.foafKnows.add(arjohn)
|
| 546 |
9977 |
james_leigh |
js>
|
| 547 |
10691 |
james_leigh |
js> con.setNamespace("foaf", "http://xmlns.com/foaf/0.1/")
|
| 548 |
9419 |
james_leigh |
js> con['export'](new org.openrdf.rio.rdfxml.RDFXMLWriter(java.lang.System.out), [])
|
| 549 |
|
james_leigh |
<?xml version="1.0" encoding="UTF-8"?>
|
| 550 |
|
james_leigh |
<rdf:RDF
|
| 551 |
|
james_leigh |
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
| 552 |
|
james_leigh |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
| 553 |
|
james_leigh |
|
| 554 |
9434 |
james_leigh |
<rdf:Description rdf:about="http://meta.leighnet.ca/data/rdf/2009/foaf/james">
|
| 555 |
9419 |
james_leigh |
<rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
|
| 556 |
|
james_leigh |
<foaf:firstName>James</foaf:firstName>
|
| 557 |
|
james_leigh |
<foaf:surname>Leigh</foaf:surname>
|
| 558 |
|
james_leigh |
<foaf:interest>RDF</foaf:interest>
|
| 559 |
|
james_leigh |
<foaf:knows rdf:resource="http://meta.leighnet.ca/data/rdf/2009/foaf/arjohn"/>
|
| 560 |
|
james_leigh |
</rdf:Description>
|
| 561 |
|
james_leigh |
|
| 562 |
|
james_leigh |
<rdf:Description rdf:about="http://meta.leighnet.ca/data/rdf/2009/foaf/arjohn">
|
| 563 |
|
james_leigh |
<rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
|
| 564 |
|
james_leigh |
<foaf:firstName>Arjohn</foaf:firstName>
|
| 565 |
|
james_leigh |
</rdf:Description>
|
| 566 |
|
james_leigh |
|
| 567 |
|
james_leigh |
</rdf:RDF>
|
| 568 |
|
james_leigh |
js> con.close()
|
| 569 |
|
james_leigh |
+--
|
| 570 |
9973 |
james_leigh |
|
| 571 |
9974 |
james_leigh |
Message Vocabulary
|
| 572 |
9973 |
james_leigh |
|
| 573 |
10951 |
james_leigh |
In addition to the RDFS and OWL vocabulary, the object repository also supports
|
| 574 |
11769 |
james_leigh |
its own vocabulary for declaring methods (describing messages). This vocabulary
|
| 575 |
|
james_leigh |
can be used to declare interface methods. These abstract methods or message classes
|
| 576 |
10951 |
james_leigh |
can be created by extending the class msg:Message and creating restrictions for
|
| 577 |
|
james_leigh |
its msg:target and response properties (msg:object msg:objectSet msg:literal
|
| 578 |
11769 |
james_leigh |
msg:literalSet).
|
| 579 |
|
james_leigh |
|
| 580 |
|
james_leigh |
Method annotations and parameter annotations can be added to the generated
|
| 581 |
|
james_leigh |
interfaces by using OWL annotation properties. Generated Java annotations
|
| 582 |
|
james_leigh |
are created with String array values.
|
| 583 |
|
james_leigh |
|
| 584 |
|
james_leigh |
To add the @Sparql annotation use the OWL annotation property msg:sparql on
|
| 585 |
|
james_leigh |
the message class.
|
| 586 |
9974 |
james_leigh |
|
| 587 |
11769 |
james_leigh |
Show in
|
| 588 |
|
james_leigh |
Figure 15 is a sample of what a message might look like in turtle.
|
| 589 |
|
james_leigh |
|
| 590 |
|
james_leigh |
<<Figure 15. Sample Usage of Message Vocabulary>>
|
| 591 |
9973 |
james_leigh |
|
| 592 |
9974 |
james_leigh |
+--
|
| 593 |
|
james_leigh |
@prefix xsd:<http://www.w3.org/2001/XMLSchema#>.
|
| 594 |
|
james_leigh |
@prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>.
|
| 595 |
|
james_leigh |
@prefix owl:<http://www.w3.org/2002/07/owl#>.
|
| 596 |
10835 |
james_leigh |
@prefix msg:<http://www.openrdf.org/rdf/2011/messaging#>.
|
| 597 |
11769 |
james_leigh |
@prefix :<http://example.com/rdf/2012/example#>.
|
| 598 |
9973 |
james_leigh |
|
| 599 |
9974 |
james_leigh |
# Declare classes and properties for this example
|
| 600 |
11769 |
james_leigh |
:Mammal rdfs:subClassOf owl:Thing.
|
| 601 |
9974 |
james_leigh |
:Person rdfs:subClassOf :Mammal.
|
| 602 |
|
james_leigh |
:Dog rdfs:subClassOf :Mammal.
|
| 603 |
|
james_leigh |
|
| 604 |
11769 |
james_leigh |
:dateOfBirth a owl:FunctionalProperty, owl:DatatypeProperty;
|
| 605 |
9974 |
james_leigh |
rdfs:domain :Mammal;
|
| 606 |
|
james_leigh |
rdfs:range xsd:date.
|
| 607 |
|
james_leigh |
|
| 608 |
9977 |
james_leigh |
# Common message that responds with the current date time
|
| 609 |
10835 |
james_leigh |
:GetCurrentTime rdfs:subClassOf msg:Message;
|
| 610 |
11769 |
james_leigh |
rdfs:subClassOf [owl:onProperty msg:target; owl:allValuesFrom :Mammal];
|
| 611 |
10835 |
james_leigh |
rdfs:subClassOf [owl:onProperty msg:literal; owl:allValuesFrom xsd:dateTime];
|
| 612 |
11769 |
james_leigh |
msg:sparql "SELECT (now() AS ?now) {}".
|
| 613 |
9974 |
james_leigh |
|
| 614 |
11769 |
james_leigh |
# Declare method that take a date time and responds with the mammal's age at that time
|
| 615 |
|
james_leigh |
# This message uses the parameter "when" as a query parameter
|
| 616 |
|
james_leigh |
:GetAgeAt rdfs:subClassOf msg:Message;
|
| 617 |
|
james_leigh |
rdfs:subClassOf [owl:onProperty msg:target; owl:allValuesFrom :Mammal];
|
| 618 |
|
james_leigh |
rdfs:subClassOf [owl:onProperty msg:literal; owl:allValuesFrom xsd:integer];
|
| 619 |
|
james_leigh |
msg:sparql """
|
| 620 |
|
james_leigh |
PREFIX :<http://example.com/rdf/2012/example#>
|
| 621 |
|
james_leigh |
SELECT DISTINCT ((year($when) - year(?birth)) AS ?age) {
|
| 622 |
|
james_leigh |
$this :dateOfBirth ?birth
|
| 623 |
|
james_leigh |
}
|
| 624 |
9974 |
james_leigh |
""".
|
| 625 |
|
james_leigh |
|
| 626 |
11769 |
james_leigh |
:when a owl:FunctionalProperty, owl:DatatypeProperty;
|
| 627 |
|
james_leigh |
rdfs:domain :GetAgeAt;
|
| 628 |
9974 |
james_leigh |
rdfs:range xsd:dateTime.
|
| 629 |
|
james_leigh |
|
| 630 |
|
james_leigh |
# Dog's age is calculated differently than other mammals
|
| 631 |
11769 |
james_leigh |
# This message is a specialization of the previous and overrides it for all dogs
|
| 632 |
|
james_leigh |
:GetDogAgeAt owl:intersectionOf (:GetAgeAt [owl:onProperty msg:target; owl:allValuesFrom :Dog]);
|
| 633 |
|
james_leigh |
msg:sparql """
|
| 634 |
|
james_leigh |
PREFIX :<http://example.com/rdf/2012/example#>
|
| 635 |
|
james_leigh |
SELECT DISTINCT ((year($when) * 7 - year(?birth) * 7) AS ?age) {
|
| 636 |
|
james_leigh |
$this :dateOfBirth ?birth
|
| 637 |
9974 |
james_leigh |
}
|
| 638 |
|
james_leigh |
""".
|
| 639 |
|
james_leigh |
|
| 640 |
|
james_leigh |
# Some sample data to test with
|
| 641 |
|
james_leigh |
:jack a :Dog;
|
| 642 |
|
james_leigh |
:dateOfBirth "2005-02-18"^^xsd:date.
|
| 643 |
|
james_leigh |
|
| 644 |
|
james_leigh |
:mel a :Person;
|
| 645 |
|
james_leigh |
:dateOfBirth "1956-01-03"^^xsd:date.
|
| 646 |
|
james_leigh |
|
| 647 |
|
james_leigh |
:lucia a :Person;
|
| 648 |
|
james_leigh |
:dateOfBirth "2009-10-30"^^xsd:date.
|
| 649 |
|
james_leigh |
+--
|
| 650 |
|
james_leigh |
|
| 651 |
11769 |
james_leigh |
When an object repository is set to use the Ontology in Figure 15, the
|
| 652 |
11797 |
james_leigh |
repository in Figure 16 can be used to evaluate the messages and calculate the
|
| 653 |
11769 |
james_leigh |
age as shown in Figure 17. Since an empty prefix was used in the ontology, no prefix is used when
|
| 654 |
|
james_leigh |
calling messages (or properties). If the schema changes at runtime the method
|
| 655 |
|
james_leigh |
ObjectConnection#recompileSchemaOnClose() should be called to compile the
|
| 656 |
|
james_leigh |
changes within the ObjectConnection#close() method.
|
| 657 |
9974 |
james_leigh |
|
| 658 |
11769 |
james_leigh |
<<Figure 16. Creating ObjectRepository from the Console>>
|
| 659 |
9974 |
james_leigh |
|
| 660 |
|
james_leigh |
+--
|
| 661 |
10840 |
james_leigh |
Commands end with '.' at the end of a line
|
| 662 |
|
james_leigh |
Type 'help.' for help
|
| 663 |
|
james_leigh |
> connect data.
|
| 664 |
|
james_leigh |
Disconnecting from default data directory
|
| 665 |
|
james_leigh |
Connected to data
|
| 666 |
|
james_leigh |
> create object-native.
|
| 667 |
|
james_leigh |
Please specify values for the following variables:
|
| 668 |
|
james_leigh |
Repository ID [native]: mammals
|
| 669 |
|
james_leigh |
Repository title [Native store]: Mammal Store
|
| 670 |
|
james_leigh |
Rollback if multiple states observed (enforce snapshot)? (false|true) [false]:
|
| 671 |
|
james_leigh |
Rollback if outdated state observed (enforce serializable)? (false|true) [false]:
|
| 672 |
|
james_leigh |
Changeset namespace [urn:trx:localhost:]:
|
| 673 |
|
james_leigh |
Archive all removed data (false|true) [false]:
|
| 674 |
|
james_leigh |
If not, archive transactions with removed triples less than [100]:
|
| 675 |
|
james_leigh |
Minimum recent transactions [100]:
|
| 676 |
|
james_leigh |
Maximum recent transactions [1000]:
|
| 677 |
|
james_leigh |
Triple indexes [spoc,posc]:
|
| 678 |
|
james_leigh |
Max Query Time [0]:
|
| 679 |
|
james_leigh |
Default Query Language [SPARQL]:
|
| 680 |
|
james_leigh |
Ontology [http://www.w3.org/2002/07/owl]:
|
| 681 |
|
james_leigh |
Read Schema from Repository [false]: true
|
| 682 |
|
james_leigh |
Repository created
|
| 683 |
|
james_leigh |
|
| 684 |
|
james_leigh |
> open mammals.
|
| 685 |
|
james_leigh |
Opened repository 'mammals'
|
| 686 |
11769 |
james_leigh |
mammals> load mammal.ttl.
|
| 687 |
10840 |
james_leigh |
Loading data...
|
| 688 |
|
james_leigh |
Data has been added to the repository (3048 ms)
|
| 689 |
|
james_leigh |
mammals> quit.
|
| 690 |
|
james_leigh |
Closing repository 'mammals'...
|
| 691 |
|
james_leigh |
Disconnecting from data
|
| 692 |
|
james_leigh |
Bye
|
| 693 |
|
james_leigh |
+--
|
| 694 |
|
james_leigh |
|
| 695 |
11769 |
james_leigh |
<<Figure 17. Calling Object Messages from JavaScript>>
|
| 696 |
10840 |
james_leigh |
|
| 697 |
|
james_leigh |
+--
|
| 698 |
|
james_leigh |
$ jrunscript -J-Djava.ext.dirs=lib:dist
|
| 699 |
|
james_leigh |
js> var rm = org.openrdf.repository.manager.RepositoryProvider.getRepositoryManager("data")
|
| 700 |
|
james_leigh |
js> var repo = rm.getRepository("mammals")
|
| 701 |
9974 |
james_leigh |
js> var con = repo.getConnection()
|
| 702 |
11769 |
james_leigh |
js> var jack = con.getObject("http://example.com/rdf/2012/example#jack")
|
| 703 |
|
james_leigh |
js> var mel = con.getObject("http://example.com/rdf/2012/example#mel")
|
| 704 |
|
james_leigh |
js> var lucia = con.getObject("http://example.com/rdf/2012/example#lucia")
|
| 705 |
|
james_leigh |
js> var now = jack.GetCurrentTime()
|
| 706 |
|
james_leigh |
js> jack.GetAgeAt(now)
|
| 707 |
|
james_leigh |
49
|
| 708 |
|
james_leigh |
js> mel.GetAgeAt(now)
|
| 709 |
|
james_leigh |
56
|
| 710 |
|
james_leigh |
js> lucia.GetAgeAt(now)
|
| 711 |
|
james_leigh |
3
|
| 712 |
9974 |
james_leigh |
js> con.close()
|
| 713 |
|
james_leigh |
+--
|
| 714 |
|
james_leigh |
|
| 715 |
9419 |
james_leigh |
The ObjectRepository simplifies interacting with RDF resources in OO
|
| 716 |
|
james_leigh |
languages on the JVM. By bridging RDF properties and object properties,
|
| 717 |
|
james_leigh |
creating and manipulating RDF resources is as easy as manipulating objects.
|
| 718 |
|
james_leigh |
|
| 719 |
9486 |
james_leigh |
|