Finding information by performing a GET
on a web of OSLC resources or on a ServiceProvider is a powerful, general mechanism, but sometimes it is inconvenient or inefficient to find specific information this way. To help with this problem, OSLC provides 2 distinct query mechanisms to find information in resources faster.
Starting from an OSLC Resource URL
OSLC implementations may support a technique called Selective Properties to enable clients to retrieve only selected property values of a specific resource. For each resource whose URL is <url>
, an OSLC implementation may define a set of related resources whose URLs are of the form <url>?oslc:properties=
. Each of these resources is a related resource whose representation contains the specified subset of triples of the resource whose URL is <url>
and/or related resources.
Here's how the selective properties values oslc.properties
and oslc.prefix
work.
oslc.properties
The oslc.properties key=value
pair portion of the URL lets you specify the resource with the set of properties you wish to retrieve. Both immediate and nested properties may be specified. A nested property is a property that belongs to the resource referenced by a property value in another resource. Nested properties are enclosed in brace brackets, and this nesting may be done recursively, i.e. a nested property may contain other nested properties.
For example, suppose we have a bug report resource at the following URL:
http://example.com/proj1/4242
Suppose this bug resource has properties such as dcterms:title
, dcterms:description
, and dcterms:creator
, and that dcterms:creator
refers to a foaf:Person
resource that has properties such as foaf:givenName
and foaf:familyName
. Suppose you want to retrieve a resource that includes the dcterms:title
of the bug report and the foaf:givenName
and foaf:familyName
of the person referred to by the bug report’s dcterms:creator
. The following URL illustrates the use of oslc.properties
in the query string of a URL to include those properties:
http://example.com/proj1/4242?oslc.properties=dcterms:title,dcterms:creator{foaf:givenName,foaf:familyName}
This URL identifies a resource whose representation contains exactly the desired information. The representation would look like this:
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix foaf: <http://http://xmlns.com/foaf/0.1/>.
<http://example.com/proj1/4242> dcterms:title "Bug 4242".
<http://example.com/proj1/4242> dcterms:creator <http://example.com/users/1>.
<http://example.com/users/1> foaf:givenName "Dave".
<http://example.com/users/1> foaf:familyName "Johnson".
oslc.prefix
Languages such as Turtle and SPARQL let you define URI prefixes (e.g. dcterms:
) so you can represent URIs more compactly (e.g. dcterms:title
). The use of compact URIs is also convenient when writing query strings. OSLC domain specifications predefine some prefixes for this purpose. For example, the oslc.properties
query string assumes that dcterms:
and foaf:
have been predefined. However, OSLC domain implementations may add new properties and so it is not possible to predefine all prefixes. To handle this situation, you can define additional prefixes in the query string using oslc.prefix
.
Suppose that foaf: was not predefined in the above example. You add its definition to the query string as follows (line breaks added for formatting marked with //
):
http://example.com/proj1/4242 //
?oslc.prefix=foaf=<http://xmlns.com/foaf/0.1/> //
&oslc.properties= //
dcterms:title,dcterms:creator{foaf:givenName,foaf:familyName}.
Starting from a ServiceProvider
The section entitled Starting from an OSLC Resource URL describes how to efficiently extract information from a graph of resources if you have the URL of a specific resource to start from. There is also an important case where the starting point is a ServiceProvider.
In addition to providing queryBases for a ServiceProvider, an OSLC implementation may provide additional resources that allow clients to find selective subsets of the resources and resource properties in queryBases. The URLs of these resources are constructed by adding a query component to the URL of the queryBase rather than to the URL of an OSLC resource. This can be much more convenient and efficient than performing a GET
on the whole container, or paging through the container.
Query Syntax
The OSLC Core Spec Query Specification document defines a standard set of OSLC query parameters.
Query example
In the following examples, assume a ServiceProvider that contains bug reports (and potentially other resources) for a particular project. Assume also that those bug reports point to user accounts. The user accounts could be in the same ServiceProvider as the bug reports, but since the same accounts may be used to identify users in multiple projects, it’s more likely they are held somewhere else. The URL of the queryBase for the ServiceProvider is http://example.com/proj1
and the queryBase resource looks like this:
# the query base for proj1
<http://example.com/proj1>
rdfs:member
<http://example.com/proj1/4242> ,
<http://example.com/proj1/4243> ,
<http://example.com/proj1/4244> ,
<http://example.com/proj1/4245> ,
<http://example.com/proj1/4246> ,
<http://example.com/proj1/4247> ,
<http://example.com/proj1/4248> .
The actual bug report resources look like the following:
# representation of http://example.com/proj1/4242
<http://example.com/proj1/4242>
dcterms:title "Bug 4242" ;
dcterms:creator <http://example.com/users/1> .
# representation of http://example.com/proj1/4243
<http://example.com/proj1/4243>
dcterms:title "Bug 4243" ;
dcterms:creator <http://example.com/users/2> .
# representation of http://example.com/proj1/4244
<http://example.com/proj1/4244>
dcterms:title "Bug 4244" ;
dcterms:creator <http://example.com/users/3> .
# representation of http://example.com/proj1/4245
<http://example.com/proj1/4245>
dcterms:title "Bug 4245" ;
dcterms:creator <http://example.com/users/1> .
# representation of http://example.com/proj1/4246
<http://example.com/proj1/4246>
dcterms:title "Bug 4246" ;
dcterms:creator <http://example.com/users/2> .
# representation of http://example.com/proj1/4247
<http://example.com/proj1/4247>
dcterms:title "Bug 4247" ;
dcterms:creator <http://example.com/users/3> .
# representation of http://example.com/proj1/4248
<http://example.com/proj1/4248>
dcterms:title "Bug 4248" ;
dcterms:creator <http://example.com/users/1> .
Suppose now that we use the query syntax to compose the following URL.
http://example.com/proj1?oslc.where=dcterms:creator=<http:example.com/users/1>
This URL identifies a resource that contains a subset of the queryBase information, as shown here:
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
<http://example.com/proj1>
rdfs:member
<http://example.com/proj1/4242> ,
<http://example.com/proj1/4245> ,
<http://example.com/proj1/4248> .
The example above selected a subset of bug reports based on a property of the bug reports themselves. It is possible to further restrict the list by selecting based on a property of the user resources that the bug reports reference, as shown below. The URL of the query resource is this:
http://example.com/proj1?oslc.where=dcterms:creator{foaf:givenName="Martin" and foaf:familyName="Nally"}
And its representation is this:
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.com/proj1>
rdfs:member
<http://example.com/proj1/4243> ,
<http://example.com/proj1/4246> .
For the purposes of this example, assume the user accounts look like this:
# user 1
<http://example.com/users/1> a foaf:Person ,
foaf:givenName "Dave" ;
foaf:familyName "Johnston" .
# user 2
<http://example.com/users/2> a foaf:Person ,
foaf:givenName "Martin" ;
foaf:familyName "Nally" .
# user 3
<http://example.com/users/3> a foaf:Person ,
foaf:givenName "Arthur" ;
foaf:familyName "Ryman" .
It is also possible to use query to retrieve property values for the bugs and users, not just a list of bugs, as shown in the following example. The URL of the query resource is
http://example.com/proj1?oslc.where=dcterms:creator=<http:example.com/users/3>&oslc.select=dcterms:title
And the resulting representation is this:
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.com/proj1>
rdfs:member
<http://example.com/proj1/4244> ,
<http://example.com/proj1/4247> .
<http://example.com/proj1/4244>
dcterms:title "Bug 4244" .
<http://example.com/proj1/4247>
dcterms:title "Bug 4247" .
Additional Query Capabilities
In addition to the capabilities illustrated in these examples, Query includes syntax for inequality operators (!=, <=, >=, <, >
), the ability to test that a value is an element within a set of values, ordering of results, and full-text searches. See the specification for details.
Guidance on Query
OSLC implementers have a few options when it comes to query. They can implement any of the following:
-
OSLC Query
The OSLC query capabilities are designed to be a compromise. They are powerful enough to be useful to clients, but simple enough to be implemented with reasonable effort by tools. It is not a trivial effort to implement the OSLC Query capabilities, but it’s not an insurmountably difficult problem either. Common approaches to implementing the OSLC query capability are to transform an OSLC query into an existing query API implemented by the tool, or to transform an OSLC query into some query language that is understood by the underlying implementation technologies used by the tool – often SQL on an RDBMS. This mapping will have to take account of the transformation of the OSLC resource model into the target data model as well as the transformation of the OSLC query syntax into the underlying query syntax. The difficulty of this transformation may depend as much on the former as the latter. -
SQL
You might think that since many existing tools are built on RDBMS technologies, it would be trivially simple to offer SQL as a query language. In practice this is usually much harder than it sounds since the internal data model of the tool is often far removed from the simple resource model of OSLC. This means that a transformation between external SQL and internal SQL is needed, and since SQL is a fully-featured query language, it is usually harder to implement this transformation than to implement OSLC Query. -
SPARQL
Another option is to implement SPARQL. Since SPARQL is a sophisticated query language, it is probably not reasonable to expect that tools will implement a SPARQL query capability by transforming it to a different underlying data model and query language supported by the tool’s implementation data management layer, as might be practical for implementing OSLC Query. However, there are a number of freely-available open-source RDF triple-store implementations that offer complete SPARQL query implementations, so another implementation strategy is to make a copy of the most recent version of every resource and put it in an RDF triple-store, keep it up to date in real time, and then offer OSLC users SPARQL query using the SPARQL capabilities of the RDF triple store.
Of course, if the state of the resources in the tool fits well with the relational data model, implementers could use the same technique with RDBMS technologies to expose SQL as a query language. -
Proprietary
Implementing a proprietary query language is always an option, but it has a much lower client value, since a client is faced with the need of “learning” the proprietary query language of each tool.
Learn more about Query Mechanisms in the OSLC Core specification