Skip to content

Wrapped sources

Dave Reynolds edited this page May 27, 2014 · 2 revisions

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).

Wrapped data source: WSource

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.

Aside on description caching

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.

WSource key methods

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.

Wrapped result set: WResultSet

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.

Wrapped result row: WQuerySolution

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) ))

Wrapped RDF node: WNode

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.

Clone this wiki locally