-
Notifications
You must be signed in to change notification settings - Fork 2
Wrapped sources
Wrapped sources provide convenience functions for access RDF data from templates. The wrapping simplifies the normal Jena API and provides some weak typing (especially allowing properties to be given using simple curie strings).
For use in UI templates the SparqlSource can be wrapped by an instance of WSource which provides scripting-friendly convenience functions.
To configure a wrapped source use something like:
source = com.epimorphics.appbase.data.WSource
source.cacheSize = 1000
source.source = $ssource
The cacheSize setting is optional and controls the number of resource descriptions that will be cached locally.
It is common in UIs to want to want to be able to render a bunch of resources using at least their labels but potentially other properties. The choice of label property to use typically involves selecting from a range of properties (skos:prefLabel, skos:altLabel, rdfs:label, dct:title, foaf:name) and selecting a matching language from a set of label values. When the data source is remote the cost of requesting such label, or broader, descriptions is high.
Appbase handles this by catching partial or complete resource descriptions and provides a means to request appropriate descriptions in batches as well as making individual describe/select requests on demand.
For many methods we need to provide some RDF Node as an argument. The wrapped interfaces allow you to specify such arguments using an instance of Node, RDFNode, a wrapped node (WNode) or a uri/curie string. In particular in templates we frequently use curie strings, which in turn rely on the configured prefixes. We use spec in the tables below to indicate where this flexibility is allowed.
| Method | Explanation |
|---|---|
select(query) |
Run a sparql select query returning a wrapped result set. The query will be expanded to include all relevant prefixes from the app's prefixes |
select(query, var1, spec1, ...) |
As select but prebinds variables. The argument list should be a set of alternating variable name and value pairs |
find(query, var) |
Runs a select query, extracts all values for the given var and returns a list of wrapped nodes for those values |
getNode(spec) |
Return a wrapped node |
describe(set) label(set)
|
Takes a list of wrapped nodes or a wrapped result set and returns a version of it in which every resource has an associated description. A describe call fetches a full sparql DESCRIBE whereas a label call just fetches a set of potential label properties. |
search(query [, limit]) |
Free text search which returns a list of wrapped nodes which match the query, assumes the source supports jena-text. |
Similar to an ARQ ResultSet but where all the values are wrapped nodes suitable for further template access.
| Method | Explanation |
|---|---|
copy() |
Materializes the entire result set in memory as wrapped nodes. The resulting WResultSet can iterated over multiple times whereas the initial WResultSet will materialize wrapped results on demand and will only allow one complete iterable iterator over the set of results. |
getResultVars() |
List of variable names in the query |
A WResultSet is also Iterable which makes it easy to do #foreach loops over the results.
| Method | Explanation |
|---|---|
get(varname) |
Return the value for the given variable in this row of the result set |
Together these make it easy to issue and loop over a sparql query in a velocity template. For example:
#foreach($row in $source.select("SELECT ?i WHERE {?i a ?c}", "c", $uri) )
<tr>
<td>#render($row.i)</td>
</tr>
#end
Here we take a URI $uri for a class (perhaps passed as an query parameter to the template page) and list instances of that class in some given wrapped source $source.
If the #render macro needs access the labels of the instances then it may be more efficient to request these in a batch by changing the first line to:
#foreach($row in $source.label( $source.select("SELECT ?i WHERE {?i a ?c}", "c", $uri) ))
This wraps up a single RDF Node (actually a Node) value. In the case of a resource node it may have an associated description graph which may contain a complete description (result of SPARQL DESCRIBE) or a partial description just containing label values (skos:prefLabel, skos:altLabel, rdfs:label, dct:title, foaf:name). It also has a reference to an associated wrapped source. Requests for labels or other properties of a resource will consult the attached description if present and sufficiently complete, otherwise they will provide an additional query to source. In this way it is possible preload descriptions in a batch call for efficiency, and to cache them across calls, but the API will function whether the descriptions have been preloaded or not.
| Method | Explanation |
|---|---|
isResource() isURIResource() isLiteral() isAnon()
|
Tests if the node is a resource, uri resource, literal or blank node |
isNumber() |
Tests if the node is a literal corresponding to some number (integer, float, decimal) |
asNumber() asInt() asFloat()
|
For a number literal returns its value as an Number, integer or float, throws an exception otherwise |
asLiteral() |
Returns the node as a Literal, or null if it is not a literal node |
getLiteralValue() |
For a literal returns the corresponding java object value |
getDatatype() |
Return the URI for the datatype of a literal, after prefix shortening, e.g. "xsd:string" |
isList() |
Tests if the node is a resource corresponding to a RDF list |
asList() |
Returns the members of the list as a plain java.util.List of wrapped nodes |
getURI() |
Returns the URI of a URI resource |
getLabel() getLabel(language)
|
Return a suitable display label for the node. For a literal node this is just its lexical form. For a resource node it is picks the first value of an ordered list of possible label properties (skos:prefLabel, skos:altLabel, rdfs:label, dct:title, foaf:name). The second call picks the version of the label which corresponds to the given language code if any, otherwise picks a plain literal or whatever language is available. |
getPropertyValue(spec) |
Return a value of the given property on the node as another wrapped node. |
listPropertyValues(spec) |
Return all values of the given property on the node as java.util.List of wrapped nodes. |
hasResourceValue(spec-prop, spec-value) |
Tests if the node has a value for the given property which is the given resource |
listProperties() |
Return a list of all property values for the node. Each entry in the list will be a PropertyValue object containing the property as a wrapped node (getProp()) and its values as a list of wrapped nodes (getValues()). |
listInLinks(spec) |
Return a list of all the wrapped nodes which connected to this one via the specified property |
listInLinks() |
Return all nodes which connection to this one via any property, return is a list of PropertyValue objects, but where the property is being read as inverted. |
connectedNodes(path) |
Return a list of all the wrapped nodes which are connected to this via the given sparql property path expression (which can use prefixes from the app's prefix configuration |
All of the calls that involve access to properties of the node will try to use the node's attached description if it exists but otherwise will trigger a new query to the source.