SPARQL Web Pages - User Guide

Version 1.1.0, June 29, 2012

Authors:
Holger Knublauch <holger@topquadrant.com>

NOTE: This requires TopBraid 3.6

Abstract

This document introduces the key elements of the SPARQL Web Pages (SWP) framework. SWP is an RDF-based language for describing user interfaces that render Semantic Web data. Dedicated properties such as ui:view are used to link RDFS/OWL resources with user interface descriptions. User interface components are described with the help of HTML or XML snippets that may contain SPARQL queries to dynamically insert data-driven content.

This document is part of the SPARQL Web Pages Specification.


Table of Contents

 

1 Getting Started with SWP

Semantic Web languages (RDF, OWL, SPARQL, etc) are well established for describing domain models and ontologies. Semantic Web resources have unique identifiers that makes it possible to link them together, and reuse information from distributed repositories.

A key idea of Semantic Web languages is that resources can be self-describing: an instance may point to its class (via rdf:type), and Semantic Web agents can retrieve additional information about the class to learn about its properties, its position in an inheritance hierarchy, and rules or constraints that can be used to infer implicit information from what has been explicitly stated. This ability to dynamically discover what to do with arbitrary RDF resources in an open network is one of the key advantages of RDF over comparable frameworks.

While most existing RDF-based languages focus on describing models, it is usually necessary to apply different frameworks to put those models into user interfaces and executable applications. Frequently, developers use APIs for mainstream languages (such as Jena for Java) to bridge the RDF world with the code that is used for the rest of an application. Bridging mainstream objects with RDF resources is often quite complex, and many of the advantages of a dynamic, declarative and self-describing modeling language like RDF are lost in this process.

SWP takes the Semantic Web ideas one step further and applies them to user interface descriptions. In particular, SWP can be used to make RDF resources self-describing so that generic software agents can learn how to visualize them at execution time. Furthermore, SWP creates a very seamless transition from an application's model to its view (and control) components, reducing the need to switch between languages and paradigms. As a result of this, SWP improves the productivity of modern web developers by supporting a model-driven approach that exploits the strengths of the Semantic Web infrastructure.

1.1 An Example

Assuming you are familiar with HTML and languages like JSP or PHP, then the following SWP snippet may serve as a good introduction to how SWP works. The following (TopBraid Composer) screenshot shows the definition of an SWP view that is associated with the class skos:Concept.

The property ui:instanceView is used to link a class with a SWP snippet. SWP snippets may consist of any textual language, but in particular XML-based notations and here in particular XHMTL. The example above includes a short HTML snippet that defines a rendering of SKOS concepts so that they display the name of the concept in a heading, and then a list of narrower concepts (children). The SWP engine would render an example instance as shown below:

The HTML snippet contains a couple of elements and attributes that are interpreted as instructions by the SWP engine. For example, when executing the construct {= ui:label(?this) }, the engine will invoke the SPARQL function ui:label and insert the function's result into the HTML document. Here, the variable ?this points to the current instance of the class that we are looking at. ui:label is a built-in function that generates a human-readable rendering of a given resource, typically using properties such as rdf:label.

SWP also defines a collection of control elements. In the example above, <ui:forEach> is used to iterate through the results of a SPARQL SELECT query (listing all child concepts of the concept specified by ?this). The control element <ui:resourceView> will recursively insert the best suitable SWP rendering for the specified resource. In the example above, this will insert a hyperlink to the child concepts, but this is entirely model-driven so that the engine may insert other renderings for resources that have different ui:instanceViews associated with them.

1.2 Overview of the SWP Framework

SWP is primarily defined as a collection of RDF vocabularies that can be used to link resources with user interface descriptions. Two key properties for the linkage are ui:view and ui:instanceView. These properties point to UI snippets that are either stored in external text files, or by means of RDF data structures (usually blank nodes). The difference between those two options will be clarified later, in section 6.

The SWP snippets can contain XML elements from a target language such as XHTML or SVG. The snippets can also just create text nodes that may be used to construct JSON and similar languages. The execution of SWP engines usually happens on a server, and that server can consult any number of ontologies to build responses, supporting multiple variations of the Model-View-Control architecture, ranging from simple document generators to complex Ajax use cases.

The key idea of SWP is to embed SPARQL queries and expressions into UI snippets. These SPARQL queries often create new variable values (bindings) that can be used further down the road. For example, if a SELECT query binds a result variable ?narrower then this variable can be used within all child nodes of the element that has created it. It is then possible to write new SPARQL queries that reference the ?narrower variable and have its value pre-bound. These fundemantal topics around variable scoping and SPARQL embedding are covered by the following section 2.

SWP supports various mechanisms for attaching user interface snippets with an RDF model. The starting point is often to have a resource that shall be displayed. Any individual resource can have a link to a SWP snippet using the property ui:view. However, a more common use case is that all instances of a given class (and its subclasses) share the same visualization, and for those the property ui:instanceView can be used. A dedicated control element <ui:resourceView> can be used to insert the appropriate snippet based on those properties. This is explained in detail in section 3.

In addition to attaching (HTML) snippets to RDF classes and instances, SWP makes it easy to modularize UI code into user-defined classes. These classes can be instantiated as new XML tags, and arguments can be passed into the class to populate a snippet called the "prototype" of that class. This approach makes it possible to split long HTML documents into smaller building blocks that are much easier to manage and reuse. User-defined SWP classes will be covered by section 4.

While it is perfectly fine to use SWP only for comparably simple tasks such as generating a documentation page from an ontology, the framework has been designed to also cover more complex use cases, including complete web applications with multiple interlinked pages and Ajax callbacks. The corresponding control elements and design patterns supported by SWP for application development are introduced by section 5.

1.3 What's new in Version 1.1

SWP version 1.1 introduces several incremental enhancements over earlier versions. Note that you need at least TopBraid 3.6 to use those features:

 

2 Structure of SWP Documents

SWP documents (snippets) must be well-formed XML trees with a single root element. At rendering time, an SWP engine will walk this tree structure starting at the root and evaluate each node recursively. Nodes may have embedded SPARQL expressions, queries and other control elements as described in the following subsections.

2.1 Embedding SPARQL Expressions with {= ... }

SPARQL expressions are SPARQL structures that are typically used in FILTER or LET assignments and that only returns a single value. Examples include (bracketted) expressions, calls of built-ins, or function calls. Any such SPARQL expression can be embedded into a SWP document using the {= ... } syntax as shown in the following example:

    The answer is {= 40 + 2 }

At execution time, the expression will be evaluated, and the result will be inserted into the target document. The result of the mathematical operation above is an RDF literal, and all literals will simply be inserted as their lexical form, e.g. 42. If the result of the expression is a URI resource, then the URI will be inserted, such as in the following example (where ?link is assumed to be bound to a given resource).

    <a href="{= ?link }">Click here</a>

If the expression returns a blank node or unbound, then nothing will be inserted into the target document.

Note that special characters in SWP documents must be escaped according to the usual XML syntax rules. In the example above, " has been escaped with &quot;. Another frequently needed pair of characters is &lt; for < and &gt; for >.

2.2 let: Assignments, Scoping and ui:group

Like most programming languages, SWP allows developers to assign new variables. Any element in a SWP document may contain attributes with the namespace prefix let. In the following example, the variable ?birthYear is bound to 1971. This value can then be used in other SPARQL expressions or queries contained within the children of the element holding the let: assignment.

    <div let:birthYear="{= xsd:integer(1971) }"> 
        Your age is {= 2010 - ?birthYear } years.
    </div>

In general, variables bound in one element will be visible in all children (recursively) but not in the siblings of that element.

In some cases, it is desirable to create a variable binding without having to create an XML element that would go into the target document. In those cases, the control element ui:group can be used as an empty element to hold those. In the following example, only the text is created, and (unlike in the snippet above) no extra div:

    <ui:group let:birthYear="{= xsd:integer(1971) }"> 
        Your age is {= 2010 - ?birthYear } years.
    </ui:group>

Tip: The control element ui:group is also useful in cases where the result of the SWP rendering is not a well-formed XML document (with a single root etc), but rather some text such as JSON. You basically create a single ui:group as root and then only use text nodes and other control elements.

2.3 Embedding SPARQL Queries with {# ... } and letrs:

Taking the idea of embedded SPARQL expressions further, it is also possible to embed SPARQL SELECT queries into SWP documents, surrounded by {# ... }. The result of such queries depends on the context though, and the result may either be interpreted as a tabular SPARQL result set, or just a single value. In the following example, the value of the href attribute will be the first result of the given SELECT query:

    <a href="{# SELECT ?link 
                WHERE { ?this ex:link ?link }
             }">Click here</a>

The example above assumes that there is only a single value for ex:link at the resource specified by ?this. The system will run the query, use its first result value, and discard the rest. Since SPARQL does not give you any guarantees about the order of bindings in a result set, this may actually lead to unpredictable results unless you are using ORDER BY.

Query modifiers (Advanced Topic): SWP supports four system properties ui:queryLimit, ui:queryOffset, ui:queryOrderBy and ui:queryOrderByDir that can be used to modify the SELECT queries found within the same surrounding element. They can be used to specify values for the SPARQL keywords LIMIT, OFFSET and ORDER BY that must be fixed values in standard SPARQL syntax. An example use case of these properties is callbacks for user interface components that require paging through large result sets.

Result Sets as variables: In order to treat the results of a SELECT query as a proper result set, in which multiple rows and columns can be traversed, the letrs: namespace prefix can be used. In the following example, a SELECT query is executed and stored in variable ?rs. The variable points to a spr:Table following the SPIN Result Sets format. This means that it is possible to run queries over the result set itself, e.g. to count the number of rows and columns:

    <ui:group letrs:rs="{#
                SELECT ?firstName ?lastName
                WHERE {
                    ?person ex:firstName ?firstName .
                    ?person ex:lastName ?lastName .
                }
            }">
        This result set has {= spr:rowCount(?rs) } rows and {= spr:colCount(?rs) } columns.
    </ui:group>

The main use case of this will become apparent in the conjunction of ui:forEach, but using letrs: makes it possible to avoid duplicate computations of the same result sets, and to do meta-queries.

2.4 Iterations with ui:forEach

The SWP element ui:forEach can be used to traverse the result set of a SPARQL SELECT query row by row. In each iteration, the result variables of the SELECT query will be bound in the children of the element. The child nodes of the ui:forEach element will be multiplied for each iteration.

The following example produces an HTML list of subclasses of the given resource ?this.

    <h1>Subclasses</h1>
    <ol>
        <ui:forEach ui:resultSet="{#
                       SELECT ?label
                       WHERE {
                           ?subClass rdfs:subClassOf ?this .
                           ?subClass rdfs:label ?label .
                       } ORDER BY ?label }" >
            <li>{= ?label }</li>
        </ui:forEach>
    </ol>

Example output:

    <h1>Subclasses</h1>
    <ol>
        <li>Customer</li>
        <li>Person</li>
    </ol>

As an optional argument of ui:forEach, the name of an index variable can be provided using ui:indexVar. The value of this variable will be the iteration counter, starting with 0.

Another optional argument of ui:forEach is ui:separator. This can contain any string that shall be inserted between each row of the result set. For example, <ui:forEach ui:resultSet="..." ui:separator=",">... will insert a comma between each entry of the output.

Note that the ui:resultSet of the ui:forEach does not need to be a SELECT query by itself. Instead, it is possible to pass in a SPIN Result Set that may have been evaluated in a previous step, e.g. using a letrs: assignment or a SPIN template ui:call, e.g. <ui:forEach ui:resultSet="{= ?rs }"> if the variable ?rs has been bound to a result set in a surrounding element.

TopBraid 4.2 introduces two optional arguments ui:offset and ui:limit that can be used to simulate "paging" through a result set similar to the OFFSET and LIMIT keywords in SPARQL. Their values must be integers.

2.5 Branching with ui:if and ui:else

SWP defines a control element called ui:if that can be used to branch the execution flow depending on a condition. ui:if evaluates an argument ui:condition. If the condition is (the RDF literal) true, then the children of the ui:if will be inserted into the document. Otherwise nothing will be created, unless there is an ui:else branch immediately following the ui:if element.

In the following example, the isIRI function is evaluated on the current binding for ?this. Depending on whether this is true or false, either of the two branches will be inserted: An a hyperlink or a span.

    <ui:if ui:condition="{= isIRI(?this) }">
        <a href="{= ?this }" >{= ui:label(?this) }</a>
    </ui:if>
    <ui:else>
        <span class="blankNode">{= ui:label(?this) }</span>
    </ui:else>

Note that the type of RDF literals will be ignored to simplify the syntax, i.e. "true" is equal to "true"^^xsd:boolean.

TopBraid 4.2 introduces the control element ui:elseif as syntactic sugar for a combination of ui:else with an embedded ui:if. ui:elseif must have a ui:condition argument.

2.6 Using external SPARQL Queries with ui:call

In some cases, embedding complete SPARQL queries makes a SWP document hard to maintain. It is often desirable to keep the queries more cleanly separated from the actual rendering document. SPIN Templates are a powerful mechanism for making SPARQL queries reusable. The basic idea is that queries get a URI and any number of arguments, and those arguments can be filled in when the template is used. The SWP control element ui:call can be used to evaluate SPIN Templates that wrap a SELECT query and to bind the result set to a variable.

The following example assumes that there is a SPIN template ex:GetSubClasses which takes one argument arg:superClass and returns a list of labels for the subclasses of that argument ?superClass. The body of that template may look like the following:

    SELECT ?label
    WHERE {
        ?subClass rdfs:subClassOf ?superClass .
        ?subClass rdfs:label ?label .
    } ORDER BY ?label

A SWP document may now "call" this template with the following syntax:

    <h1>Subclasses</h1>
    <ui:call ui:template="ex:GetSubClasses" arg:superClass="{= ?this }" ui:varName="rs">
        <ol>
            <ui:forEach ui:bindVars="?label" ui:resultSet="{= ?rs }">
                <li>{= ?label }</li>
            </ui:forEach>    
        </ol>    
    </ui:call>

By default, ui:call will put the result set into the variable ?rs, but other variable names can be specified using ui:varName. Also note that the embedded ui:forEach uses ui:bindVars (introduced with TopBraid 4.2) to select which variables from the template call's result set shall be used. The values of ui:bindVars must be comma-separated lists of variable names (spelling out the ? as well as space characters between the variables are OK).

Compared to the example from sub-section 2.4, this snippet with ui:call is potentially easier to read and maintain for the page designer, and the query can be reused in multiple places. The recommended pattern is to store the templates in separate (.spin.) files that do not use any SWP elements, but only contain the "model" or "control" parts of a Model-View-Control architecture.

The main disavantage of using ui:call is that the names of the result variables are not known to the snippet, and in general the binding between the UI code and the queries is a bit loose. It is often a matter of taste which approach works better.

2.7 Setting the Query Context and "Global" Variables with ui:setContext

SPARQL has the notion of the default graph, which is the graph used by the WHERE clause unless some other named graph has been specified (e.g., using GRAPH). In many cases, it is convenient to explicitly switch to a different default graph while the SWP engine executes. In the following example, the control element ui:setContext is used to switch to a different graph for the child nodes.

    <h1>Links</h1>
    <ui:forEach ui:resultSet="{#
                SELECT ?link ?home
                WHERE {
                    ?link a ex:Link .
                    ?link ex:home ?home .
                }
            }"
        <ui:setContext ui:queryGraph="{= ?home }">
            <h2>{= ui:label(?link) }</h2>
            ...
        </ui:setContext>
    </ui:forEach>

The block inside of the setContext element will operate on a different default graph, specified by the variable ?home. This also means that SPARQL functions such as ui:label will use a different context, and may retrieve the rdfs:label from the home graph.

Common use cases of ui:setContext are in conjunction with ui:createLink which is handled further below.

As of SWP 1.1, ui:setContext can also be used to set context variables that can later be queried using the function ui:contextValue. A context variable is visible within all children of the ui:setContext, including the prototypes of any nested elements. In the following example, the variable active can be queried inside of the children and the ex:MyElement element.

    <div>
        <ui:setContext ui:varName="active" ui:varValue="{= true }">
            <span>Active is now {= ui:contextValue('active') }</span>
            <ex:MyElement ... />
        </ui:setContext>
        <-- The variable is no longer bound here -->
    </div>

Note that the values of ui:varValue are turned into string literals by default. If you want to have the variable point to an RDF literal of a different type or a resource node then you need to use the {= ... } notation as in the example above.

2.8 Adding xmlns: declarations using ui:xmlns (Advanced Topic)

Any SWP element may carry the attribute ui:xmlns. The value of this attribute must be a URI resource. If present and if the resource is from a namespace with a valid prefix, then the generated HTML or XML element will have an attribute xmlns: for the namespace of the resource. For example, assuming the prefix ex point to http://example.org/ex#, then the following snippet

    <div ui:xmlns="ex:MyResource" />

will produce

    <div xmlns:ex="http://example.org/ex" />

 

3 Linking Elements with Resources

The SWP vocabulary defines a couple of properties that can be used to associate types of visualizations with certain RDF resources. SWP engines can use these properties to select and propose a suitable screen rendering (or business intelligence report, etc) for a given resource.

3.1 Views for Individual Resources with ui:view

The property ui:view links a specific RDF resource with one or more UI elements.

The following example (in Turtle notation) instructs SWP engines to render the resource ex:PaulPlatypus with the ex:PlatypusImage.

    ex:PaulPlatypus
      a       ex:Platypus ;
      rdfs:label "Paul Platypus"^^xsd:string ;
      ui:view ex:PlatypusImage .

Technically, views must be instances of the class ui:Element or its subclasses. Editing tools such as TopBraid Composer make it easy to edit those views as blank node structures, with a custom HTML-like editor that directly appears on the form of the associated resource. Thus the details of whether a view is an RDF blank node or not become irrelevant. In the following screenshot, a ui:view has been attached to the class skos:Concept:

The variable ?this has a special meaning in such views: it is bound to the surrounding resource. In the example above, ?this will point to the class skos:Concept itself.

If a SWP engine has been asked to render a given resource, it will look for associated value of the ui:view property first. The more common case though is to use ui:instanceView, which is described in the following sub-section.

3.2 Views for Class Members with ui:instanceView

The property ui:instanceView links an RDFS/OWL class with a UI element to instruct an engine to represent all instances of that class with the given visualization. SWP engines should consider inheritance so that visualizations attached to subclasses shall be preferred over those attached to superclasses.

We have already seen an example of ui:instanceView in the introduction. Another example is shown below. In that example, three different views have been attached to the class rdfs:Resource:

In those views, the variable ?this will be pre-bound to the instance that is currently rendered.

The three views above define different ways of visualizing instances of that class. The property ui:id is used to distinguish them. The control element ui:resourceView (described below) can be used to select which of the views shall be picked. A similar mechanism is supported by the SWP server using a servlet argument to specify the matching ids.

The general mechanism for selecting a view also considers a property ui:priority which is also shown in the screenshot above. Each view can have a priority which is used if the same class has multiple views associated with it. A typical use case is the file tui.rdf which defines "global" views that can be applied to all resources. These global views are, as shown above, attached to the class rdfs:Resource. However, someone else may want to override those default views, and create their own alternative views in some other file. In those cases, they should associate a ui:priority higher than the one used by the tui views. Since the default value is 0, it is sufficient to just specify no priority in that particular case.

For a maximum of control over the view selection mechanism, it is possible to use SPIN expressions as values of ui:priority. For example, you can set the priority as ui:priority="{= IF(ui:contextValue('myAppName'), 10, -10) }" to return 10 if the view is used in a given context, and -10 otherwise. This design pattern can be used to define application-specific views: the surrounding code of the application would use ui:setContext to set variables that can be queries in the priority expression.

3.3 Selecting Views with ui:resourceView

One of the strengths of SWP is the linkage between resources (or their classes) and views. This makes it possible to define pages that contain other views as children, and those children are dynamically selected while the page is being created. For example, if you need to display a list of items, and each item may be of an unknown type, then each list item may use a different rendering for the underlying resources - a picture for a foaf:Person, a summary of past purchases for a ex:Customer etc.

The control element ui:resourceView instructs the engine to insert the most suitable rendering of a given resource into the target document. In the following example, ui:resourceView is used to populate a table:

    <table>
        <ui:forEach ui:resultSet="{#
                SELECT ?item
                WHERE {
                    ?this ex:contains ?item .
                } }">
            <tr>
                <td>
                    <ui:resourceView ui:resource="{= ?item }" ui:matchIds="icon" />
                <td>
                <td>
                    <ui:resourceView ui:resource="{= ?item }" ui:matchIds="summary" />
                <td>
            </tr>
        </ui:forEach>
    </table>

ui:resourceView must contain a ui:resource that points to the resource to render. The engine will select a suitable view by means of the following algorithm:

  1. Use the best suitable ui:view of the resource.
  2. Use the most specific ui:instanceView associated with the types of the resource, walking up the parent hierarchy if needed.

As shown in the example for ui:instanceView above, there are sometimes different kinds of views available for a given resource, such as a full page or a shorter summary snippet. In order to distinguish those, the property ui:id can be attached to the views. Suggested values of this property are

The argument ui:matchIds can be set for ui:resourceView control elements to specify which kinds of ids shall be accepted. The values of this argument are comma-separated strings, such as "summary,label" to indicate that a "summary" is preferred, but a "label" would also be accepted if no "summary" exists. If left blank, then only views with no ui:id or with "full" will be selected. If you want to explicitly address view without ui:id, then use *, e.g. "label,*" will first try to find a label and if this fails it will fall back to those views that have no ui:id.

In the example above, the system will create an HTML table with two columns, and one row for each ?item. For the first column, the system will attempt to find a view with the id icon, which may or may not be present. For the second column, the system will insert a summary which is usually always present if the tui ontology has been installed.

3.4 Selecting Views with ui:classView (Advanced Topic)

Very similar to ui:resourceView, the control element ui:classView can be used to insert an SWP view that is attached to a class using ui:instanceView. The main difference though is that ui:classView does not operate on an instance, and the variable ?this is not bound when the view is inserted.

ui:classView is rarely needed but there are use cases where applications want to reuse the same views in different modes, e.g. once as an instance viewer and once as a search form for instances.

The attributes of ui:classView are ui:class to point to the class, and ui:matchIds to select the ids to match. All other arguments that are not from the ui: namespace will be passed as pre-bound variables into the instance view.

 

4 User-Defined Classes

A key benefit of SWP compared to other template languages is the ability to define and instantiate customized object types. User-defined SWP classes are regular RDFS/OWL classes that have a so-called prototype attached to them. Classes may also have arguments, which are mapped to XML attributes when instantiated. The prototype may reference those argument values to generate output. These concepts are explained in detail in the following subsections.

4.1 Prototypes with ui:prototype

The property ui:prototype links a user-defined class with a template instance that serves as blueprint for any instance of the class. At execution time, the SWP engine will create a deep copy of this prototype as a starting point to populate the instance node.

The following example will illustrate this concept. Let's assume we want to (repeatedly) create a HTML list of subclasses of the given class (?superClass). We can define a class ex:SubClassesList as a subclass of ui:Element and of type ui:NodeClass with the following prototype:

    <ul>
        <ui:forEach ui:resultSet="{#
            SELECT ?subClass
            WHERE {
                ?subClass rdfs:subClassOf ?superClass .
            }
            ORDER BY ?subClass }">
            <li>{= ui:label(?subClass) }</li>
        </ui:forEach>
    </ul>

The class must declare that it takes an argument with the local name superClass, e.g. arg:superClass (more on arguments in the next subsection). The new class can now be used as a named XML element anywhere, such as in the following snippet:

    <div>
        <h1>Subclasses of {= ui:label(?this) }</h1>
        <ex:SubClassesList arg:superClass="{= ?this }" />
    </div>

The execution engine will replace any occurrence of the user-defined class with its prototype. The prototype can contain any SWP structure, including control elements.

4.2 Arguments

User-defined classes can be made configurable with arguments. Arguments declare the (XML) attributes that the user can specify for instances of the class. The property spin:constraint is used to link a user-defined class with its spl:Arguments.

Let's assume we want to extend the example from the subsection above, so that we can not only display subclasses, but values of any relationship, such as skos:broader or ex:hasChild. In order to do so, we want to be able to substitute the rdfs:subClassOf predicate with any other given property. We declare an argument with spl:predicate pointing to the property arg:property, having the spl:valueType of rdf:Property. We can now change the prototype of our class to the following:

    <ul>
        <ui:forEach ui:resultSet="{#
            SELECT ?value
            WHERE {
                ?value ?property ?object .
            }
            ORDER BY ?value }">
            <li>{= ui:label(?value) }</li>
        </ui:forEach>
    </ul>

And we can use this new class (now called ex:AnyPropertyList):

    <div>
        <h1>Subclasses of {= ui:label(?this) }</h1>
        <ex:AnyPropertyList arg:property="rdfs:subClassOf" arg:object="{= ?this }" />
    </div>

This creates exactly the same output, but with a more reusable class. Note that the variable ?property will be pre-bound for all nodes of the prototype. The rule is that the system will automatically create variable bindings for variables that have the local name of the predicate declared in the argument. Above, the predicate arg:property will be mapped to the variable ?property, and the property arg:object will be bound to ?object.

Note that if you subclass another SWP class, then all "inherited" arguments will also be bound to variables. Due to this, inheritance hierarchies between SWP classes make most sense to share the definitions of arguments, no matter of whether the prototypes look similar or not.

In some cases, the list of arguments can become quite long, such as in <ex:AnyPropertyList arg:property="{= ?property }" arg:object="{= ?object }" />. If the variables ?property and ?object are already bound in the surrounding elements, then it is sufficient to write <ex:AnyPropertyList ui:args="*" />. The built-in ui:args="*" will automatically match any existing variable bindings from the outside with the declared arguments of the element.

Similar to ui:args="*" it is possible to declare variables that shall be used as default values if no other value is present. The following snippet illustrates the use of the default: namespace for that purpose:

    <ui:group default:property="{= rdfs:label }">
        <ex:AnyPropertyList arg:object="{= ?this }" >
    </ui:group>

default: is similar to let: assignments, but in addition to binding a variable into the current scope, it also instructs the engine to pass its values into namesake arguments of contained elements. In the example above, the argument arg:property is implicitly bound to rdfs:label. Note that default variables will by default be string literals, so if you need proper RDF resources or literals of other datatypes, then use the {= ... } notation.

Classes that only declare arguments, or otherwise group together related classes, can be marked as not instantiable using ui:abstract.

Classes that are meant to be used only within the current file and not outside of it should be marked as ui:private.

The following TopBraid Composer screenshot shows a complete user-defined SWP class as an example.

This example class can be instantiated as shown below:

    <tui:Link tui:node="owl:Thing" />

4.3 Global Includes with ui:headIncludes

The property ui:headIncludes can link a SWP node class with one or more SWP snippets. At execution time, the engine will insert those snippets into the (HTML) head section of the result page (and not into the current context). Typical use cases are JavaScript snippets, the HTML title tag or other global definitions such as inline stylesheets.

In the following example, various components require a global include of a certain JavaScript library. An abstract superclass has been introduced with the following ui:headIncludes:

    <ui:group let:base="lib/extjs/">
        <link href="{= fn:concat(?base, &quot;resources/css/ext-all.css&quot;) }" rel="stylesheet" type="text/css"/>
        <script src="{= fn:concat(?base, &quot;adapter/ext/ext-base.js&quot;) }" type="text/javascript"/>
        <script>Ext.BLANK_IMAGE_URL = '{= ?base }resources/images/default/s.gif';</script>
        <script src="{= fn:concat(?base, &quot;ext-all.js&quot;) }" type="text/javascript"/>
        <script>
            Ext.onReady(function() {
                Ext.QuickTips.init();
            });
        </script>
    </ui:group>

Any component that requires the above snippet in the HTML page can simply be made a subclass of that abstract superclass, inheriting the head includes. Note that the system will prevent duplicate head includes if they originate from the same class.

4.4 Error Handling with ui:errorPrototype and ui:throw (Advanced Topic)

Similar to ui:prototype, the property ui:errorPrototype links a user-defined class with zero or more SWP snippets. If such a class is instantiated, then the engine will first attempt to build XML nodes for all error prototypes (including those from superclasses). If any of those error prototypes creates a non-empty XML document, then this document will be used instead of the ui:prototype.

Error prototypes are often a convenient mechanism to implement user-friendly error handling. For example, assume you have a couple of components that are only visible if the current user has certain privileges. In this case, you can create an abstract SWP class that acts as a superclass of your components. In that superclass, define an ui:errorPrototype that validates the permissions and creates a simple text such as shown below.

    <ui:if ui:condition="{= !ex:currentUserHasReadAccess() }">
        <span>You do not have sufficient privileges</span>
    </ui:if>

In the example above, if the condition is false, then the snippet will be turned into an "empty" XML document, and the system will continue with the default behavior of using the ui:prototype instead.

In some cases, using ui:errorPrototypes is too inefficient, because lots of (duplicate) computations would be needed to check for error conditions, in multiple (error) prototypes. For those cases, SWP provides a built-in control element ui:throw that simply interrupts the execution of the engine and fails with a servlet error, providing a human-readable error message.

4.5 Overriding existing Class Definitions with ui:overrides (Advanced Topic)

It is a good practice to organize and distribute SWP class definitions in libraries so that they can be reused in different places. Such generic libraries can significantly reduce development costs. However, like with any reusable library, developers may want to make small adjustments here or there, for example to insert additional HTML elements. One (naive) approach for that is to make a deep copy of the existing class definitions and/or move them to another namespace and then modify it there. However, this quickly leads to unmanageable code because the new cloned system is out of synch and will no longer benefit from updates to the underlying components.

The property ui:overrides can be used to declare that a given element class should substitute the ui:prototype and ui:errorPrototype values of a given class. In order to override a given element ex:BaseClass, create a subclass ex:SubClass of it and attach the property ui:overrides to it, pointing back to the original ex:BaseClass. Then define a new ui:prototype at ex:SubClass. Whenever the element ex:SubClass is used, the system will from now on use the prototype from the subclass.

4.6 Plug-ins with ui:insertionPoint and ui:insert

User-defined components may declare insertion points that serve as a plug-in mechanism for other components to use.

An example use case is the following. Assume you have a user interface widget with a tool bar and that may contain a variable number of buttons. Subclasses of your widget may want to add custom buttons that are specific to them. You may want to have many of such subclasses, without limiting what could potentially go into the components.

In this example, the base class ex:BaseComponent may define the following prototype:

    <div>
        <table>
            <tr>
                <td>My Component</td>
                <td>
                    <ui:insertionPoint ui:pointId="toolbar" />
                </td>
            </tr>
        </table>
        <span>Some more stuff goes here...</span>
    </div>

A SWP class ex:SubComponent may be declared as a subclass of ex:BaseComponent with the following prototype:

    <ex:BaseComponent arg:... >
        <ui:insert ui:into="toolbar">
            <a href="action1.html">Button1</a>&nbsp;
            <a href="action2.html">Button2</a>
        <ui:insert>
    </ex:BaseComponent>

When ex:SubComponent is instantiated, the result will include the nodes defined in the ui:insert into the ui:insertionPoint:

    <div>
        <table>
            <tr>
                <td>My Component</td>
                <td>
                    <a href="action1.html">Button1</a>&nbsp;
                    <a href="action2.html">Button2</a>
                </td>
            </tr>
        </table>
        <span>Some more stuff goes here...</span>
    </div>

ui:insertionPoint must have a single container element around it - the td in the example above.

As of SWP 1.1 it is no longer necessary to explicitly use ui:insert. Instead you can write the example above as

    <ex:BaseComponent arg:... >
        <div>
            <a href="action1.html">Button1</a>&nbsp;
            <a href="action2.html">Button2</a>
        </div>
    </ex:BaseComponent>

In this shorter form each direct child of the component that declare the insertion point will be inserted into the next available insertion point. If there are more than one extension points, then it will traverse them alphabetically.

Note that there are other mechanisms of creating plug-in behavior. Since SWP views are RDF resources which you can query with SPARQL (using GRAPH ui:graph { ... }), you can store extra metadata in your SWP models to identify those component that shall be used as "plug-ins". A detailed discussion of these design patterns goes beyond the scope of this document.

4.7 Selecting Views with ui:dynamicView (Advanced Topic)

SWP is entirely RDF and SPARQL driven, which means that the structure of SWP declarations itself can be queried at run-time to dynamically select which (HTML) elements to insert into the target document. A typical use case in ontology-driven applications is to have widgets that have different content depending on the type of object to render. For example, a string literal should be displayed using a span while resources ending with .png should be displayed using img. The control element ui:dynamicView allows SWP developers to dynamically select the type of element to insert when the page is being constructed.

In the following example, ui:dynamicView is used to insert a suitable widget for an object, while the function ex:selectWidget gets the most suitable user-defined element for the provided argument.

    <ui:dynamicView ui:class="{= ex:selectWidget(?object) }" arg:object="{= ?object }" />

Assuming that ?object is a resource ending with .png, the SPIN function ex:selectWidget may return ex:ImageViewer. The SWP engine then essentially produces:

    <ex:ImageViewer arg:object="{= ?object }" />

Any additional argument of the ui:dynamicView element will be passed into the new element. If the ui:class argument evaluates to unbound then nothing gets inserted.

4.8 Querying View Metadata with ?thisNode and ?thisParent (Advanced Topic)

Since SWP models themselves are represented in RDF, it is possible to query the document structure itself while the SWP engine is running. Two system variables are available to get pointers into that graph in the current context:

Note that in order to traverse the SWP graph itself, you need to switch to the ui:graph, e.g. using GRAPH ui:graph { ?root ui:child ?thisParent ... } or GRAPH ui:unionGraph { ... }.

 

5 Application Development (Advanced Topic)

SWP is not limited to creating individual pages or renderings, but is also a framework for creating applications that use linked (RDF) data as their core data models. This section covers a range of topics that, taken together, help developers get started with using SWP for the creation of linked data applications consisting of multiple pages.

5.1 The Role of the Server

For the purpose of this discussion, we assume that we have a SWP server (such as TopBraid Live) that is able to handle incoming HTTP requests to return SWP pages (including HTML, SVG and JSON). In many cases, those renderings are attached (and can be derived from) a given Resource. The linkage properties such as ui:instanceView can be used for that purpose. In the case of TopBraid Live, the URL to get an HTML page for owl:Thing would look like the following:

    http://localhost:8083/tbl/uispin?_resource=http%3A%2F%2Fwww.w3.org%2F2002%2F07%2Fowl%23Thing

This particular server uses the following arguments (all optional):

Argument Description
_resource The URI of the resource to render.
_matchIds A comma-separated list of ui:ids to match against, e.g. "summary,label,*".
_base The base URI of the default query graph to operate on.
_view The URI of a specific view to display (instance of ui:Element).
_viewClass The URI or qname of a user-defined view class (subclass of ui:Elements) to display. All other arguments that match the declared arguments of the view class will be passed into the view, e.g. uispin?_viewClass=ex:MyView&name=Test will be comparable to <ex:MyView arg:name="Test" />.
_snippet A boolean to instruct the engine to not wrap the result into a full HTML document (with tags such as html and head).
_format The mime type for the response, e.g. application/json.
_cache If set to true, then the server will cache the result of this request. Subsequent calls to the same URL will return the cached version, significantly boosting response times. Note that changes to the underlying RDF model or SPARQL queries will not be detected automatically, which means that this option should only be used for static content and read-only applications.

In order to fulfill its requests, a SWP server will operate on a collection of SWP files that are registered with it. The server will pre-load all files containing .ui. in their name and combine them into a (virtual) union graph called ui:graph. This graph will be used at execution time to identify which visualizations are available for a given context. The UI graph can also be queried by the SWP documents themselves, e.g. the following query will enumerate all classes that have an instance view attached to them:

    SELECT ?class
    WHERE {
        GRAPH ui:graph {
            ?class ui:instanceView ?view .
        }
    }

See also the built-in SPARQL function ui:param on how to query additional parameters of the servlet call.

In a typical SWP application, generated HTML pages would contain hyperlinks to other pages from the same information system, and the same server. Those links may become quite long, and the syntax may be hard to remember and may not portable between SWP servers. For this reason, SWP provides a built-in control element ui:createLink that generates a URL that can then be turned into a hyperlink, e.g. using href. The following example creates a simple link to a page rendering owl:Thing:

    <ui:createLink ui:resource="owl:Thing">
        <a href="{= ?link }">Thing</a>
    </ui:createLink>

ui:createLink binds a variable called ?link which can then be used in the child nodes of the element. You can use the property ui:varName to specify a different variable name, to avoid potential name clashes.

Most of the servlet arguments from the table in the subsecion above can be specified in similar ways, using the built-in properties ui:snippet, ui:viewClass, ui:format and ui:queryGraph. This makes it possible to let the system do the low-level work of turning any combination of those arguments into a valid URL against the right server.

There is an optional boolean property ui:sendQueryGraph that can be set to true to instruct the engine to propagate the current query graph into the linked page. The effect of this will be that the linked page will start with the provided named graph as its default graph. This is typically used in conjunction with ui:setContext.

The ui:createLink element can take any number of other arguments. All arguments not from the ui: namespace will be passed into the servlet as named argument. For example, arg:firstName="Darwin" will be turned into &firstName=Darwin as part of the link. These additional arguments will be passed into the selected SWP view for execution.

5.3 Dynamic Views with ui:loadable

Many JavaScript-based applications use Ajax callbacks to replace parts of a page when an event happened. For example, clicking on a tree on the left of the page may replace the form on the right. JavaScript libraries such as jQuery support such load operations relatively conveniently - yet doing the right thing is often a difficult undertaking.

The control element ui:loadable can be placed around divisions of a page that shall be re-loadable. The following example illustrates how this works.

    <ui:loadable ui:loadId="form">
        <ui:if ui:condition="{= bound(?subject) }">
            <span>This is the form for {= ui:label(?subject) }</span>
        </ui:if>
    </ui:loadable>

When the page with the snippet above loads first, it will simply contain an empty <div />. The div carries an internal attribute that provides enough information to reload the parts inside of the ui:loadable. It will get the HTML id specified as ui:loadId and also have an attribute uistate with a partial URL for the server callback. This uistate includes the values of all currently bound variables, the context variables and the query graph, as well as a pointer back to the corresponding SWP snippet in the original source.

The SWP language itself does not define a standard JavaScript function to do the actual reloading, but TopQuadrant's evolving SWA library does. This includes a function called swa.load that can be used for the example above as follows:

    <a onClick="swa.load('form', { subject : '<http://example.org/MySubject>' })" ... >

This will make an Ajax request to the server to reload the content of the ui:loadable but this time with the variable ?subject bound to the example subject. The ui:if would then behave differently and insert the nested span.

The element ui:loadable may have its attribute ui:cache="true" to ensure that the request is cached. This is only recommended for read-only snippets.

As of TopBraid 4.2, ui:loadable may have an attribute ui:loadLater="true" to indicate that the loadable shall not be executed in the first round, but be lazy loaded in an Ajax callback as soon as the surrounding page has been finished. This is a convenient way to break up loading of large documents into smaller transactions, giving more instant feedback to the users while the lower sections of a page are still loading. Note that this currently requires the SWA JavaScript library.

5.4 SWP and JavaScript

As a general rule of thumb, you should avoid embedding <script> tags into SWP body elements. Instead, you should store the JavaScript code in a text (*.js) file and import it into the HTML document's head (through ui:headIncludes).

TopBraid 4.2 introduces the function ui:functionCall that makes it easy to interact between SWP HTML code and those externally defined JavaScript functions. For example

    <ui:group let:arg="Hello, World">
        <a onclick="{= ui:functionCall('myapp.function', ?arg) }" ...
    </ui:group>

creates the following output

    <a onclick="myapp.function(&quot;Hello, World&quot;)" ...

This way the resulting SWP code doesn't get caught up with JavaScript details and remains easier to maintain and modular. Furthermore, the separation into different files is more natural if a development team consists of HTML layout and JavaScript experts.

5.5 Creating Ajax Callbacks and JSON

Many Ajax widgets such as tree viewers require a pointer to a URL from which they get JSON or XML to dynamically populate content. The URLs can be created using ui:createLink, and the arguments expected by the Ajax widget can be implemented as named SWP arguments.

The resulting JSON can then be created by a view that does not return HTML but only text nodes. As explained earlier, it is possible to create arbitrary text documents, as long as the root element is ui:group. SWP control structures such as ui:forEach and ui:if can be used in either case, also to produce text nodes only. You can tell the servlet to return JSON by setting the ui:format to application/json when a link URL is created.

SWP 1.1 introduces a library called swon that includes pre-defined element that make it easy to produce JSON from SPARQL Result Sets. Open this file in TopBraid to see the available elements.

Many callbacks may not need to return any result at all, and only do something. SWP widgets may also want to call other servlets such as SPARQLMotion. The ui:createLink element provides a property ui:servlet for that purpose. For example, set it to sparqlmotion to call the TopBraid Live SPARQLMotion handler, and set arg:id to the name of the script to call. All other arguments can be passed into the servlet using the same mechanism.

5.6 Performing Updates with ui:update and ui:transaction

SWP is typically only used to create visualizations. However, application development often also requires updates to some database, for example in response to editing a form. In order to be maximally useful and complete, SWP provides a control element ui:update that may contain SPARQL UPDATE requests.

The syntax of ui:update is illustrated in the example below:

    <ui:update ui:updateQuery="{!
                INSERT {
                	GRAPH &lt;urn:x-var:teamGraph&gt; {
                        ?tag a teamwork:Tag .
                        ?tag rdfs:label ?name .
                        ?tag rdfs:comment ?comment .
                        ?tag sioc:has_creator ?user .
                        ?tag teamwork:manager ?user .
                        ?tag teamwork:status teamwork:Uncommitted .
                        ?tag dcterms:created ?timeStamp .
                    }
                }
                WHERE {
                    BIND (afn:now() AS ?timeStamp) .
                    BIND (smf:userWithName(smf:currentUserName()) AS ?user) .
                    BIND (smf:buildURI(&quot;&lt;urn:x-tags:{?name}&gt;&quot;) AS ?tag) .
                } }"/>

The example above shows that UPDATE queries must be embedded into a SWP document using {! ... }.

UPDATE does not support variables as graph names, e.g. INSERT INTO ?teamGraph would not be valid. However, dynamically determining the target graph is a common requirement. For this reason, SWP provides a "hack" that instructs the engine to dynamically resolve a named graph by looking at current variable bindings. The convention is to use the naming convention urn:x-var:... where ... is replaced with the name of a bound variable.

If database transactions are supported and needed, multiple ui:update elements can be grouped together by a ui:transaction element. This will make sure that all updates are regarded as atomic operation by the engine. Inside of ui:transaction you can use ui:preCondition to evaluate constraints that need to be valid before the updates should happen. This is illustrated in the following example which creates a new instance of a given class with a given uri.

    <-- ?uri is the URI for the new instance, ?type the rdf:type -->
    <ui:transaction ui:message="Adding instance of {= ui:label(?type) }">
        <ui:preCondition ui:errorMessage="{#
                SELECT ?message
                WHERE {
                    FILTER (EXISTS { ?uri ?anyP ?anyO } || EXISTS { ?anyS ?anyP ?uri }) .
                    BIND (fn:concat('The URI ', ?uri, ' is already used' ) AS ?message) .
                }
            }">
            <ui:update ui:updateQuery="{!
                    INSERT {
                        ?uri a ?type .
                    }
                    WHERE {
                    }
                }" />
        </ui:preCondition>
    </ui:transaction>

5.7 Creating Temporary Triples with ui:tempGraph

It is sometimes necessary to keep track of status changes while a SWP document is being created. For example, assume you want to recursively walk through an RDF tree structure and need to keep track of which nodes have already been visited. SWP provides a dedicated named graph ui:tempGraph that can be used at execution time to write and query "temporary" RDF triples. The graph ui:tempGraph is local to a SWP engine execution, i.e. it starts empty and will be completely wiped out when the page rendering has been completed. The following example saves a temporary triple:

    <ui:update ui:updateQuery="{!
        INSERT {
            GRAPH ui:tempGraph {
                ?node ex:visited true .
            }
        } 
        WHERE {
        } }"/>

Inside of the same request, you can later query those temporary triples using

    <ui:if ui:condition="{= spl:objectInGraph(?node, ex:visited, ui:tempGraph) }">...

5.8 Generating Arbitrary XML with ui:parse

Some RDF models contain XML mark-up, e.g. stored in strings or XML literals. In order to insert those "raw" snippets into a SWP document, the control element ui:parse can be used. This takes a string and attempts to parse it into valid XML document with a single root element.

The following example illustrates this, and also introduces a common problem in generating HTML pages from ontologies. Assume that a given resource ?this has an rdfs:comment consisting of multiple rows. TopBraid has a built-in function html:encodeBRs that takes those comments and replaces native line breaks into proper HTML line breaks with <br /> elements. However, the result of this function is not an XML document snippet but another string. That string can be inserted into the target document using ui:parse as shown below:

    <ui:group let:comment="{= spl:object(?this, rdfs:comment) }">
        <ui:parse ui:str="{= html:encodeBRs(?comment) }"/>
    </ui:group>

5.9 Using Stylesheets

It is possible (and recommended) to use Cascading Style Sheets (CSSs) for defining the layout of SWP documents.

When a UI element is rendered into an HTML page, then the engine will check for a CSS file ending with .css at the location of the SWP document's base URI. For example, the CSS file of the namespace http://example.org/myproject/myrdf would be expected at http://example.org/myproject/myrdf.css. The SWP engine will automatically include any such stylesheet into the resulting HTML document.

Individual styles of any HTML element can be set using the normal style attribute, with semicolon-separated name/value pairs. In addition to that, the SWP HTML vocabulary defines many RDF properties in its css namespace. If present, the values of those style properties will be concatenated into a single style attribute. This is illustrated in the following example:

    <div css:margin-left="16px" />

This will be rendered into the following HTML:

    <div style="margin-left:16px" />

5.10 Scalable Vector Graphics (SVG)

The W3C's Scalable Vector Graphics (SVG) is becoming an increasingly popular graphical language. SVG is being natively supported by most web browsers (except for the outdated version of IE that is bundled as internal web browser of Eclipse on Windows). With its SVG support, SWP can be used to generate SVG documents such as box-and-lines diagrams, statistical charts and animations from RDF data.

In order to use SVG with SWP, you need to import the SWP SVG vocabulary from http://uispin.org/svg. This schema defines classes for all SVG Tiny 1.2 elements and properties for all SVG attributes and styles.

The following example ui:instanceView can be used to display any RDF resource that has an rdfs:label as an oval with a label inside it. Note that uppercase names are needed for the SVG classes, e.g. svg:Ellipse.

    <svg:G>
        <svg:Ellipse svg:cx="100" svg:cy="48" svg:rx="60" svg:ry="26"
            css:fill="yellow" css:stroke="black"/>
        <svg:Text svg:x="70" svg:y="50">{= ui:label(?this) }</svg:Text>
    </svg:G>
Generated SVG Source Screen Rendering
<svg:svg
        xmlns:svg="https://www.w3.org/2000/svg"
        xmlns:xlink="https://www.w3.org/1999/xlink">
    <svg:g>
        <svg:ellipse cx="100" cy="48" rx="60" ry="26"
            fill="yellow" stroke="black"/>
        <svg:text x="70" y="50">Statement</svg:text>
    </svg:g>
</svg:svg>

 

6 SWP Document Syntax

SWP attempts to link the worlds of user interface development (e.g. in HTML) with RDF-based data modeling. Bridging the various languages in those areas is not always easy, and some people may prefer to stick to existing infrastructure and tools to maintain their UI files. For this reason, SWP offers two mechanisms for representing SWP snippets: either as text files or as RDF structures. Both are explained in the following subsections.

6.1 Snippets from Text Files

The starting point of any SWP application is the RDF model that holds the view references. Properties such as ui:instanceView and ui:prototype may be used to link concepts with the XML structures of views. Any of those properties may actually point to an external text file that contains the XML code in a format that is easy to edit with conventional tools.

In order to link to an external file, the file needs to be stored on the same (server or file) location as the SWP file. For example, assume you have a file snippet.uispin and an RDF model containing SWP definitions with the base URI http://example.org/models/mymodel. The .uispin file needs to be placed into the same directory as the model, and the reference to it (e.g. using ui:instanceView) needs to use the URI http://example.org/models/snippet.uispin as a URI resource. If a local copy of that file is present in the same folder as the RDF file, then editing tools like TopBraid Composer will use the local copy instead of trying to resolve that URL on the web.

6.2 Snippets as RDF Structures

SWP not only defines properties that can be used to link RDF-based data models with visualizations, but also includes its own RDF-based data model for representing the visualizations themselves. The basic idea is that any XML document can be represented by RDF (blank) nodes and RDF properties. XML elements are mapped to instances of classes, and the XML attributes become property values. As shown in the class diagram below, SWP utilizes a small collection of classes for representing the various kinds of XML nodes.

The details of this internal representation are usually not relevant for end users. SWP comes with default RDF vocabularies for HTML and SVG, but any other XML vocabulary can be used as well.

The key benefit is that this approach makes it possible to store SWP snippets directly together with the RDF model that it renders. Often those triples will live in a separate graph and will be stored in a file ending with .ui.* to keep model and view triples cleanly separated. But with everything in RDF, it becomes possible to track and update dependencies between the SWP snippets and the model: if a resource is renamed, then an editing tool can easily also rename all references to that resource in the SWP snippets.

 

Appendix A: SWP Functions

Any SWP engine must provide the following SPARQL functions.

A.1 ui:label

It is often desirable to render RDF resources by human-readable labels instead of their qnames or even URIs. The function ui:label can be used to get such a label in an efficient way. Implementations can chose what to return, but as a general policy the rdfs:label (or sub-property thereof) should be used. This is more flexible than a direct triple match against rdfs:label because the function may consider the current context, such as the natural language of the requesting client.

Implementations may chose to optimize this function with native data structures because it will be used frequently.

A.2 ui:arg

The magic property (property function) ui:arg can be used to query the provided arguments of a SWP element at execution time. This provides a powerful introspection mechanism for building generic components that take a dynamic number of arguments.

In the following example, assume that you have a user-defined SWP class ex:AjaxRequest that can be used to create server callbacks with an arbitrary number of arguments. An instance might look as follows:

    <ex:AjaxRequest arg:firstName="John" arg:lastName="Doe" />

The class ex:AjaxRequest may have the following prototype:

    <script>
    ...
        <ui:forEach ui:resultSet="{#
                SELECT ?param value
                WHERE {
                    ?property ui:arg ?value .
                    LET (?param := afn:localname(?property)) .
                } }">
            ... generate JavaScript...
        </ui:forEach>
    ...
    </script>

In this prototype, the result variables of the loop will be bound to "firstName" / "John", and "lastName / "Doe". It is common to combine the ui:arg function with the names graph ui:graph to query for additional properties of the argument predicates, such as their spl:valueType and spl:defaultValue.

A.3 ui:systemPreference

The SPIN function ui:systemPreference can be used to access system settings of the SWP engine. In some cases (such as to retrieve Google API Keys), components need to adapt to the local environment and can not create themselves by just looking at the models. The function takes a key (string) and returns the value of the preference (if set).

A.4 ui:uniqueId

The SPIN function ui:uniqueId creates a unique identifier string that can be then be assigned to components, e.g. as HTML ids. The function takes no arguments and returns a different string with each invocation.

A.5 ui:encodeNode

The function ui:encodeNode renders a given RDF node to a string, using the following conventions:

The sibling function ui:decodeNode can be used for the reverse direction.

A.6 ui:decodeNode

The function ui:decodeNode creates an RDF node from a string created by ui:encodeNode earlier. This pair of functions is particularly useful in representing resources across client-server interactions

A.7 ui:encodeURL

The function ui:encodeURL encodes a given string so that it can be used as part of a URL, e.g. for Ajax callbacks.

A.8 ui:escapeJSON

The function ui:escapeJSON converts a given string to a JSON-friendly string that can be sent across the wire. In particular, this replaces ' with \' so that string literals can be placed between matching ' braces.

A.9 ui:graphWithImports

The function ui:graphWithImports casts a given named graph resource to an encoded resource that instructs the engine to also include the owl:imports closure (and the system graph). In TopBraid, this adds a '+' as in <http://my.com/graph+>. Returns the original graph unchanged if it already has the additional encoding.

A.10 ui:graphWithoutImports

The function ui:graphWithoutImports does the opposite as ui:graphWithImports.

A.11 ui:concat

The function ui:concat is almost identical to the SPARQL 1.1 built-in CONCAT (and its alias fn:concat). The important distinction through is that the latter fail if one of the arguments are unbound. For example if you call CONCAT("Hello, ", ?person) then the function will output nothing if ?person is unbound. ui:concat will still produce what it can and output Hello even if ?person is unbound.

ui:concat is also used internally by the SWP engine if you are using an inline expression in an attribute value, e.g. class="my-class {= ?other}" will be turned into a call to ui:concat under the hood. You usually won't have to care about this because the SWP parser does this automatically.

A.12 ui:currentQueryGraph

The function ui:currentQueryGraph returns the URI resource for the currently active query graph. This is either set using ui:setContext or via the _base argument of the servlet.

A.13 ui:param

The function ui:param can be used to query any additional parameter that has been passed into the SWP servlet. For example, if the servlet has been called using uispin?_resource=owl:Thing&name=John then you can use ui:param('name') to get the value "John". By default this function will create string literals. If you want to automatically cast into any other datatype, then you can pass this in as second argument, e.g. ui:param('date', xsd:date). If the value is a URI, then you can specify any rdfs:Class as second argument, to get a proper resource. In the latter case, the function will remove '<' and '>' around the URI.

A.14 ui:contextValue

The function ui:contextValue provides access to the values of context values that were previously set using ui:setContext. The only argument of this function is the name of the variable to get.

A.15 ui:functionCall

The function ui:functionCall is the recommended mechanism for creating JavaScript function calls. In a typical use case, this function is the only value of an event listener, e.g. the onclick attribute of a hyperlink. The first argument is the name of the function to call, while the other arguments are inserted as arguments to the function. ui:functionCall makes sure that characters are correctly escaped, making SWP code much easier to read.

See above for examples.

 

Appendix B: Reference

The URL of the SWP Core Schema is http://uispin.org/ui

The URL of the (tiny) SWP Link Schema is http://uispin.org/uilink

The URL of the SWP CSS Vocabulary is http://uispin.org/css

The URL of the SWP HTML Vocabulary is http://uispin.org/html

The URL of the SWP SVG Vocabulary is http://uispin.org/svg

 

A version of this article has been translated to Serbo-Croatian language by Anja Skrba from Webhostinggeeks.com.