About this Manual

This manual is for Web developers who want to develop linked data applications using Callimachus. Those new to Callimachus should start by doing the Callimachus Meeting Notes Tutorial.

Callimachus is a highly scalable platform for creating and running data-driven websites. 3 Round Stones offers commercial support and private virtual cloud hosting for enterprises running Callimachus.

If you have not installed Callimachus yet, please follow the installation instructions in Getting Started with Callimachus.

Part I. Introducing Callimachus

Introduction

This part provides you with an introduction to Callimachus, what it is and why you would want to use it.

A. Where the name Callimachus came from

Who he was

This project was named after Callimachus the father of Bibliography who worked at the ancient Library of Alexandria.

Callimachus lived during 305-240 BCE.

Illustration: Great Library of Alexandria

Callimachus

  • could not categorize his own work by using Aristotle's hierarchical classification system (a problem now known as "Callimachus’ Quandary"), and therefore

  • was the first person to define the use case for Linked Data!


B. Callimachus features

Allows new data to be easily integrated with existing data

Callimachus makes data easy to create, view, and update. Integrating new data with existing data is much easier to accomplish compared to using relational databases.

Displays linked data in visually appealing web pages

A new user can easily import linked data and rapidly transform it into attractive web pages and editable forms.

Allows applications to be changed while in production

Callimachus queues and locks the data store to allow uninterrupted service while changes are made to application


C. Who is using Callimachus

Here is a recent sample of organizations that have adopted Callimachus by sector. For competive reasons some names are not mentioned.

Government

Callimachus will soon host all the data published as Linked Open Data for the US Environmental Protection Agency (EPA). The system is currently in the final phases of a security review, and is due to launch in 2013. It combines US EPA data on 1.3 million facilities regulated by the US EPA. This includes data ranging from dry cleaning operations to nuclear power plants, and reports on toxic chemicals emitted over the last 25 years.  It cross links to chemical substance databases, Open Street Maps, DBpedia content and much more.

Healthcare

Callimachus is used by Sentara, a regional healthcare delivery and payer organization that insures 400,000 lives. Sentara is developing a Web and mobile application called 'Weather Health'. The application combines data from the US National Library of Medicine, National Oceanic and Atmospheric Agency (NOAA), US EPA and DBpedia to better respond to chronic conditions, and reduce costly emergency visits. 

The Weather Health is project considered to be a "national good" by Sentara.  They dedicated the application to improving healthcare outcomes and reducing the cost of healthcare delivery in the US by empowering patients with timely, relevant information. 

Pharmaceuticals

Callimachus is being used as a knowledge management platform by a major pharmaceutical company to combine enterprise data with open data from the Web.  This KM solution was developed in 2012 and is slated to go into phase 1 production in 2013.

Publishing

Callimachus is being used to power an agile publishing workflow for an international business publisher. The system combines content from company document management stores with open Web content and a variety of enterprise systems.  The system was developed in 2012 and is anticipated to be used throughout North America by up to 400 editors in 2013.

Research 

Researchers in Europe, Brazil and the United States are using Callimachus to standardize metadata and combine data from different systems.  In one example, researchers in Finland created a "virtual machine laboratory" to track mechanical parts in industrial assembly lines.  Callimachus was used to host information about each part, including how parts related to other parts.


D. What developers are saying about Callimachus

Actually makes it easy to create a linked data application

“Tools I've been using include Protogé, Google Refine and Callimachus. It is the only development tool I have found that actually makes it easy to create a linked data application.”

All you need is a browser

“The user interface is consistent and all you need is a browser.”

RESTful from the ground up

“Callimachus is RESTful from the ground up.”

Confidence in the deep knowledge of the development team

“I have confidence in the expertise and deep knowledge of the development team.”

Handles change history well

“Wiki Systems don't handle structured content well nor promulgate change well. Callimachus focuses on structured content and handles change history well.”

Keeps unnecessary details hidden

"Callimachus keeps lots of the details hidden that I don't want or need to see. It allows me to see the ontology on the level that I need to."

Allows ontologists to work with UI experts

"There is a difference between the ontologists & UI guys [who work in HTML/CSS]. Using Callimachus, the UI guys don't have to become ontology experts and the ontologists don't need to look under the hood at the UI code."

Absolutely necessary glue for Web apps

"It provided easy to use, absolutely necessary "glue" for producing data drive Web apps."

Enables a focus on business direction not the UI

"With Callimachus, I'm getting that shorter path to the technical resolution for that I'm trying to deliver. Allows me to focus on the business direction and not the UI"


E. Developer prerequisites

Web standards

Callimachus developers should be familiar with current Web standards, especially HTML version 5, CSS version 3 and JavaScript.

As well some knowledge of transforming data using XML technologies is helpful, especially XSLT and the recent XML pipeline language, XProc.

Linked data standards

Callimachus developers should also be familiar (or prepared to become familiar) with the standard for linked data - the Resource Description Framework (RDF).  In particular, they need to learn how to use RDFa as a means of annotating HTML tags with data via the addition of attributes.

Reference documents

The developer should refer to the following documents as required:

HTML 5

CSS 3

RDF

SPARQL

XSL

Xproc


Part II. Background

Overview

This part covers background concepts that have specific meaning in Callimachus, and are essential to know about when developing a Callimachus application.

Chapter 1. A Short Introduction to RDF

In this chapter we briefly describe what RDF is, what its advantages are and how it works in Callimachus.

1.1. About RDF

1.1.1. Introduction

The Resource Description Framework (RDF) is a W3C standard for modelling linked data. The purpose of linked data is to enable data from different sources to be easily and meaningfully linked together, thereby making it more useful.

1.1.2. Triples

RDF represents data as simple sentences called “triples”. A triple is made up of a subject, predicate and object. 

1.1.3. Car ownership modeled as triples

A triple can be visualized as a graph, where ovals represent the subject or object of the sentence, while arrows represent the predicates (i.e. the relationships).

1.2. Advantages of RDF over relational databases

1.2.1. Expanding your data horizons

With RDF one resource can be combined with any other resource by making an assertion about the relationship (a triple). This makes it easy to expand a database that has been implemented using RDF.

1.2.2. Advantages of RDF over relational databases
External data Inferencing Schema New attributes Query structure
Relational Database Merge schema Not supported Required Requires migration Optimized for updates
RDF Database Identify redundencies Optional Optional Added on the fly Faster joins

1.3. RDF resource

1.3.1. Definition

An RDF resource is any person, place, event, object (i.e. anything) that can be uniquely identified by using a Uniform Resource Identifier (URI). 

1.3.2. Examples

Data concerning:

  1. A store

  2. An item in a store

  3. The price of an item in a store

  4. Someone’s opinion about the price of an item in a store

  5. and so on...

In Callimachus the domain, folder path plus resource name combine to form the absolute identifier of the resource.

1.3.3. Adding meaning by using vocabularies

When naming resources developers are encouraged to use terms from commonly used controlled vocabularies or "ontologies".  Controlled vocabularies make it possible to construct queries that relate otherwise disparate datasets.

1.3.4. Commonly used vocabularies

Below are some widely used vocabularies for naming and describing resources.

Vocabulary  Description Searchable QNames
Dublin Core Fifteen properties frequently used to describe resources, similar to the type of information found on a library card.
Friend of a Friend (FOAF) A vocabulary for linking people and information about them.
Freebase A repository of open data containing almost 23 million entities.
GoodRelations A vocabulary for describing products and services.
GeoNames A vocabulary with the official geographical names for all countries and containing over eight million placenames.
Open Graph Protocol A vocabulary for describing "rich objects" in a Facebook social graph.
RDF Schema (RDFS) A vocabulary for structuring RDF resources.
Semantically-Interlinked Online Communities (SIOC) A vocabulary for linking online communities.
Simple Knowledge Organization System (SKOS) A vocabulary for organizing knowledge contained in thesauri, classification schemes, subject heading lists and taxonomies.
Vcard A vocabulary for the type of information that might be found on a business card.

Note: QName stands for "qualified name" and enables the abbreviation of URIs. The QNames shown here are used to lookup resources  in Callimachus.

1.4. RDFa

1.4.1. What it is

RDFa is a W3C standard used to embed RDF data directly inside web pages by using attributes - hence the 'a' in RDFa. While RDFa is similar to microdata and microformats, it offers important advantages such as being able to use multiple vocabularies in the same page.

Source: Executive Briefing on Linked Data

Like a credit card, web pages that use RDFa have both a human-readable as well as a machine-readable side. 

1.4.2. RDFa attributes

RDFa uses the attributes shown below to embed meaningful data in the page by forming triple statements.

Subject or resource Predicate Literal values
  • @about

  • @resource

  • @href

  • @src

  • @property

  • @rel

  • @rev

  • @content

  • @datatype

  • @xml:lang

  • text()

1.4.3. How Callimachus uses RDFa attributes

Callimachus extends the RDFa syntax by allowing variables as well as URIs to be used in attributes. This allows data to be updated directly in web pages, as well as displaying updated data as it changes.

Callimachus further extends the RDFa syntax by introducing expressions that allow values to be substituted within attribute values or within text nodes.

The table below describes the purpose of each RDFa attribute and how it is represented in Callimachus.

Attribute

Purpose

Representation

@about and @src

Specifies the resource that the metadata is about.

Variable or URI

@rel and @rev

Specifies a relationship or a reverse-relationship with another resource (sometimes called object property).

Reserved keyword or CURIE

@href and @resource

  1. Specifies the partner resource of rev or rel, or

  2. Specifies the resource the metadata is about for property (when rev or rel is not present).

Variable or URI

@property

 Specifies a CURIE property for the content of an element (sometimes called datatype property).

CURIE

@content

An optional attribute that overrides the content of the element when using the property attribute.

A plain literal (string)

@datatype

An optional attribute that specifies the datatype of text specified for use with the property attribute.

@typeof

An optional attribute that specifies the RDF type(s) of the subject.

Note: Callimachus converts the attributes into graph patterns. Blank nodes and empty property contents are treated as wildcards. Graph patterns with wildcards or variables partners are optionally joined in the result.


Chapter 2. Callimachus User Interface

This describes the main features of the Callimachus user interface.

2.1. Main menu

2.1.1. Description

The main menu is represented as a small icon beside the Look-up box, and provides system-level functions when clicked.

Screenshot: main menu

Menu item Function
Home folder Brings you to the root folder. From the root folder you can navigate and modify the site.
Recent changes Displays recent changes to the site.
About Callimachus Takes you to the Callimachus project home.
Getting started Takes you to the Callimachus Getting Started document.
Send feedback Allows you to send feedback using Google Groups.
Help Page sensitive help links, if applicable (opens in a new browser).
Other links Other pages specific links may also appear.
What links here Displays other resources that are linked to the current one.
Related changes Displays changes related to the current resource.
Permissions Displays and allows permissions to the current resource to be changed.
Introspect resource Inspect the components that comprise a resource.
Print this page Print the current page.
User name Takes you to your user page where you can change your password or email address.
Sign out Signs you out of Callimachus.

2.2. Create menu

2.2.1. Description

The create menu is represented as a red button with the label Create when navigating folders. When pressed it provides a submenu of resources that are used to build Callimachus applications (see Callimachus Resources).

Screenshot: Create menu

2.3. Resource browser

2.3.1. Description

The resource browser provides a convenient way for users to view, modify, discuss and find out more about an RDF resource or a Callimachus  resource. It consists of the five tabs shown below. Access to tabs depends on user permissions.

Screenshot: The Resource Browser

2.4. View tab

2.4.1. Description

The resource browser View tab shows the resource rendered for viewing according to its type.

Screenshot: View tab for a DocBook article

Note: For the View tab to be active for an RDF resource, it must be of a class that has a view template associated with it.

2.5. Edit tab

2.5.1. Description

The resource browser Edit tab allows the resource to be edited depending on its type.

Screenshot: Edit tab showing a DocBook article

Note: For the Edit tab to be active for an RDF resource, it must be of a class that has a edit template associated with it.

2.6. Discussion tab

2.6.1. Description

The resource browser Discussion tab allows changes to a resource to be discussed.

Screenshot: Discussion tab allowing discussion about a DocBook article

2.7. Describe tab

2.7.1. Description

All resources in Callimachus are stored as OWL/RDF, and the resource browser Describe tab shows the RDF that describes the current resource.

Screenshot: Describe tab showing the triples for the main article

2.8. History tab

2.8.1. Description

The resource browser History tab shows in chronological order the changes made to a resource.

Screenshot: History tab showing the changes to a DocBook article


Chapter 3. Callimachus Resources

Callimachus resources are used to build Callimachus applications. A Callimachus resource is created by using the create menu from a folder. When naming a Callimachus resource, these naming conventions should be followed.

Access to a resource may be controlled by using the Permissions menu item.

3.1. File

Callimachus supports some binary and text files, ZIP files and Callimachus Archive File (CAR) files. 

3.1.1. Binary and Text Files

Binary and text files are used to store many of the types of Callimachus resources and are the building blocks for all Callimachus applications. See Appendix B. BLOB Resource Types for a complete list of file types you can use in Callimachus.

Adding, deleting or renaming a file

To add a file

  1. Click the upload file button, next to the create menu, from the folder you wish to store the file in, then
  2. Using the file upload dialogue upload the file from your computer

To delete a file

  • using the resource browser navigate to the folder with the file you want to delete, then

  • open the file, click on the edit tab and press the Delete button

To rename a file (not all types of files can be renamed)

  • using the resource browser navigate to the folder with the file you want to rename

  • click on the edit tab and press the Save as... button

  • save the file with its new name

  • delete the older file

3.1.2. ZIP Files

ZIP files can be used to import files in bulk. Files from a local filesystem can be archived together and imported into a folder at once. However, the entire folder's content must be imported at once.

3.1.3. Callimachus Archive Files

A Callimachus Archive File (CAR) file has the .car extension and contains the contents of a folder at some point in time. CAR files are used to backup and restore Callimachus applications, as well as to transfer large amounts of RDF data between systems.

3.2. Folder

3.2.1. Description

A Callimachus folder is a way to group files/resources.

A folder may contain either

  • File resources,
  • Folder resources, or
  • RDF resources
3.2.2. Creating a new folder

To create a folder, select 'Folder' using the create menu from the folder you wish to create the new folder in. You will be presented with the following dialogue:

Screenshot: New Folder dialogue

3.2.3. Deleting the contents of a folder

To delete the contents of a folder

  • Click on the Edit tab
  • Use the Delete button to delete the folder and its contents
3.2.4. Granting folder permissions

To grant permissions to a folder, navigate to the desired folder and select Permissions from the main menu.

Lookup and add User Group(s) to the appropriate Role to assign permissions.

Role Permissions
Reader view a read-only copy of the resource
Subscriber view, see the history, and discuss the resource
Editor make changes using the edit tab and create new resources in this folder
Administator view, create and modify using any available operation
3.2.5. Exporting and importing the contents of a folder

Callimachus compresses and stores the contents of folders in CAR files. To export or import the contents of a folder, navigate to the folder and open the main menu.

If you click the Export folder contents entry, you will be prompted for a location on your computer to save the CAR file. If you click Import folder contents you will be prompted to specifiy the CAR file you wish to import.

Note: The imported files will overwrite the current files.

3.3. Article

3.3.1. Definition

A Callimachus article is a text file that is structured using the DocBook XML markup language, a popular and open standard for marking up technical documentation. Articles may be included in one or more Callimachus books.

3.3.2. Purpose

Articles are used to create documentation in Callimachus.

3.3.3. Creating a new article

To create an article, select Article using the create menu from the folder you wish to store the article in. You will be presented with the following:

Screenshot: New article

3.3.4. Editor

Callimachus uses the CKEditor to edit books and articles. To learn more about how to use the functions of the CKEditor that Callimachus exposes, please take a look at CKEditor's documentation.

3.4. Book

A Callimachus book is a DocBook document.

Books organize articles into a desired sequence and hierarchy and may be divided into parts and chapters.

To create a book, select Book using the create menu from the folder you wish to store the book in. You will be presented with the following initial DocBook code:


<?xml version="1.0" encoding="UTF-8" ?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" 
      xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0">

<title>Untitled Book</title>

</book>

Screenshot: Initial code for a book

3.4.1. Including an article

Use the xi:include tag to include an article by specifying its relative path.


<xi:include href="articles/who-is-using-callimachus.docbook" />

The pragma ?docbook will respond with the transclude all articles and return the combined docbook file.

3.4.2. Editing an included article

To edit an article when viewing a book

  • click on the  symbol which appears immediately after the article's title
  • press the edit tab to edit the article
3.4.3. Linking to a point in a book

When linking to a particular point in a book, insert an archor tag to set the destination for the link. The link target can be a named anchor within the article, a hash identifier elsewhere in the book, or the view page of an included article. Other links will point to the coresponding resources.

3.4.4. Adding a part

Use the following DocBook code to add a part to the book. Insert the code directly after the book's title tag for the first part.


    <part>
        <title>Topic</title>
        <preface>
            <title>Introduction</title>
            <para>
                Text goes here.
            </para>
            <para>Topics</para>
        </preface>
        <xi:include href="articles/new-topic.docbook" />
    </part>
3.4.5. Adding a chapter

Use the following DocBook code to add a chapter to a part. Insert the code directly after the part's <title> tag for the first chapter.


        <chapter>
            <title>Chapter title goes here</title>
            <info>
                <abstract>
                    <para>Overview goes here.</para>
                    <para>Topics</para>
                </abstract>
            </info>
            <xi:include href="articles/new-topic.docbook" />
        </chapter>

3.5. Class

3.5.1. Definition

A class describes a set of resources that share some common characteristics. In Callimachus a class is a set of RDF resources that use the same templates. Callimachus templates dynamically merge RDF data within XHTML5 pages, allowing users to create, view or edit resources from their browsers. Super classes may be used to inherit or override page templates.

3.5.2. Creating a new class

To create a class, select Class using the create menu from the folder you wish to store the class in. You will be presented with the following dialogue:

Screenshot: New class dialogue

3.5.3. Classes and RDF resource types

When you create a Callimachus class you are also creating a RDF resource type.

3.5.4. Controlling who can create resources

Use the Authors link to specify the User Groups that are allowed to create resources for the class.

3.5.5. Looking up resources

Icons may be used to look up resources of the class. To add an icon, click the Icon link to open a file upload dialogue.

3.5.6. Using external classes

An external OWL class can be associated with a Callimachus class to apply templates. Use the Explore OWL classes in this graph menu entry (in the main menu of a graph) to view an imported OWL vocabulary, then follow the instructions to create an equivalent Callimachus class.

3.6. Concept

Callimachus concepts are used to categorize objects or events.  A concept consists of one primary label which is used to construct its URI, as well as any number of alternate labels. These alternate labels are used to assist in concept lookup.

Concepts are primary used to to clarify the usage and meaning of something. In an application they are used to populate controls such as dropdowns, checkboxes or radio buttons.

Note: A concept is a common attribute of an object, not a set of objects, which would instead be modeled as a class.

To create a concept, select Concept using the create menu from the folder you wish to store the concept in. You will be presented with a form.

3.6.1. Example

The set of US state names or a list of the Canadian provinces are examples of concepts.

3.7. Graph document

3.7.1. Definition

A graph is a set of RDF triples. A Callimachus graph document is an RDF document encoded as a Turtle file.

3.7.2. Purpose

Graph documents are used to add RDF data to the Callimachus RDF database.

3.7.3. Creating a graph document

To create a graph document, select Graph document using the create menu from the folder you wish to store the graph document in. You will be presented with the following initial Turtle code:

@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rif: <http://www.w3.org/2007/rif#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix skosxl: <http://www.w3.org/2008/05/skos-xl#> .
@prefix cc: <http://creativecommons.org/ns#> .
@prefix wdr: <http://www.w3.org/2007/05/powder#> .
@prefix void: <http://rdfs.org/ns/void#> .
@prefix msg: <http://www.openrdf.org/rdf/2011/messaging#> .
@prefix calli: <http://callimachusproject.org/rdf/2009/framework#> .
@prefix : <#> .
3.7.4. Sample Turtle file

Here is a sample turtle file:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix ex: <http://example.org/stuff/1.0/> .

<http://www.w3.org/TR/rdf-syntax-grammar>
  dc:title "RDF/XML Syntax Specification (Revised)" ;
  ex:editor [
    ex:fullname "Dave Beckett";
    ex:homePage <http://purl.org/net/dajobe/>
  ] .
3.7.5. Turtle syntax

Angle brackets are used to identify relative URLs, while colons outside of angle brackets identify a compact URI or a CURIE. The prefix before the colon is mapped to a namespace at the top and prepended to the remaining part after the colon. A comma separates multiple objects; a semicolon separates multiple relationships to to same subject; and a period marks the end of a subject.

For more information about the Turtle syntax see Turtle syntax for RDF.

3.8. Named query

3.8.1. Definition

A named query is a SPARQL SELECT query that may be created and edited directly in Callimachus.

3.8.2. Purpose

Named queries provide “result sets” or answers to questions asked using the SPARQL Query Language. The result sets can be visualized as pie charts, line charts, annotations on Google maps and so on.

3.8.3. Creating named queries

To create a named query, select Named query using the create menu from the folder you wish to store the named query in. You will be presented with the following initial code:

#
# @Cache-Control:
# @view
#
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT * {
}

See Using Named Queries for more details.

3.8.4. Example Named Query

Here is an example of a named query that shows pollution levels over time.

    PREFIX owl: <http://www.w3.org/2002/07/owl#>
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
    PREFIX tri: <http://usepa.3roundstones.net/id/us/fed/agency/epa/tri/schema/>
    PREFIX : <#>

    SELECT DISTINCT ?year ?pounds
    WHERE {
    ?tri_facility owl:sameAs <http://usepa.3roundstones.net/facilities/110000484039>
    ; tri:has_report ?report .

    ?report tri:reports_release_of ?chem
    ; tri:reporting_year ?year
    ; tri:released_to ?location .

    ?chem skos:prefLabel “$chemical” .

    ?location tri:amount_in_pounds ?pounds
    ; tri:environmental_medium <http://usepa.3roundstones.net/id/us/fed/agency/epa/tri/environmental_medium/AIR_STACK> .

    } order by ?year

Here is the result set displayed as a graph.

Source: A Real-World Linked Open Data Story

3.9. Page

3.9.1. Definition

A Callimachus Page is an XHTML5 compliant web page.

3.9.2. Purpose

Pages are used to store hypertext that may be used stand alone or as a template for an RDF resource.

3.9.3. Creating a new page

To create a named page, select Page using the create menu from the folder you wish to store the new page in. You will be presented with the following XHTML 5 code:

<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/callimachus/template.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Title Here</title>
    <link rel="edit-form" href="?edit" />
    <link rel="comments" href="?discussion" />
    <link rel="version-history" href="?history" />
</head>
<body>
    <h1>Title Here</h1>
</body>
</html>

Pages are used to create Callimachus Templates which are in turn associated with Callimachus Classes.

3.10. Pipeline

3.10.1. Definition

A Callimachus pipeline performs a sequence of operations on specified XML documents, such as transforming them into RDF in order to load data from a remote source. Callimachus supports XProc pipeline documents and uses the Calabash XProc implementation. 

3.10.2. Creating Pipelines

To create a pipeline, select Pipeline using the create menu from the folder you wish to store the pipeline in. You will be presented with the following initial code:

<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline version="1.0"
        xmlns:p="http://www.w3.org/ns/xproc"
        xmlns:c="http://www.w3.org/ns/xproc-step"
        xmlns:l="http://xproc.org/library">

<p:identity />

</p:pipeline>
3.10.3. Invoking pipelines

Pipelines are invoked by HTTP GET and POST requests, using the URL as the request URL with results in the query component.

Result URL example

http://example.com/my-pipeline.xpl?results

Additional key / value pairs are used in the query component are passed as options into the pipeline.

HTTP GET request

Sending an HTTP GET request to the result URL will trigger an instantiation of the pipeline, without providing an input document for the source port. The pipeline would have to take care of that by either

  • Embedding the input document into the pipeline, or
  • Requesting it using the p:http-request step
Example: Invoking a pipeline using HTTP GET
<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline 
    xmlns:t="http://xproc.org/ns/testsuite" 
    xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0" 
    name="pipeline">
    <p:load href="http://example.com/document.xml" />
    <p:xslt>
        <p:input port="stylesheet">
            <p:inline>
                <xsl:stylesheet version="1.0">
                    <xsl:output method="xml" indent="yes" />
                    <xsl:template match="/">
                        <Info elementNo="{count(/Elements/Element)}"/>
                    </xsl:template>
                </xsl:stylesheet>            
            </p:inline>      
        </p:input>
    </p:xslt>  
</p:pipeline>

Assuming an HTTP GET request to http://example.com/document.xml returns: 

<?xml version="1.0" encoding="UTF-8" ?>
<Elements>
  <Element />
  <Element />
</Elements>

then, an HTTP GET request to the pipeline will result in:

<?xml version="1.0" encoding="UTF-8" ?>
<Info elementNo="2"/>

Note: The URL used by the p:load step can identify a Callimachus web resource (an XML document), facilitating the use of Callimachus web resources as XProc pipelines and inputs to such pipelines.

HTTP POST request

Sending an HTTP POST request to the result URL will trigger an instantiation of the pipeline, passing the request body as an input document for the source port.

3.10.4. Pipeline Parameters

Any parameters appended to the result URL, as additional query components, will be passed as options name/(string) value pairs.

So a POST request to:

http://example.com/my-pipeline.xpl?result&foo=bar 

to the following pipeline:

<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:p="http://www.w3.org/ns/xproc"
        version="1.0" 
        name="pipeline">
    <p:option name="foo" required="true" />
    <p:xslt>
        <p:with-param name="foo" select="$foo" />
        <p:input port="stylesheet">
            <p:inline>
                <xsl:stylesheet version="1.0">
                    <xsl:output method="xml" indent="yes" />
                    <xsl:param name="foo"/>
                    <xsl:template match="/">
                        <Element foo="{$foo}"/>
                    </xsl:template>
                </xsl:stylesheet>            
            </p:inline>      
        </p:input>
    </p:xslt>    
</p:pipeline>

will result in:

<Element foo="bar"/>

3.11. PURL

3.11.1. Definition

A Persistent URL or PURL is a permanent identifier for a web resource. 

3.11.2. Purpose

A PURL solves the problem of changing URIs in a location-based URI scheme such as HTTP by providing the permanent identification of a web resource.

Note: You may want to refer to the PURL FAQ for some background information about PURLs.

3.11.3. Creating a PURL

To create a PURL, select PURL using the create menu from the folder that you wish to store the PURL in. You will be presented with the following dialogue:

When you press the Create button the PURL will appear in a Callimachus folder, just like any other Callimachus resource.

PURL fields

Here is a description of the fields used to specify a PURL:

Description
Local name The name of your PURL. This name will be appended to the URL of the folder you are in to form the PURL's address.
Comment An optional field provided for your own use.
Type See Types of PURLs.
Content location The target location for the response content from the PURL. All types of PURLs require a target location.
Cache control How long the results of a PURL should be cached by a proxy or a client.
3.11.4. Types of PURLs

PURLs are categorized by the HTTP response code they result in. Callimachus implements the following types of PURLs:

Response code Label Description
200 Copy A PURL resource of this type is a cached copy of its target location. It is most often used in Callimachus to refer to XProc pipelines for the collection, transformation and rendering of remote content.
301 Canonical The resource has been assigned a new permanent URI and any future references to this resource SHOULD use the given location URI. The PURL redirects a client to the target location.
302 Alternate A representation of the resource resides temporarily at the given location. The PURL redirects a client to the target location.
303 Described by The target location provides information about the requested resource, but the requested resource may not be an "information resource" (that is, it may be a real-world object). This type of PURL is most often used when resolving RDF and Linked Data resources.
307 Resides The resource location has been temporarily changed. Redirection to the target location should be considered temporary and may change.
308 Moved The resource URL has been permanently moved to the target location.
404 Missing The resource is not available. It is "Missing". This situation may or may not be temporary. The content of the target location is used as the response content. The content might be shown to a user if it is more than 512 bytes in length.
410 Gone The resource is no longer available and no forwarding address is known. This condition is expected to be considered permanent. The content of the target location is used as the response content. The content might be shown to a user if it is more than 512 bytes in length.

Note: The 200 PURL is also known as an "Active PURL" because the PURL takes an active role in creating its response. Other types of PURLs are passive in that they simply redirect to existing content and/or return an appropriate HTTP response code.

3.11.5. PURL example

In this example, we will name our PURL "blogrollup" to match the example XProc pipeline given in the XProc RSS feed example. This example uses a PURL of type 200 in order to resolve against a dynamically generated RSS feed.

The "Content location" field is set to the PURL's target location. PURLs of type 404 and 410 also require a target location for their response content. In this example, we will provide a relative URL to the XProc results,  and append ?results to the XProc URL to get the results of the pipeline instead of the pipeline itself.

The Cache Control field determines how long the results of a PURL should be cached by a proxy or a client. In this example, we have reduced the max-age parameter from 3600 seconds (1 hour) to 300 seconds (5 minutes).

The screenshot below shows the blogrollup PURL next to two XProc pipelines: blogrollup and hello-world.

How it works

The XProc pipeline "blogrollup(.xpl)" serves as the target for the PURL "blogrollup". When the PURL "blogrollup" is resolved, the target location blogrollup.xpl?results is invoked, which creates the RSS feed and returns it as the result of the PURL.

Benefit of using this PURL

You could just call the XProc pipeline directly, however the PURL provides a significant benefit: The PURL address can stay persistent, even if the location of the target URL changes. Additionally, either the PURL or the pipeline can take parameters that impacts the output of the pipeline. Equally important is the ability for 200 type PURLs to cache their results.

3.11.6. Support for partial PURLs

Callimachus does not implement "Partial PURLs" as of the 1.0 release. Partial PURLs "allow PURLs to be created which refer to a directory level portion of a URL; any path information appended to a partial redirect PURL may in turn be appended to its target URL. That allows a single PURL to redirect to a hierarchy on a target Web server." They are useful in that they allow PURL targets to refer to database content. Callimachus may implement support for partial PURLs in a later release.

3.12. Script

3.12.1. Definition

A script is a JavaScript file that is stored with a .js extension in a Callimachus folder.

3.12.2. Creating a script

To create a script, select Script using the create menu from the folder you wish to store the script in.

3.12.3. Including scripts in a page

Scripts may be included in any Callimachus page or template by using the <script> tag. Below is a page the linking the script utility.js to a Callimachus page:

 <head>
    <title>Customer Report</title>
    <link rel="edit-form" href="?edit" />
    <link rel="comments" href="?discussion" />
    <link rel="version-history" href="?history" />
    <script type="text/javascript" src="/scripts/utility.js"></script>
...

Note: It is recommended that all <script> elements include a @src attribute for all, but the the most trival scripts.

3.13. Style

3.13.1. Definition

A style is a Cascading Style Sheet (CSS) file, used to specify the visual display of content. It is stored with a .css extension in a Callimachus folder.

3.13.2. Creating styles

To create a style, select Style using the create menu from the folder you wish to store the style in.

3.13.3. Using styles

Styles are used to specify the visual presentation of a page. A style sheet may be included in any Callimachus page by naming it within a <link> tag.

3.13.4. Linking style sheets to pages or templates

Linking the style sheet report.css to a Callimachus page:

<head>
    <title>Customer Report</title>
    <link rel="stylesheet" href="/styles/report.css" type="text/css" />
</head>

The stylesheet report.css centers the main heading:

h1
{
text-align:center;
}

Note: It is reccommended to use external styles sheets and not the <style> element.

3.14. User Group

3.14.1. Definition

A User Group is a collection of Callimachus users.

3.14.2. Purpose

User Groups make it more convenient to grant users permissions to resources.

3.14.3. Default Groups

Permission groups exist within Callimachus to make the assignment of abilities to users easier. If a user belongs to that permission group, they are able to perform whatever functions are allowed by that group. There are currently eight different groups in Callimachus - each with a different purpose and level of ability. It is important to assign users to these groups carefully, ensuring that each user has only the minimum access necessary to perform their functions effectively.

Label Path Members Default permissions
public /auth/groups/public A virtual group of all agents Read-only access to the home folder
system /auth/groups/system A group of all IP addresses on the local machine Read-only access to the /callimachus/ folder
everyone /auth/groups/everyone A virtual group of all authenticated agents View and discuss resources in the home folder
users /auth/groups/users Empty list of users Document, link, and upload binary resources
staff /auth/groups/staff Empty list of users Design and code websites and develop applications
power /auth/groups/power Empty list of users Access all data in the underlying data store
admin /auth/groups/admin List of users, including the initial user Edit other user accounts and modify the underlying data store
super /auth/groups/super Nobody Modify /callimachus/ resources
3.14.4. Create a User Group

To create a User Group, select Group using the create menu from the folder you wish to create it in. You will be presented with the following dialogue:

Screenshot: New Group dialogue

Give the group a name and a description. You may use Wiki text to describe the group.

Warning: The group name cannot be changed once it has been created.

3.14.5. Adding Users

A new user group by default is permits no access. To allow individuals access to a group they must be listed as members. To allow group members access from any location list the members in the Members field.


Part III. Developing Callimachus Applications

Overview

In this chapter you will learn how to import linked data, use Callimachus templates and template language, and how to create applications by applying some proven patterns and best practices.

Chapter 4. Callimachus Templates

Callimachus templates determine how RDF resources are created, viewed and edited and are based on HTML 5 plus RDFa. Templates are always associated with a Callimachus class.

Templates allow developers to use the Callimachus template language to manage data in web pages, scripts to make them interactive, styles to make them attractive, and named queries to do things such as summarize large amounts of data as google charts.

This provides a breakdown of the initial code for the three Callimachus template types.

NB: To improve efficiency during the code/test cycle for XHMTL pages, make sure to ahdere to the following practices: 1) Make sure JavaScript and CSS code are not embedded in XHTML files (JS and CSS should be in their own files). 2) Save the generated styles.css output into a new file and change the layout to use the pre-generated styles.css (instead of the dynamic one).

4.1. Resource Create Template

4.1.1. Description

A create template is an HTML 5 form that determines how RDF resources are created. Each create template is associated with a Callimachus class, and developers may script create templates by applying these patterns.

4.1.2. Initial create template code

Here is the default code generated for a new create template.

 1. <?xml version="1.0" encoding="UTF-8" ?>
 3. <html xmlns="http://www.w3.org/1999/xhtml"
 4.     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
 5.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 6.     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
 7. <head>
 8.     <title>New Resource</title>
 9. </head>
10. <body>
11.     <h1>New Resource</h1>
12.     <form method="POST" action="" enctype="application/rdf+xml" typeof=""
13.             onsubmit="return calli.saveResourceAs(event,calli.slugify($('#label').val()))">
14.         <fieldset>
15.             <div class="control-group">
16.                 <label for="label" class="control-label">Label</label>
17.                 <div class="controls">
18.                     <input type="text" id="label" value="{rdfs:label}" class="auto-expand" required="required" autofocus="autofocus" />
19.                 </div>
20.             </div>
21.             <div class="control-group">
22.                 <label for="comment" class="control-label">Comment</label>
23.                 <div class="controls">
24.                     <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
25.                 </div>
26.             </div>
27.             <div class="form-actions">
28.                 <button type="submit" class="btn btn-success">Create</button>
29.             </div>
30.         </fieldset>
31.     </form>
32. </body>
33. </html>
4.1.3. Code Analysis
Lines Element Purpose
1 xml Specifies the character encoding to be UTF-8.
4-6 html element Declares the namespaces used to identify resources in this page.
8,11 title, h1 Contains placeholders for the name of the type of resources being created.
12 form HTML form that will update the RDF database when the user presses the submit button.
15-26 input field classes Placeholders for input fields.
28 button Create button submits the data.

4.2. Resource Edit Template

4.2.1. Description

An edit template is an HTML form and determines how resources from a Callimachus class are modified by the user. Each edit template is associated with a Callimachus class, and developers may script Edit templates by using these patterns and functions.

4.2.2. Initial edit template code

Here is the default code generated when a new edit template is created.

 1. <?xml version="1.0" encoding="UTF-8" ?>
 2. <html xmlns="http://www.w3.org/1999/xhtml"
 3.     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
 4.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 5.     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
 6. <head>
 7.     <title resource="?this">{rdfs:label}</title>
 8. </head>
 9. <body resource="?this">
10.     <h1 property="rdfs:label" />
11.     <form method="POST" action="" enctype="application/sparql-update" resource="?this">
12.         <fieldset>
13.             <div class="control-group">
14.                 <label for="label" class="control-label">Label</label>
15.                 <div class="controls">
16.                     <input type="text" id="label" value="{rdfs:label}" class="auto-expand" required="required" />
17.                 </div>
18.             </div>
19.             <div class="control-group">
20.                <label for="comment" class="control-label">Comment</label>
21.                 <div class="controls">
22.                     <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
23.                 </div>
24.             </div>
25.             <div class="form-actions">
26.                 <button type="submit" class="btn btn-primary">Save</button>
27.                 <button type="button" onclick="window.location.replace('?view')" class="btn">Cancel</button>
28.                 <button type="button" onclick="calli.deleteResource(event)" class="btn btn-danger">Delete</button>
29.             </div>
30.         </fieldset>
31.     </form>
32. </body>
33. </html>
4.2.3. Code analysis
Lines Element Purpose
1 xml Specifies the character encoding to be UTF-8.
3-5 html Declares the namespaces used to identify resources in this page.
7 title Assigns the page title the label of the current resource.
9 body Sets the RDF subject for elements inside the body element.
10 h1 Displays the label of the current resource.
11 form Form used to update the RDF data for the current resource.
13-24 input fields Sample input fields.
26-28 buttons Buttons used to submit, cancel changes or delete the current resource.

4.3. Resource View Template

4.3.1. Description

A view template determines how resources from a Callimachus class are rendered for display. Each view template is associated with a Callimachus class, and developers may script view templates by applying these patterns.

4.3.2. Initial view template code
 1. <?xml version="1.0" encoding="UTF-8" ?>
 2. <html xmlns="http://www.w3.org/1999/xhtml"
 3.     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
 4.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 5.     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
 6. <head>
 7.     <title resource="?this">{rdfs:label}</title>
 8.     <link rel="edit-form" href="?edit" />
 9.     <link rel="comments" href="?discussion" />
10.     <link rel="describedby" href="?describe" />
11.     <link rel="version-history" href="?history" />
12. </head>
13. <body resource="?this">
14.     <h1 property="rdfs:label" />
15.     <pre class="wiki" property="rdfs:comment" />
16. </body>
17. </html>
4.3.3. Code Analysis
Lines Element Purpose
1 xml Specifies the character encoding to be UTF-8.
3-5 html Declares the namespaces used to identify resources in this page.
7 title Displays the name of the current resource.
8-11 link(s) Links for editing, describing and viewing the version history of the current resource.
13 body Sets the subject of the RDFa attributes contained in the body of the page.
14 h1 Displays the name of the resource being edited.
15 pre The content of the comment field, which may include wiki markup.

4.4. Named Query Template

4.4.1. Description

A named query template determines how query results from a Named Query are displayed. Each template is associated with a Named Query using the SPARQL comment # @view. When this comment is present in the query, the queries' view tab will return the markup in the template. The template can then use JavaScript to load the query results (shown below) or if the query has exactly one variable in the SELECT clause, the template can walk the graph from the results of that variable binding as described in View Templates for Named Queries.

4.4.2. Named Query code
# @view pie-chart.xhtml
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
PREFIX vcard:<http://www.w3.org/2006/vcard/ns#>
PREFIX directory:<http://dir.w3.org/rdf/2012/directory/>
SELECT ?label (count(distinct ?proj) as ?value) {
    ?proj directory:isOrganizationType [ skos:prefLabel ?label ]
} GROUP BY ?label ORDER BY desc(?value)
4.4.3. View template code
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Pie Chart</title>
    <script src="https://www.google.com/jsapi" type="text/javascript"> </script>
    <script type="text/javascript">
        google.load("visualization", "1", {callback: function(){
            var chart = new google.visualization.ChartWrapper({
                dataSourceUrl:"?results",
                options:{"hasLabelsColumn":true,is3D:false,height:300},
                chartType:"PieChart"
            });
            chart.setContainerId("pie-chart");
            chart.draw();
        }});
    </script>
</head>
<body>
    <h1>Pie Chart</h1>
    <div id="pie-chart" class="chart" style="height:300px;width:400px"></div>
</body>
</html>

Chapter 5. Callimachus Template Language

The Callimachus template language enables programmers to retrieve and manipulate RDF data stored in Callimachus.

5.1. Evaluation Context

Every element in a Callimachus template must have either a new subject or an inherited subject.

5.1.1. New Subject

As processing progresses, any @about or @resource attributes will change the current subject.

Below the body changes the current subject to the variable ?this.

<body resource="?this">
  <!-- Expressions and RDFa attribute in body will use the subject ?this. -->
</body>

If @about and @resource is not present, then @src and @href can also set the new subject of an element.

5.1.2. Inherited Subject

The usual way an inherited subject gets set is when a parent element has the attribute @resource.

<body resource="?this">
  <ul>
    <li rel="foaf:knows" resource="?friend">
      <!-- Within this element the current subject is ?friend. -->
    </li>
  </ul>
</body>

The attribute @href and @src can also change the inherited subject.

<body resource="?this">
  <ul>
    <li rel="foaf:knows" resource="?friend">
      <a rel="foaf:img" href="?img">
        <!-- Within this element the current subject is ?img. -->
      </a>
    </li>
  </ul>
</body>

5.2. Variables

Variables are referenced using a '?' followed by a name, such as ?this or ?myObject. The variable ?this is bound to the resource being rendered for view and edit templates.

Variables can be declared using RDFa attributes, such as @about and @resource. Once variables are declared, they can be used

  • within the current element

  • in nested elements

  • in RDFa attributes, or

  • in Callimachus expressions.

5.2.1. Using variables

Variables can be used in the RDFa attributes  @about, @content, and @resource to declare a new variable, or to reference a variable declared in a parent element.

Variables can also be used in the  @href and @src attributes if they are used on an element that also contains a @rel, @rev, or @property attribute.

5.3. Expressions

Callimachus expressions can be placed in attributes or between elements (i.e. text nodes). Expression types may be variable, property or literal, as described below.

5.3.1. Variable Expressions

A variable wrapped in curly brackets will either be replaced with the bound variable value or removed. In the example below, the bound value to the variable ?this is substituted for {?this}.

Properties that are not present in the RDF store will result in an empty string in the resulting HTML page.  Thus, use of the curly bracket syntax may result in empty tags or attributes.  For example, this is always expected to succeed since the ?this variable should always exist:

<body resource="?this">
  <p>The URI of this resource is {?this}.</p>
</body>

However, the use of a property in tag contents or some tag attributes (such @src) might result in an empty tag when the property is not present in the RDF store.  So:


<h1>{rdfs:label}</h1>

could become:


<h1></h1>

in the generated HTML if the property rdfs:label does not exist in the RDF store.  The possibility of empty tags could become significant, as with image tags when a property is used in the src attribute because some browsers (e.g. Firefox version 29) will display an empty image tag as a broken image.  Therefore, one might prefer to replace the use of curly brackets:


<img src="{foaf:depiction}" />  # An anti-pattern.  Do not use!

with:


<img rel="foaf:depiction" src="?depiction" />

to avoid the creation of an empty tag.

5.3.2. Property Expressions

A CURIE wrapped in curly brackets will be replaced with the property value from the RDF store for the current subject. In the example below the expression has the subject of ?this and a predicate of rdfs:label. The object of matching triples from the RDF store will be substituted for the expression {rdfs:label}.

<head>
  <title resource="?this">{rdfs:label}</title>
</head>
5.3.3. Literal Expressions

Quoted strings wrapped in curly brackets will be replaced with the literal string within.

This code:

<p>The expression {'{rdfs:label}'} is often used to refer to resources.</p>

Would produce:

<p>The expression {rdfs:label} is often used to refer to resources.</p>

5.4. Loops

Callimachus can only loop over properties and relationships present in the RDF store.

Any element with the @property attribute will be repeated (or not shown at all) for every matching property value in the RDF store.

<body resource="?this">
  <h2>List of values for the current resource</h2>
  <ul>
    <li property="rdf:value" content="?value">
      <!-- this li element may be repeated -->
    </li>
  </ul>
</body>

Any element with @rel or @rev attribute and a @resource attribute will be repeated (or not shown at all) for every matching relationship partner in the RDF store.

<body resource="?this">
  <h2>List of friends for the current resource</h2>
  <ul>
    <li rel="foaf:knows" resource="?friend">
      <!-- this li element may be repeated -->
    </li>
  </ul>
</body>

Chapter 6. Functions and Events for Scripting Edit and Create Templates

The three types of JavaScript functions listed below provide common behaviour for RDFa-aware DOM manipulation. These functions are used with edit templates.

6.1. Dialogue functions

6.1.1. Overview

Callimachus uses the following four functions for manipulating resources using dialogue boxes.

6.1.2. createResource
Description

Allows the user to choose or create a resource for a dropzone by using a dialogue box. If no src is provided the href attribute of the event.target will be used.

Signature

calli.createResource( event, [src] )

Parameter Description
event HTML click event
src (optional) URL of the page to display in the dialogue.
Example
<a href="Person?create" title="Create a Person"
      onclick="return calli.createResource(event)"
      class="ui-icon ui-icon-newwin" />
6.1.3. deleteResource
Description

Issues a HTTP DELETE request to the current resource (i.e. current page URL). If the request is successful the browser page is replaced by either the

  • redirect page, or the
  • parent resource page, when a redirect page is not specified.
Signature

calli.deleteResource( event, [redirect] )

Parameter Description
event HTML click event
redirect (optional) URL to redirect browser to
Example
<button type="button" onclick="calli.deleteResource(event)" class="btn btn-danger">Delete</button>
6.1.4. saveResourceAs
Description

Assigns a URI to a the resource in a form, if no @resource or @about is present on the form. This method will prompt the user to confirm a namespace and fileName if the event is not a submit event or if the namespace for the resource cannot be determined. When the user confirms the namespace and fileName, the form is automatically submitted.

Signature

calli.saveResourceAs( event, [fileName, [create]] )

Parameter Description
event
  • HTML form submit or
  • HTML click event
fileName (optional) Suggested local part of newly crated resource
create (optional) URI of the class of resource to create
Example
<form method="POST" action="" enctype="application/rdf+xml" typeof="foaf:Person"
    onsubmit="return calli.saveResourceAs(event,calli.slugify($('#label').val()))">
6.1.5. selectResource
Purpose

Allows the user to select a resource for a dropzone by using a folder view dialogue box.

Signature

calli.selectResource( event, [src] )

Parameter Description
event HTML click event
src (optional) URL of the page in the dialogue
Example
<a href="/scheme/medimus/top" title="Browse Mediums"
    onclick="return calli.selectResource(event)"
    class="ui-icon ui-icon-folder-open" />
Detailed logic

Here is how the method operates in more detail.

IF ... THEN ...
no src is provided the href attribute of the event.target will be used
the Select button is clicked the subject of the current page is dropped onto event.target as a s:text/uri-list

6.2. DOM functions

6.2.1. Purpose

The following three functions manage resources by manipulating the Document Object Model (DOM).

6.2.2. addResource
Description

Adds a resource to the parentNode or to a container element. The control element must have a unique id.

Signature

calli.addResource (event, [container] )

Parameter Description
event HTML click event
container (optional) CSS selector of container element
Example
<div class="control-group">
    <label for="altLabel" class="control-label">Alternate label</label>
    <div id="altLabel-control" class="controls">
        <input type="text" id="altLabel" property="skos:altLabel" content="?alt" value="{?alt}" class="auto-expand" />
        <a href="javascript:void(0)" title="More" onclick="return calli.addResource(event)" class="ui-icon ui-icon-plus" />
    </div>
</div>


<div class="control-group">
    <label for="adr" class="control-label">Address <a href="javascript:void(0)" title="Another Address"
        onclick="return calli.addResource(event,'#adr')" class="ui-icon ui-icon-plus" /></label>
    <div id="adr" rel="vcard:adr" class="controls">
        <div typeof="vcard:Address">
            <input type="text" placeholder="street address" value="{vcard:street-address}" />
            <input type="text" placeholder="extended address" value="{vcard:extended-address}" />
            <input type="text" placeholder="po box" value="{vcard:post-office-box}" />
        </div>
    </div>
</div>
6.2.3. insertResource
Description

Inserts an RDFa resource into a dropzone. The new resource URI is read from the text/uri-list of the dropped data.

Signature

calli.insertResource( event )

Parameter Description
event HTML drop event
Example
<div id="related" dropzone="link s:text/uri-list" class="control-group"
        ondrop="return calli.insertResource(event)">
    <label class="control-label">Related</label>
    <div rel="skos:related" class="controls vbox">
        <span resource="?related" typeof="skos:Concept" class="ui-state-highlight ui-corner-all">
            <span property="skos:prefLabel" />
        </span>
    </div>
</div>
// Or, create your own pseudo event
calli.insertResource(jQuery.extend(jQuery.Event('drop'),
  {target:$('#id-of-dropzone')[0],dataTransfer:{getData:function(){return url_of_resource}}}
));
6.2.4. removeResource
Description

Removes an RDFa resource from the page.

Signature

calli.removeResource( event )

Parameter Description
event HTML click event
Example
<span about="?medium" typeof="skos:Concept" class="ui-state-highlight ui-corner-all">
  <span property="skos:prefLabel" />
  <a href="{?medium}" title="Remove" onclick="return calli.removeResource(event)" class="ui-icon ui-icon-close" />
</span>

6.3. Utility functions

6.3.1. Overview

In this part we will examine the utility functions available in Callimachus.

6.3.2. getUserIri
Description

This JavaScript function retrieves the current user identifier, or null if the user is not logged in.

Signature

calli.getUserIri()

Example
var user = calli.getUserIri();
if (user) {
  $('#form').append('<span rel="dc:creator" resource="' + user + '"/>');
}

6.4. Form Events

6.4.1. calliSubmit

The calliSubmit event is triggered from forms with enctype="application/rdf+xml", enctype="application/sparql-update", editor forms, or method="PUT" (if the form's @enctype matches the input[type=file] @accept attribute).

Event property Description Example
type Event type always "calliSubmit"
resource URI of the resource that will be created or edited "http://example.com/this-resource"
payload request body rdf+xml string, sparql-update string, file object
preventDefault() Stops the form from submitting
6.4.2. calliDelete

Triggered when the calli.deleteResource function is called.

Event function Description Example
type Event type always "calliDelete"
resource URI of the resource that will be deleted "http://example.com/this-resource"
location The DELETE request URL "http://example.com/this-resource?edit"
preventDefault() Stops the resource from being deleted
6.4.3. calliRedirect

Triggered when the submit or delete operation is successful.

Event property Description Example
type Event type always "calliRedirect"
resource URI of the resource that was created, edited, or deleted "http://example.com/this-resource"
location The redirect target "http://example.com/this-resource?view"
cause submit, calliSubmit, or calliDelete event object {type:"calliSubmit"}
preventDefault() Cancels the redirection


Chapter 7. Patterns for Scripting Edit and Create Templates

This describes software patterns you can use when developing your Edit and Create templates.

7.1. Input Patterns

7.1.1. Overview

In this part we will explore patterns for handling the following kinds of user input:

7.1.2. Single Text Input
Intent

To allow the user to input at most one value for a property.

Motivation

Restricting the number of property values the form can be more effective, reduce complexity and reduce user distractions.

Applicability

Use for functional property values.

Implementation

Assign the value a property expression, and include a datatype attribute if needed. Use  class="auto-expand" to cause the textarea to grow as the content grows.

Sample Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:foaf="http://xmlns.com/foaf/0.1/"
   xmlns:dcterms="http://purl.org/dc/terms/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
   <head><title resource="?this">{foaf:name}</title></head>
   <body>
      <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" typeof="foaf:Person" >
         <fieldset>
            <div class="control-group">
               <label for="name" class="control-label">Name</label>
               <div class="controls">
                  <input type="text" id="name" value="{foaf:name}" class="auto-expand" required="required" size="24" />
               </div>
            </div>
            <div class="control-group">
               <label for="date" class="control-label">Date</label>
               <div class="controls">
                   <input id="date" type="date" datatype="xsd:date" value="{dcterms:date}" />
               </div>
            </div>
            <div class="control-group">
               <label for="comment" class="control-label">Comment</label>
               <div class="controls">
                   <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
               </div>
            </div>
            <div class="form-actions">
               <button id="save" type="submit" class="btn btn-primary">Save</button>
               <button id="cancel" type="button" onclick="location.replace('?view')" class="btn">Cancel</button>
               <button id="delete" type="button" onclick="calli.deleteResource(event)" class="btn btn-danger">Delete</button>
            </div>
         </fieldset>
      </form>
   </body>
</html>
7.1.3. Multiple Text Input
Intent

Allow the user to input zero or more values for a property.

Motivation

Callimachus provides JavaScript functions to add multiple property values.

Applicability

Use for non-functional property values, such as keywords or alternate labels.

Implementation

Use the calli.addResource(event) function to add more input boxes with @property.

Sample Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
  xmlns:dcterms="http://purl.org/dc/terms/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
  xmlns:skos="http://www.w3.org/2004/02/skos/core#">
  <head><title resource="?this">{skos:prefLabel}</title></head>
  <body>
     <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" typeof="skos:Concept" >
       <fieldset>
          <div class="control-group">
             <label for="label" class="control-label">Label</label>
             <div class = "controls">
                <input type="text" id="label" value="{skos:prefLabel}" class="auto-expand" required="required" autofocus="autofocus" />
             </div>
          </div>

          <div class="control-group">
             <label for="altLabel" class="control-label">Alternate label</label>
             <div class="controls">
                <input type="text" id="altLabel" property="skos:altLabel" content="?alt" value="{?alt}" class="auto-expand" />
                <a href="javascript:void(0)" title="More" onclick="return calli.addResource(event)" class="ui-icon ui-icon-plus" />
             </div>
          </div>
          <div class="form-actions">
             <button id="save" type="submit">Save</button>
             <button id="cancel" type="button" onclick="location.replace('?view')">Cancel</button>
             <button id="delete" type="button" onclick="calli.deleteResource(event)">Delete</button>
          </div>
       </fieldset>
    </form>
  </body>
</html>

7.2. Manipulation Patterns

7.2.1. Overview

In this part we will explore the following two patterns for creating and editing resources:

7.2.2. Class Instance Create
Intent

To create a new resource associated with Callimachus templates, through a Callimachus class.

Motivation

In addition to exploring and viewing existing resources, the application may allow a user to add additional resources. For example, in a workflow-based application the user may need to be able to create new tasks.

Applicability

Use this where the class of resource is known. The class definition provides a starting point for deciding which properties should be included in the creation form. However, the actual choice of properties is determined by the developer.

Implementation

The create template enables the creation of a new instance of a creatable class. The properties in the form are not determined by the class definition so the developer is free to leave out or add new properties as appropriate (e.g. the use of an rdfs:label may not be mandated by the class definition).

Security

By default, the create operation is restricted to authorized users. To enable this for users of the admin group we add the admin group as a calli:author for the class. Add other user groups as appropriate.

Sample Code

Defines a new Callimachus class specific for resources created locally. Make this a subclass of the more general foaf:Person. The resulting resource will have both the Callimachus class type and any types in the typeof attribute of the form. Within the Class, assign a new create template.

The RDFa create template allows the user to initialise the new resource. The resource is assigned a URL based on the input label. The label is first converted to a lower-case uri-safe format.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:foaf="http://xmlns.com/foaf/0.1/">
   <head>
      <title>New Person</title>
   </head>
   <body>
      <form id="form" method="POST" action="" enctype="application/rdf+xml" typeof="foaf:Person"
             onsubmit="return calli.saveResourceAs(event,call.slugify($('#name').val()))">
          <fieldset>
              <div class="control-group">
                   <label for="name" class="control-group">Name</label>
                   <div class="controls">
                        <input type="text" id="name" value="{foaf:name}" required="required" />
                   </div>
              </div>
              <div class="control-group">
                   <label for="comment" class="control-label">Comment</label>
                   <div class="controls">
                        <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
                   </div>
              </div>
              <div class="form-actions">
                   <button id="create" type="submit" class="btn btn-success">Create</button>
              </div>
          </fieldset>
      </form>
   </body>
</html>
7.2.3. Class Instance Edit
Intent

To update the properties of an existing resource.

Motivation

Based on the known class of a resource we can create an edit page that enables the user to edit those properties and submit these changes.

Applicability

Use this pattern where the values of an RDF resource can be directly updated by the user.

Implementation

The editing view may be accessed by appending ?edit to the URL of the resource (as long as it is an instance of an editable class). In addition, the 'Edit' tab can be used from the view page.

Sample Code

Define an edit template for a Callimachus Class. The template uses the predefined validation rule required="required" that should be used on mandatory inputs.

The RDFa template person-edit.xhtml displays the current values for the form entries and submits the the list of RDF updates on form submission.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:foaf="http://xmlns.com/foaf/0.1/">
   <head><title resource="?this">{foaf:name}</title></head>
   <body resource="?this">
      <h1 property="foaf:name" />
      <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" typeof="foaf:Person" >
         <fieldset>
             <div class="control-group">
                 <label for="name" class="control-label">Name</label>
                 <div class="controls">
                      <input type="text" id="name" value="{foaf:name}" class="auto-expand" required="required" />
                 </div>
             </div>
             <div class="control-group">
                  <label for="comment">Comment</label>
                  <div class="controls">
                       <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
                  </div>
             </div>
             <div class="form-actions">
                  <button id="save" type="submit">Save</button>
                  <button id="cancel" type="button" onclick="location.replace('?view')">Cancel</button>
             </div>
         </fieldset>
      </form>
   </body>
</html>

The following sample extends person-edit.xhtml adding the ability to delete the resource. The javascript adds a click handler to the delete button that calls calli.deleteResource(event) on confirmation.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:foaf="http://xmlns.com/foaf/0.1/">
   <head><title resource="?this">{foaf:name}</title></head>
   <body resource="?this">
      <h1 property="foaf:name" />
      <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" typeof="foaf:Person" >
         <fieldset>
             <div class="control-group">
                 <label for="name" class="control-label">Name</label>
                 <div class="controls">
                      <input type="text" id="name" value="{foaf:name}" class="auto-expand" required="required" />
                 </div>
             </div>
             <div class="control-group">
                  <label for="comment">Comment</label>
                  <div class="controls">
                       <textarea id="comment" class="auto-expand">{rdfs:comment}</textarea>
                  </div>
             </div>
             <div class="form-actions">
                  <button id="save" type="submit" class="btn btn-primary">Save</button>
                  <button id="cancel" type="button" onclick="location.replace('?view')" class="btn">Cancel</button>
                  <button id="delete" type="button" onclick="calli.deleteResource(event)" class="btn btn-danger">Delete</button>
             </div>
         </fieldset>
      </form>
   </body>
</html>

7.3. Selection Patterns

7.3.1. Overview

In this chapter we will explore four patterns for making data selection easier:

7.3.2. Large Hierarchical Selection
Intent

To choose from a large set of finite possible concepts.

Motivation

When categorizing resources the number of categorizes is often too large for a flat list and requires the ability to browse through possible concepts.

Applicability

Use for object relationships that have a large set of finite possible objects.

Implementation

Create a single top concept with skos:narrower and skos:related of the hierarchical concepts that are valid objects for this relationship. The user will be able to navigate among the concepts using broader and narrower relationships. When the user navigates to the concept they want they can click the select button.

Sample Code
<div id="medium" dropzone="link string:text/uri-list" class="control-group"
    ondrop="return calli.insertResource(event)">
 <label class="control-label">Medium <a href="/scheme/medimus/top" title="Browse Mediums"
     onclick="return calli.selectResource(event)" class="ui-icon ui-icon-folder-open" /></label>
  <div rel="dcterms:medium" class="controls">
   <span resource="?medium" typeof="skos:Concept" class="ui-state-highlight ui-corner-all">
     <span property="skos:prefLabel" />
     <a href="{?medium}" title="Remove relationship" onclick="return calli.removeResource(event)" class="ui-icon ui-icon-close" />
   </span>
 </div>
</div>
7.3.3. Limited Selection
Intent

To provide the user with a small set of possible relations to choose from.

Motivation

Some relationships are limited to small set of target objects, that are curated separately. For this it is important to provide the user with a list of possible selections inline.

Applicability

Use when the number of possible target objects in a relationship is limited and can be shown to the user all together.

Implementation

Create a folder containing the concepts that should be presented to the user. Use the calli:hasComponent relationship from the folder to the concepts to build to list.

Within an edit template page, add one of the following markup patterns.

Sample Code

Horizontal radio buttons are best used when the relationship is functional (only one object) and the concepts can be listed in a single line.

<div xmlns:dcterms="http://purl.org/dc/terms/" class="control-group">
  <label for="medium" class="control-label">Medium</label>
  <div id="medium" class="controls">
    <label class="inline radio" rel="dcterms:medium" resource="?concept">
      <input type="radio" name="medium" checked="checked" />
      <span rev="calli:hasComponent" resource="/scheme/mediums/" property="skos:prefLabel" />
    </label>
  </div>
</div>

Horizontal checkboxes are best used when the relationship is non-functional (can have multiple objects) and the concepts can be listed in a single line.

<div xmlns:dcterms="http://purl.org/dc/terms/" class="control-group">
  <label for="medium" class="control-label">Medium</label>
  <div id="medium" class="controls">
    <label class="inline checkbox" rel="dcterms:medium" resource="?concept">
      <input type="checkbox" name="medium" checked="checked" />
      <span rev="calli:hasComponent" resource="/scheme/mediums/" property="skos:prefLabel" />
    </label>
  </div>
</div>

Vertical checkboxes is best used when the relationship is non-functional (can have multiple objects) and all concepts should visible to the user at once.

<div xmlns:dcterms="http://purl.org/dc/terms/" class="control-group">
  <label for="medium" class="control-label">Medium</label>
  <div id="medium" class="controls">
    <label class="checkbox" rel="dcterms:medium" resource="?concept">
      <input type="checkbox" name="medium" checked="checked" />
      <span rev="calli:hasComponent" resource="/scheme/mediums/" property="skos:prefLabel" />
    </label>
  </div>
</div>
7.3.4. Range Relationships
Intent

Allow the user to lookup or create resources by type.

Motivation

Many relationships between resources are open ended, requiring only particular resource types. The user may link to a large possible set of objects or create a new one.

Applicability

Use for object relationships that have a open ended set of possible objects.

Implementation

Use the function calli.createResource(event) and point to a class with a create template that the user can use to create an object resource. The attribute typeof restricts the inline lookup to resources of that type.

Sample Code
<div id="knows" dropzone="link string:text/uri-list" class="control-group"
    ondrop="return calli.insertResource(event)">
  <label class="control-label">Knows <a href="/schema/Person?create" title="Create"
      onclick="return calli.createResource(event)" class="ui-icon ui-icon-newwin" /></label>
  <div rel="foaf:knows" class="vbox controls">
    <span resource="?knows" typeof="foaf:Person" class="ui-state-highlight ui-corner-all">
      <span property="foaf:name" />
      <a href="{?knows}" title="Remove relationship" onclick="return calli.removeResource(event)" class="ui-icon ui-icon-close" />
    </span>
  </div>
</div>
7.3.5. Scroll Through Selection
Intent

To provide the user with a limited set of possible relations to choose from.

Motivation

Some relationships are limited to a set of target objects, that are curated separately. For this it is important to provide the user with a list of possible selections to choose from.

Applicability

Use when the number of possible target objects in a relationship is limited and small enough that the user can scroll quickly through all of them.

Implementation

Create a folder containing the enumerated concepts that should be presented to the user. Use the calli:hasComponent relationship from the folder to the concepts to link all possible relationships. The selected="selected" attribute in the option tag is required.

Within a edit template page, add one of the following markup patterns.

Sample Code

Drop down list is best used when the relationship is functional (only one object) and the list of concepts should be hidden by default.

<div xmlns:dcterms="http://purl.org/dc/terms/" class="control-group">
  <label for="medium" class="control-label">Medium</label>
  <div class="controls">
    <select id="medium" rel="dcterms:medium">
      <option selected="selected" about="?concept" rev="calli:hasComponent" resource="/scheme/mediums/" property="skos:prefLabel" />
    </select>
  </div>
</div>

Select box is best used when the relationship is non-functional (can have multiple objects) and the user should be able to scroll through the list of concepts.

<div xmlns:dcterms="http://purl.org/dc/terms/" class="control-group">
  <label for="medium" class="control-label">Medium</label>
  <div class="controls">
    <select id="medium" multiple="multiple" rel="dcterms:medium">
      <option selected="selected" about="?concept" rev="calli:hasComponent" resource="/scheme/mediums/" property="skos:prefLabel" />
    </select>
  </div>
</div>

Chapter 8. Patterns for Scripting View Templates

This describes software patterns you can use when scripting view templates.

8.1. Display Patterns

8.1.1. Overview

Here we will explore four patterns that can help visualize data using View templates:

8.1.2. Class Instance View
Intent

This is the simplest kind of view where we wish to display the properties of a resource, an instance of known class. The resource is represented in an RDF structure.

Motivation

To present a customised view of a resource based on a known class. The view template of the class includes properties that we would expect to see in the view page of the resource.

Applicability

Consider using this pattern where the resource is represented as RDF metadata with literal and object properties. The structure may be browsed using the Callimachus triple browser, but it is more convenient to present the user with a customised view based on the class.

Implementation

Create a Callimachus Class that is either linked from the resource through an rdf:type relationship or create the Class as an equivalent of a owl:Class linked from the resource through an rdf:type relationship.

The class instance is the task resource denoted by '?this' in both the title and the body with the template. For this example, we assume that the resource has both literal (rdfs:comment) and object properties; object properties may be displayed inline, nested within the current page, or they may translate into links to other view pages. Examples of each are shown below. In the latter case, the resource may not resolve to a user-friendly page, so the link will open an internal "view" page (if there is one). Additionally, the pre-formatted comment field may contain Creole wiki markup.

Sample Code

The RDFa template my-class.xhtml contains the following XHTML code. We assume the primary class instance has rdfs:label and rdfs:comment, two object properties dcterms:hasPart and dcterms:relation; the object of each has an rdfs:label.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:dcterms="http://purl.org/dc/terms/"
   xmlns:dbpedia-owl="http://dbpedia.org/ontology/">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <pre class="wiki" property="rdfs:comment" />

     <!-- inline object relationship -->
     <div rel="dcterms:hasPart">
        <span property="rdfs:label" />
     </div>

     <!-- out-of-line, hyper-linked relationship -->
     <div rel="dcterms:relation" resource="?resource2">
        <a href="?resource2" class="view" property="rdfs:label" />
     </div>

     <!-- out-of-line, reverse hyper-linked relationship -->
     <div rev="dcterms:relation" resource="?resource3">
        <a href="?resource3" class="view" property="rdfs:label" />
     </div>

     <!-- use of a property in an image tag -->
     <div rel="dbpedia-owl:thumbnail" resource="?thumbnail">
       <img src="?thumbnail" style="border:1px solid black;" align="left" hspace="10" vspace="10" />
     </div>

   </body>
 </html>
8.1.3. Class Membership View
Intent

To list members of a class, rather than a specific instance.

Motivation

In many applications we need to view a set of resources in order to select the specific resource we are interested in.

Applicability

Use this pattern where members of a class are to be displayed. Where membership is conditional it is possible to test for the existence of a property/value, but not for more complex filters.

Implementation

Rather than using a class view template to display a single resource, you must use a query view template to display a set of resources.

Sample Code
# my-class-membership.rq
#
# @view my-class-membership.xhtml
#
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX eg: <http://example.com#>
SELECT ?member {
    ?member a eg:MyClass
}

The Named Query references a view template: my-class-membership.xhtml. The div element has no enclosing context so establishes a new subject of the indicated type. Consequently, the div is repeated for every member of MyClass. The link to my-class-membership.rq?results (the above named query) may be included in a menu or anywhere else a link may appear.

The file my-class-membership.xhtml contains a simple RDFa template that renders all members of MyClass and provides a link to each member.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:eg="http://example.com#">
   <head><title>Class Membership</title></head>
   <body>
        <div resource="?member">
          <a href="?member" property="rdfs:label" class="view"/>
        </div>
   </body>
</html>

8.2. Formatting Patterns

This describes four ways of formatting data in View templates:

8.2.1. Property List
Intent

Display multivalued property values in a meaningful way.

Motivation

Non-functional datatype property have unordered set of values that need to be shown in a organized view.

Applicability

This pattern applies when a property may have zero or more values and is non-functional.

Implementation

Properties can be shown in a view template vertically, in a list, or horizontally.

Sample Code

To list property values vertically use a div.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <div property="skos:altLabel" />
   </body>
</html>

To list property values in an unordered list use ul/li tags.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <ul>
       <li property="skos:altLabel" />
     </ul>
   </body>
</html>

To list all property values horizontally use span tags.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <span property="skos:altLabel" />
   </body>
</html>
8.2.2. Relationship List
Intent

Display multivalued object relationships in a meaningful way.

Motivation

Non-functional object relationships have unordered set of objects that need to be shown in a organized view.

Applicability

When a relationship may have zero or more values and is non-functional.

Implementation

Object links can be shown in a view template vertically, in a list, or horizontally. A link with an href attribute can be used to link the object in an HTML view page.

Sample Code

Relationships can also be listed vertically using divs.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
      <h1 property="rdfs:label" />

      <div rel="skos:topConcept" resource="?concept">
         <a href="?concept" property="skos:prefLabel" />
      </div>
   </body>
</html>

To list relationship objects in an unordered list use ul/li tags.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <ul>
       <li rel="skos:topConcept" resource="?concept">
         <a href="?concept" property="skos:prefLabel" />
       </li>
     </ul>
   </body>
 </html>

Relationships can be listed horizontally (like properties above) using a span tag.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head>
       <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
       <h1 property="rdfs:label" />

       <span rel="skos:topConcept" resource="?concept">
           <a href="?concept" property="skos:altLabel" />
       </span>
   </body>
</html>
8.2.3. Sorted View
Intent

To display resources sorted by one or more properties

Motivation

Many resources need to be presented in a specific order:- Alphabetic order; date order; or in order of priority.

Applicability

Use this pattern where resources contain one or more properties that may be used to determine the order of presentation.

Implementation

This implementation uses the skos:member property to define the relationship between the subject, ?this, and it's ?members. The members are sorted in ascending order of their labels, by associating the style asc or desc with a property.

Sample Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:skos="http://www.w3.org/2004/02/skos/core#">
   <head><title>Sorted View</title></head>
   <body resource="?this">
      <table>
         <tbody class="sorted">
            <tr rel="skos:member" resource="?member">
               <td><a href="?member" property="rdfs:label" class="view asc"/></td>
            </tr>
         </tbody>
      </table>
   </body>
</html>
8.2.4. Wikitext
Intent

To display text property values using simple markup.

Motivation

Provide simple markup for text that can be easily read without prior knowledge of the markup syntax.

Applicability

Used for properties that may benefit from markup, but the markup will only be used in some of the property values.

Implementation

Display the property value in a pre tag with a CSS class of wiki. Callimachus will format the element using the Creole syntax on page load.

Sample Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
   <head>
      <title resource="?this">{rdfs:label}</title>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />

     <pre class="wiki" property="rdfs:comment" />

   </body>
</html>

8.3. Navigation Patterns

8.3.1. Overview

Here we explore patterns that can help users navigate your Callimachus application.

8.3.2. Context Sensitive Menu
Intent

To provide a menu item that is tied to a specific web-page.

Motivation

Many web-based application need to provide links that are determined by the currently displayed page. This might be to upload or download specific information; to copy the current resource, etc.

Applicability

Use this pattern to define a menu that is defined in the context of a given page.

Implementation

Contextual menus are defined within the web-page itself in a sidebar. This will appear in the upper right-hand corner of the page.

Sample Code

Application metadata that defines this template must be defined as with other patterns. The template below defines a list of menu items of class "aside".

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
   <body resource="?this">
      <div id="sidebar">
         <aside>
            <p><a href="?whatlinkshere">What links here</a></p>
            <p><a href="./?view">View container folder</a></p>
            <p><a href="?edit">Edit this resource</a></p>
         </aside>
      </div>
      <h1>Title Here</h1>
      <p>Rest of the page here</p>
   </body>
</html>

Chapter 9. Finding, Importing and Displaying Linked Data

This chapter provides a hands-on example showing how to find, import and display linked data in Callimachus. For the example, we are going to find and display linked data about the father of digital music synthesis - Wolfgang Palm.

9.1. Finding linked data

9.1.1. Sources of linked data

Image: Linked Open Data Project

The Linked Open Data Project provides tens of billions of RDF statements that are ready to use, with DBpedia at the center of the linked data cloud.

Other major sources include

9.1.2. Using DBpedia to get linked data

Follow these steps to get linked data from DBpedia. 

Step Action Example
1 Find the information you are looking for in Wikipedia. http://wikipedia.org/wiki/Wolfgang_Palm
2 Change the Wikipedia URL into a DBpedia URL as shown. http://dbpedia.org/resource/Wolfgang_Palm
3 Download the RDF/XML file (i.e. "Save link as"). http://dbpedia.org/data/Wolfgang_Palm.rdf

9.2. Importing linked data

Follow these steps to import linked data into Callimachus.

Step Action Example
1 Edit the URI(s) of the resources you want to host to be relative URIs. Change "http://dbpedia.org/resource/Wolfgang_Palm" to "Wolfgang_Palm"
2 Using the main menu navigate to the Home Folder and create a new folder for your data. Create a folder with the label "resource"
3 Open the new folder and using the upload file icon, next to the create menu. The modified Wolfgang_Palm.rdf is the linked data file you want to upload.
4 Upload the file. Result: A new graph document will be created in your folder. It will appear as "wolfgang_palm" in the folder listing, the .rdf file extension is not displayed in the folder view.

9.3. Displaying linked data

Follow these steps to display the linked data in Callimachus.

Step Action Example
1

Determine the type of the resource that you want to model.

Note: Use a class from a well-known vocabulary so the data will be easier to reuse. 

Wolfgang_Palm a rdf:type foaf:Person , yago:Person100007846 , yago:GermanMusicians .

2 Download the vocabulary as an RDF file. Save link as:  FOAF Vocabulary Specification
3 Upload the vocabulary RDF file into a Callimachus folder.

4 From the graph view select Explore OWL classes in this graph from the main menu.
5 Using the equivalent (assign templates) option, select the desired class to create a new Callimachus class In this case we are selecting for foaf:Person. When you create an eqivalent this class it will automatically fill in the Callimachus class name with the word Person.
6 Create a default view template and save the class. Result: You will now be able to view any RDF data that uses the foaf:Person class. Click on Class Resources from the main menu of the class to view data about Wolfgang Palm.

Chapter 10. Using Named Queries

In Callimachus Named Queries are SPARQL queries that are created using the Named Query create interface. In this chapter you will learn how to use named queries.

10.1. Named query syntax

Callimachus Named Queries use a superset of the SPARQL 1.1 query syntax SELECT form.

As in SPARQL, any prefixes used in the Named Query must be declared using a PREFIX clause. When evaluating, the base IRI of the query is the URI of the Named Query.

10.1.1. Sample named query
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT ?nameX ?nameY ?nickY
WHERE
  { ?x foaf:knows ?y ;
       foaf:name ?nameX .
    ?y foaf:name ?nameY .
    OPTIONAL { ?y foaf:nick ?nickY }
  }
OFFSET ${ ($pageNumber - 1) * $pageSize } LIMIT ${ $pageSize }

10.2. Parameters for named queries

Callimachus supports four ways of passing parameters to named queries: as wild parameters, relative pararmeters, lexical parameters, or expression parameters.

10.2.1. Wild parameters

Wild parameters use the SPARQL variable syntax with a prefix of '$', as shown in Example 1.

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?title {
  $doc a foaf:Document; dcterms:title ?title
}

Example 1: Named query that uses wild parameters

The value of the query parameters are any RDF term using the SPARQL term syntax. URIs are absolute or relative to the Named Query and wrapped in '<' and '>'. Literals maybe numeric or strings in double quotes and may include a language or datatype.

In Example 1, requests with the suffix ?results will return the title of all documents in the RDF store. This compares to requests with the suffix ?results&doc=%3Cdoc1%3E. These requests return document titles within the same namespace as the Named Query and a local part of "doc1".

Note: The %3C and %3E are percent encodings of '<' and '>'.

10.2.2. Relative parameters

Relative parameters must be bound and can only be a relative or absolute URI (i.e. not a literal value), as shown in Example 2.

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?title {
  <$doc> a foaf:Document; dcterms:title ?title
}

Example 2. Named query that uses relative parameters

In Example 2, requests with the suffix ?results will not return any results. However requests with the suffix ?results&doc=doc1 will retrieve the title of the <doc1> resource. The value of the query parameters are any relative or absolute URI (without angle brackets).

10.2.3. Lexical parameters

Lexical parameters must be bound and only be bound to literals, as shown in Example 3.

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?doc {
  ?doc a foaf:Document; dcterms:title "$title"@en
}

Example 3. Named query that uses lexical parameters

The datatype and language (if present) must be present in the Named Query itself and cannot be provided using lexical query parameters. As with relative parameters, a request using the suffix ?results will not return any results. However a request with the suffix ?results&title=Linking+Enterprise+Data will result in the document URI with an English title of "Linking enterprise Data"@en (if present in the RDF store). The value of the query parameters are any lexical value.

10.2.4. Expression parameters

Expression parameters are used to calculate the OFFSET and LIMIT for results, as shown in Example 4.

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?title {
  ?doc a foaf:Document; dcterms:title ?title
} OFFSET ${ ($pageNumber - 1) * $pageSize } LIMIT ${ $pageSize }

Example 4. Named query that uses expression parameters

Unlike other parameters, expression parameters must only have exactly one value per request. Expression parameters may contain any SPARQL expression of other (non-expression) parameters within a '${' and '}'. In this example, a request with the suffix ?results&pageNumber=1&pageSize=30 will result in a SPARQL with an OFFSET 0 and LIMIT 30.

Expression parameters have no name and do not appear in the query parameter. However, the parameters within an expression must be present in the query parameter.

10.3. Results from named queries

The results from named queries can be accessed using JavaScript in the following three ways.

10.3.1. Retrieving the results formatted as SPARQL results XML

To retrieve the results, send a GET request to the Named Query URI with the suffix ?results. This will return the tuple binding results in an XML document.

10.3.2. Retrieving the results formatted in HTML, CSV, TSV, or JSON

To retrieve the result in HTML, CSV, TSV, or JSON use the suffix: ?results&tqx=out:html , ?results&tqx=out:csv , ?results&tqx=out:tsv-excel, or ?results&tqx=out:table respectively.

All result formats comply with the GoogleChartToolsDatasourceProtocol.

10.3.3. Accessing the results from a Web browser

To access the result from a Web browser, use the google Query library to parse the result, as shown below.

  <script src="https://www.google.com/jsapi" type="text/javascript"> </script>
  <script type="text/javascript">
    // <![CDATA[
    google.load("visualization", "1.0", {callback:function() {
      new google.visualization.Query("organizations-by-country.rq?results").send(function(result){
        var select = $('#my-select');
        var data = result.getDataTable();
        var rows = data.getNumberOfRows();
        for (var i=0; i<rows; i++) {
          var option = $('<option/>');
          option.text(data.getValue(i, 0));
          select.append(option);
        }
      });
    }});
    // ]]>
  </script>

Take notice that this code relies on jQuery placing the results into an HTML element with an ID of "my-select". This ID can be whatever you want, but it must be present in the HTML for the jQuery to succeed. In this case, the HTML element that is necessary is:

<div id="my-select"> 
  ... 
</div>

10.4. View Templates for Named Queries

Callimachus supports the ability to assign a view template to a specific name query. It is quite a simple process and only requires two separate files: a query and a template. It does not matter which is created first but the two are dependent on each other, and thus both must exist to function correctly.

10.4.1. The Query

Queries that use view templates are not structured differently than queries that do not. The only difference is in a comment at the top of the query. In order to add a view template to a query, we add a comment with @view to include the relative filepath and name of the template we wish to apply.

#
# @Cache-Control: max-age=3600
# @view concept-search.xhtml
#
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>

SELECT ?concept {
  ?concept a skos:Concept; skos:prefLabel ?label
  FILTER regex(?label, "$q", "i")
} ORDER BY ?concept LIMIT 10

Example 1: Named query that uses a view template

Be aware that once you have added a view template to a named query, when you hit the View tab it will no longer appear as a table of query results. It will now be rendered through the template. You can still edit the query itself by simply clicking the Edit tab.

10.4.2. The Template

The template behaves as any other Callimachus template does, relying on RDFa markup to "traverse" the graph and display the apporpriate data. For more information about templates see the full documentation. As you can see below by adding just a few attributes to existing html tags we are able to display the results of the query as if the query was  occuring within that page.

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#">
<head>
    <title>Concept Search Results</title>
    <link rel="edit-form" href="?edit" />
    <link rel="comments" href="?discussion" />
    <link rel="describedby" href="?describe" />
    <link rel="version-history" href="?history" />
</head>
<body>
    <h1>Concept Search Results</h1>
    <ul>
        <li resource="?concept">
            <a href="{?concept}">{skos:prefLabel}</a>
            <pre property="skos:definition" />
        </li>
    </ul>
</body>
</html>

Example 2. View template for named query

Above we have added a few crucial pieces of information to the existing HTML tags. Since this template is now associated with a named query (completed in the step above) the template is able to reference the variable in the SELECT clause of the query. As you can see, the resource attribute of the <li> is now connected to ?concept, the variable that was returned in the results of the named query. From here we are able to pick and choose the data we want to display and how to display it. An HTTP request to "concept-search.rq?view&q=sun" will include any concept with the regex "sun" in the pref label.


Chapter 11. Using XProc

11.1. Callimachus Pipeline

11.1.1. Overview

Callimachus supports XProc pipeline documents as first-class Pipeline objects. It uses the Calabash XProc implementation for this purpose. Pipeline objects can be created in a folder (selecting the 'Pipeline' item from the create menu) and given content that conforms with the XProc: An XML Pipeline Language specification.

Then, POST and GET requests can be dispatched to them as web resource in order to invoke the pipeline and return the XML document from the result primary output port as the body of the response. The query component of the request URI can be used to pass values in as options into the pipeline.

The input document for the source port (declared as a document input of the pipeline) can be specified for the instantiation of the pipeline.

11.1.2. HTTP Methods

XProc pipelines can be invoked by POST and GET requests using their URL as the request URL along with request in the query component. We will refer to this as the result URL. For example:

..pipeline..URL..?results

Additional key / value pairs can be used in the query component to pass options into the XProc pipeline. This is discussed in the next section.

Sending an HTTP GET request to the result URL will trigger an instantiation of the pipeline without providing an input document in the source port. The pipeline would have to take care of that by either embedding the input document into the pipeline or requesting it using the p:load step, for example:

<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline xmlns:p="http://www.w3.org/ns/xproc" version="1.0" name="pipeline">

    <p:load href="my-query.rq?results" />

    <p:xslt> 
        <p:input port="stylesheet">
            <p:document href="my-transform.xsl" />      
        </p:input>
    </p:xslt>

</p:pipeline>

Note the URL used by the p:load step can identify a Callimachus web resource (an XML document), facilitating the use of Callimachus web resources as XProc pipelines and inputs to such pipelines.

Sending an HTTP POST request to the result URL will trigger an instantiation of the pipeline, passing the request body as an input document for the source port.

11.1.3. Pipeline Options

Any query parameters appended to the result URL, as additional query components, will be passed into the pipeline as options name/value string pairs, if the pipeline declares the options.

So a POST request to:

..pipeline..URL..?results&foo=bar

To the following pipeline:

<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline xmlns:p="http://www.w3.org/ns/xproc" version="1.0" name="pipeline">

    <p:option name="foo" required="true" />

    <p:load>
        <p:with-option name="href" select="concat('my-query.rq?results&amp;foo=', encode-for-uri($foo))"/>
    </p:load>

    <p:xslt> 
        <p:input port="stylesheet">
            <p:document href="my-transform.xsl" />      
        </p:input>
    </p:xslt>

</p:pipeline>

Will pass the foo option as a query parameter to the named query my-query.rq and use the result as the source for the xsl transformation.

I.e., the options are passed into the pipeline document as in-scope bindings options.

11.2. Overview

Callimachus 0.18 introduced an XProc implementation. XProc is an XML pipeline language and can be used to script the transformation of content such as SPARQL query results or XML data gathered from the Web. XProc is a W3C Recommendation.This page provides examples of XProc pipelines to perform common tasks.

The XProc Web site provides links to other materials, including a tutorial and examples. The XProc specification provides the complete details of the XProc syntax and should be consulted before using XProc for complex tasks. The purpose of this page is to ease your transition into XProc usage by providing a short tutorial.

Callimachus uses XProc as an extension mechanism. As of Callimachus 0.18, one can create PURLs that resolve to XProc pipelines. XProc replaces the Action with no side effects pattern that used an executable Turtle file to orchestrate the transformation of SPARQL query results to other formats via XSLT.

An XProc pipeline works similarly to other pipeline implementations: A series of "steps" are defined and the order of processing is step-by-step. Consider a Unix pipeline as an analogy:

$ cat README.txt | grep Callimachus > callimachus-refs.txt

That Unix pipeline consists of two steps (the 'cat' command and the 'grep' command. The first step echoes the contents of the file README.txt, which is passed to the 'grep' command. The 'grep' command outputs only those lines containing the word 'Callimachus'. Finally, the results are put onto the process' STDOUT and thus to a file. An XProc pipeline works in a similar manner. A number of steps are defined, the output of each becomes the input to the next. The equivalent of STDIN in XProc is called source and has zero or more XML documents. The equivalent of STDOUT in XProc is called result and has zero or more XML documents.

11.3. "Hello, World" in XProc 

XProc pipelines may be created in Callimachus just like any other type of resource. Navigate to any Callimachus folder where you have write access and select Pipeline from the menu.

You will be redirected to an editor with the default pipeline definition pre-populated in it:

To create your pipeline, simply type (or copy) your XProc definition into the editor. A simple XProc pipeline that outputs "Hello, World" looks like this:

<?xml version="1.0" encoding="UTF-8" ?> 
  
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library"> 
  
<p:serialization port="result" media-type="text/plain" method="text" /> 
  
<p:identity> 
  <p:input port="source"> 
    <p:inline> 
      <c:data content-type="text/plain">Hello, World</c:data> 
    </p:inline> 
  </p:input> 
</p:identity> 

</p:pipeline>

The output of this pipeline may be retrieved by resolving its URL with the suffix "?results" appended.

If you saved the above pipeline at the URL http://example.com/test/hello-world.xpl then you can get the pipeline itself at that URL, a human-readable HTML page containing the pipeline at http://example.com/test/hello-world.xpl?view and the results of the pipeline at http://example.com/test/hello-world.xpl?results, like this:

$ curl http://example.com/test/hello-world.xpl 
<?xml version="1.0" encoding="UTF-8" ?> 
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library"> 

<p:serialization port="result" media-type="text/plain" method="text" /> 

<p:identity> 
  <p:input port="source"> 
    <p:inline> 
      <c:data content-type="text/plain">Hello, World</c:data> 
    </p:inline> 
  </p:input> 
</p:identity> 

$ curl http://example.com/test/hello-world.xpl?results 

                     Hello, World

You might be thinking, "Wow! That's typical XML! Very verbose to do so little." We hope to convince you that XProx is an excellent way for us to extend Callimachus into new areas, such as gathering, transforming and rendering data from anywhere on the Web.

In the "Hello, World" example, the serialization tag sets the MIME type of the result. If this tag is not present, XProc defaults to a MIME type of "application/xml" and a method of "xml".

The p:identity tag is used to echo any defined input to the output. In this case, we specified a literal string and asked that it be put to the output.

We could do something similar by getting a resource from the Web and putting it to the output. It would be more interesting to get two resources from the Web and combine them. The following section gets two Atom feeds from blogs, combines them and creates a new Atom feed of the results.

11.4. Create an RSS feed from two named Atom feeds

This example uses XSLT to convert each input feed from Atom format to RSS format, gets their entries and places the entries into an RSS template. XProc p:document tags are used to read Atom feeds from blog sites and then they are converted using xslt to RSS using p:xslt steps. Lastly, an p:insert tag is used to insert the items from the produced channels into the empty rss channel.

<?xml version="1.0" encoding="UTF-8" ?> 
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library"> 

<p:serialization port="result" media-type="application/rss+xml" method="xml" /> 

<p:xslt name="prototypo-rss"> 
  <p:input port="source"> 
    <p:document href="http://prototypo.blogspot.com/feeds/posts/default" /> 
  </p:input> 
  <p:input port="stylesheet"> 
    <p:document href="http://atom.geekhood.net/atom2rss.xsl" /> 
  </p:input> 
</p:xslt> 

<p:xslt name="jamesrdf-rss"> 
  <p:input port="source"> 
    <p:document href="http://jamesrdf.blogspot.com/feeds/posts/default" /> 
  </p:input> 
  <p:input port="stylesheet"> 
    <p:document href="http://atom.geekhood.net/atom2rss.xsl" /> 
  </p:input> 
</p:xslt> 

<p:insert match="/rss/channel" position="last-child"> 
  <p:input port="source"> 
    <p:inline> 
      <rss version="2.0"> 
        <channel> 
          <title>RSS Title</title> 
          <description>This is an example of an RSS feed</description> 
          <link>http://www.someexamplerssdomain.com/main.html</link> 
          <lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate> 
          <pubDate>Mon, 06 Sep 2009 16:45:00 +0000 </pubDate> 
          <ttl>1800</ttl> 
        </channel> 
      </rss> 
    </p:inline> 
  </p:input> 
  <p:input port="insertion" select="/rss/channel/item"> 
    <p:pipe step="prototypo-rss" port="result" /> 
    <p:pipe step="jamesrdf-rss" port="result" /> 
  </p:input> 
</p:insert>

</p:pipeline>

11.5. Rendering RDF from Pipeline into HTML using Callimachus Templates

<?xml version="1.0" encoding="UTF-8" ?> 
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library" 
      xmlns:calli="http://callimachusproject.org/rdf/2009/framework#"> 

<p:serialization port="result" media-type="text/html" method="html" doctype-system="about:legacy-compat" /> 

<p:import href="/callimachus/library.xpl" /> 

<calli:render-html> 
  <p:input port="source"> 
    <p:document href="http://localhost:8080/moon?describe" /> 
    <p:document href="http://localhost:8080/sun?describe" /> 
  </p:input> 
  <p:input port="query"> 
    <p:inline> 
      <c:data content-type="application/sparql-query">
        <![CDATA[
          SELECT ?this { BIND (<$target> AS ?this) }
        ]]>
      </c:data> 
    </p:inline> 
  </p:input> 
  <p:with-param name="target" select="'moon'" /> 
  <p:input port="template"> 
    <p:document href="/callimachus/templates/concept-view.xhtml" /> 
  </p:input> 
</calli:render-html> 

</p:pipeline>

11.6. Displaying Named Query Results on OpenStreetMap via Pipeline

This example will demonstrate a few core pieces of functionality strung together to create an interesting and useful application. It will walk through the following steps:

  1. Creating a named query
  2. Using that named query as the input source of an XML Processing (XProc) pipeline
  3. Assigning a Perisistent URL (PURL) to the results of that XProc pipeline [Optional]
  4. Generating an OpenStreetMap display from a call to that PURL

Specifically, this example will generate a map of all the Nuclear Maps in the United States, plot those points on a map, and allow the user to click on any of those facilities and learn more about a facility.

11.6.1. 1. Create a named query

This query must return data in a way that is compliant with use by OpenStreetMap. Here is what the query looks like in Callimachus:

As you can see above, the query specificly selects the URL (?link), name (?title), description (?description, which is always the same), and latitute (?lat) and longitude (?long) of the facility. This query generates a SPARQL Protocol and RDF Query Language (SPARQL) XML result set which must now be transformed into Geographically Encoded Objects for Rich Site Summary (GeoRSS) via an XProc pipeline.

11.6.2. 2. Use that named query as the input source of an XProc pipeline

To generate GeoRSS from SPARQL XML results, use an XProc pipeline with the appropriate EXtensible Stylesheet Language (XSL) stylesheet.

<?xml version="1.0" encoding="UTF-8" ?> 
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library"> 

<p:serialization port="result" media-type="application/rss+xml" method="xml" /> 

<p:load href="nukemap.rq?results" /> 

<p:xslt name="nukemap"> 
  <p:input port="stylesheet"> 
    <p:document href="sparql-georss.xsl" /> 
  </p:input> 
</p:xslt>

</p:pipeline>

There a small number of tags here each with their own distinct purpose. The serialization tag (<p:serialization>) uses the port attribute (port="result") to declare that the results of the pipeline will be a form of RSS+XML (media-type="application/rss+xml"). The load tag (<p:load>) executes the named query created in step 1 and returns the results to the pipeline.

XSL Transformation is a language for transforming one form of an XML document into another form of XML. In this case we'll be going from SPARQL XML to GeoRSS.  The XSLT tag (<p:xslt>) declares the start of the XSLT and names it "nukemap". Inside that transformation, the input tag (<p:input>) uses the port attribute (port="stylesheet") to specify the stylesheet that will be applied to the results of the named query. The document tag (<p:document>) specifies the URL of the stylesheet to be used (href="sparql-georss.xsl") which in this case is located in the same directory as the pipeline.

11.6.3. 3. Assign a PURL to the results of that XProc pipeline [Optional]

To enable the ability to set caching control, as well as move or edit the XProc pipeline without having to change the link, it would be wise to assign a PURL to the results of the pipeline. However, if you are simplying putting together a prototype, or do not anticipate relocating your resource, a PURL is entirely optional. The map can call the URL of the XProc pipeline without the intermediary PURL. However, if you were to create a PURL it would look like this:

The PURL is given a name (nukemap) and a type of 200 which means that the results of this PURL will be copied from their location. Content location specifies where the PURL should look for content, which in this case we want to be the results of our XProc pipeline (nukemap.xpl?results). Lastly, we can set cache control on the PURL. This is a way of improving efficiency by not having to constantly fetch new results if a number of requests are made in quick succession. In this case we are specifying that if multiple requests are made over the course of 3,600 seconds, rather than following the PURL and getting new results each time, simply grab results from cache. 

11.6.4. 4. Generate OpenStreetMap display from a PURL

The last step of this example is to tie it all together. At this point there is now a single PURL (nukemap) that can be accessed which will return the results of the named query in GeoRSS format. Now that PURL needs to be worked into the OpenStreetMap code as the input for generating the map itself. If you are unfamiliar with OpenStreetMaps (OSM) at a high level, it would be beneficial to read some of their basic documentation and examples before diving into this code.

<?xml-stylesheet type="text/xsl" href="/callimachus/template.xsl"?> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <title>U.S. Nuclear Plants</title> 
  <script src="//www.openlayers.org/api/OpenLayers.js"></script> 
  <script> 
  // <![CDATA[ 
    jQuery(function() { 
      var map = new OpenLayers.Map("mapdiv"); 
      map.addLayer(new OpenLayers.Layer.OSM()); 
      
      map.addLayer(new OpenLayers.Layer.GeoRSS("My Points", "nukemap", { 
        tileOptions: { crossOriginKeyword: null } 
      })); 

      map.setCenter(new OpenLayers.LonLat("-98.0", "38.0").transform( 
          new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984 
          map.getProjectionObject() // to Spherical Mercator Projection 
        ), 4 // Zoom level 
      ); 
    }); 
  // ]]> 
  </script> 

  <style> 
    .leaflet-map-pane img, /* OpenStreetMap */ 
    .olMapViewport img { /* general OpenLayers maps */ 
      max-width: none; 
     } 
  </style> 

</head> 
<body> 
  <h1>U.S. Nuclear Plants</h1> 
  <table width="100%"> 
    <tbody> 
      <tr> 
        <td style="width:100%">
          <div id="mapdiv" style="height:800px"></div>
        </td> 
      </tr> 
    </tbody> 
  </table> 
</body> 
</html>

There is really one important line that makes this code different from a standard implementation of OSM and that line is:

map.addLayer(new OpenLayers.Layer.GeoRSS("My Points", "nukemap", { tileOptions: { crossOriginKeyword: null } }));

which is where we call the nukemap PURL as the source of our GeoRSS. With the infrastructure in place it is a simple adjustment to standard code that allows for a simple collection of data files to become an interesting visualization of nuclear plants in the United States.

NB: Twitter Bootstrap (which Callimachus' default theme is based on) has a default setting that intereferes with OpenStreetMap. Luckily this can be easily overcome with a bit of CSS at the top of the page. The code is below.

<style> 
  .leaflet-map-pane img, /* OpenStreetMap */ 
  .olMapViewport img { /* general OpenLayers maps */ 
    max-width: none; 
  } 
</style>

11.7. Passing Parameters into a Pipeline for Use in a Named Query

Passing parameters into an XProc Pipeline is structurally very similar to passing them into Named Queries. The URI is still query.rq?results&variableName=variable.  However, once the paramater has been successfully passed into the pipeline the pipeline must interpret it correctly depending on where it will be used. It starts the same way, with the <p:option> tag. The name attribute assigns the paramter a name while the required attribute states whether or not the parameter is necessary for the pipeline to execute.

From there, if the intent is to use the parameter in a named query, the query string must be built up inside the <p:load> tag in order for it to be passed correctly to the named query. In this example the <p:with-option> tag two attributes: the name attribute which defines it as a link (href) and the select attribute which defines where to look for that link. Inisde the select attribute is where the query string must be constructed using the concat function. The string is simply the file name for the query (nuclear-chemical-amount.rq), the suffix that returns results in SPARQL/XML (?results) and the URI-encoded variable name and string (&amp;substance='encode-for-uri($substance)). $substance here refers to the option that was defined in the previous step.

After this step, the SPARQL/XML that is returned can be passed to any other necessary steps just as it could be in a pipeline that does not use parameters.

<?xml version="1.0" encoding="UTF-8" ?>
<p:pipeline version="1.0" 
      xmlns:p="http://www.w3.org/ns/xproc" 
      xmlns:c="http://www.w3.org/ns/xproc-step" 
      xmlns:l="http://xproc.org/library"> 

<p:serialization port="result" media-type="application/json" method="text" /> 

<p:option name="substance" required="true" /> 

<p:load> 
    <p:with-option 
        name="href" 
        select="concat( 
            'nuclear-chemical-amount.rq?results&amp;substance=', 
            encode-for-uri($substance) 
        )" 
    /> 
</p:load> 

<p:xslt name="piechart">
    <p:input port="stylesheet">
        <p:document href="../coordinate-points-d3-json-sparql.xsl" /> 
    </p:input> 
    <p:with-param name="x-coordinate-variable" select="'name'" /> 
    <p:with-param name="y-coordinate-variable" select="'total'" /> 
</p:xslt> 

</p:pipeline>

Chapter 12. Some Best Practices to Follow

Here are four best practices to follow when developing Callimachus applications.

12.1. Handling multiple languages

12.1.1. Overview

Linked data applications are particularly well-suited for multilingual data portals. Below are three multilingual templates from the Callimachus Meeting Notes Tutorial which have been modified to show a best practice for managing multilingual data.

12.1.2. journal-create
Description

When a new Journal is created the jQuery function highlighted below sets the lang attribute of the comment field to the language of the user’s browser.

Source Code
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/callimachus/template.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<head>
    <title>New Journal / Nouvelle Revue</title>
    <style type="text/css">
        .fr :lang(en) { display: none; }
        .en :lang(fr) { display: none; }
    </style>
    <script type="text/javascript">
    (function($){
        var language = window.navigator.language || window.navigator.userLanguage;
        var lang = language.toLowerCase().replace(/-.*/,'');
        document.documentElement.className += ' ' + lang;
        jQuery(function($) {
            $('#comment').attr('lang', lang); 
        });
    })(jQuery);
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1 lang="en">New journal</h1>
            <h1 lang="fr">Nouvelle revue</h1>
        </div>
        <form method="POST" action="" enctype="application/rdf+xml" typeof="" onsubmit="return calli.saveResourceAs(event, calli.slugify($('#label').val()))">
            <div class="row">
                <div class="col-sm-4">
                    <div class="form-group">
                        <label for="label" lang="en">Label</label>
                        <label for="label" lang="fr">Étiquette</label>
                        <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required" autofocus="autofocus" />
                    </div>
                    <div class="form-group">
                        <label for="comment" lang="en">Comment</label>
                        <label for="comment" lang="fr">Commentaire</label>
                        <textarea id="comment" class="form-control">{rdfs:comment}</textarea>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group">
                        <button type="submit" class="btn btn-success" lang="en">Create</button>
                        <button type="submit" class="btn btn-success" lang="fr">Créer</button>
                    </div>
                </div>
            </div>
        </form>
    </div>
</body>
</html>

12.1.3. journal-edit
Description

The jQuery function loops through each value of the language attribute and hides comments which are not in the default language for the browser. If there is no comments field it adds one.

Source Code
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/callimachus/template.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<head>
    <title resource="?this">{rdfs:label}</title>
    <style type="text/css">
        .fr :lang(en) { display: none; }
        .en :lang(fr) { display: none; }
    </style>
    <script type="text/javascript">
    (function($){
        var language = window.navigator.language || window.navigator.userLanguage;
        var lang = language.toLowerCase().replace(/-.*/,'');
        document.documentElement.className += ' ' + lang;
        jQuery(function($) {
            if (!$('#comments textarea:visible').length) {
                calli.addResource({}, '#comments');
            }
        });
       window.changeLangIfModified = function(input) {
           if(input.value != $(input).text()){
               $(input).attr('lang', lang);
               $(input).text(input.value);
           }
       };
    })(jQuery);
    </script>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <form method="POST" action="" enctype="application/sparql-update" resource="?this">
            <div class="row">
                <div class="col-sm-4">
                    <div class="form-group">
                        <label for="label" lang="en">Label</label>
                        <label for="label" lang="fr">Étiquette</label>
                        <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required" />
                    </div>
                    <div class="form-group">
                        <label for="comment" lang="en">Comment</label>
                        <label for="comment" lang="fr">Commentaire</label>
                        <div id="comments">
                            <textarea id="comment" class="form-control" property="rdfs:comment"
                                onchange="window.changeLangIfModified(this)"></textarea>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary" lang="en">Save</button>
                        <button type="submit" class="btn btn-primary" lang="fr">Enregistrer</button>
                        <button type="button" onclick="window.location.replace('?view')" class="btn btn-default" lang="en">Cancel</button>
                        <button type="button" onclick="window.location.replace('?view')" class="btn btn-default" lang="fr">Annuler</button>
                        <button type="button" onclick="calli.deleteResource(event)" class="btn btn-danger" lang="en">Delete</button>
                        <button type="button" onclick="calli.deleteResource(event)" class="btn btn-danger" lang="fr">Supprimer</button>
                    </div>
                </div>
            </div>
        </form>
    </div>
</body>
</html>
12.1.4. journal-view
Description

The jQuery function loops through each value of the language attribute and hides comments which are not in the default language for the browser.

Source Code
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/callimachus/template.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{rdfs:label}</title>
    <style type="text/css">
        .fr :lang(en) { display: none; }
        .en :lang(fr) { display: none; }
    </style>
    <script type="text/javascript">
    (function($){
        var language = window.navigator.language || window.navigator.userLanguage;
        var lang = language.toLowerCase().replace(/-.*/,'');
        document.documentElement.className += ' ' + lang;
    })(jQuery);
    </script>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <div class="row">
            <div class="col-sm-8">
                <pre class="wiki" property="rdfs:comment" />
                <ul>
                    <li rev="dcterms:isPartOf" resource="?note">
                        <a href="?note">
                            <time property="dcterms:date" />
                        </a>
                    </li>
                </ul>
            </div>
            <div class="col-sm-4">
                <aside class="well well-sm">
                    <p class="lead">
                        <a resource="Note" href="Note?create" onclick="href='?create='+encodeURIComponent(getAttribute('resource'))" lang="en">Create a new note</a>
                        <a resource="Note" href="Note?create" onclick="href='?create='+encodeURIComponent(getAttribute('resource'))" lang="fr">Créer une nouvelle Note</a>
                    </p>
                </aside>
            </div>
        </div>
    </div>
</body>
</html>

12.2. Naming Callimachus resources

12.2.1. Naming Conventions

Developers should follow these conventions when naming Callimachus resources.

Identifier

Convention

Case

Example

Namespace prefix

two to six letters

lower

sig

Class

noun

PascalCase

AppDomain

Message class

verb

PascalCase

GetAppResult

Datatype property

role noun

camelCase

typeName

Time property

verb

camelCase

completedOn

Object property

verb

camelCase

hasParent

Message property

noun

camelCase

inputStream

Query parameter

noun

lower case

authordetails

File or directory

- separates

lower case

event-create.xhtml

Singleton resource

_ separates

lower case

main_resource

Other resource

+ separates

lower case

my+resource

Namespace for things

/ ends and separates

lower case

/tools/

Sub-resource

# separates parent resource

lower case

my+resource#rel0

Nested resource

/ separates parent resource

lower case

parent/child

12.2.2. Naming guidelines
  1. Use alphanumeric characters for identifiers (unless convention otherwise indicates).

  2. Keep identifiers simple and descriptive.

  3. Avoid acronyms and abbreviations.

  4. Choose easily readable identifier names.

  5. Favor readability over brevity.

  6. Do not use Hungarian notation, where the variable type can be seen from its name.

  7. Avoid using identifiers that conflict with keywords of widely used programming languages.

  8. Use slash URI identifiers for things and hash URI identifiers for classes and properties.

12.3. Guidelines for page layout

12.3.1. Purpose

Apply these guidelines when designing your forms and pages in Callimachus.

UI Element Function
Page links area All links that are specific to the content in the page should appear on the right side of the screen in the sidebar.
Definitions area Definitions of terms used in the page or instructions on how to fill in forms should be given on the right in the sidebar, below the page links area.These instructions should be visually distinct from the page links area.
Page heading All pages should include a page heading.
Form fields Form fields should have their labels above the field.
Buttons The primary form buttons should be shown before the secondary buttons, and should also be visually different.

The sidebar should be a <div id="sidebar">...</div> with exactly one attribute: id="sidebar". No other attributes should be present. The sidebar may contain <aside></aside> elements, which may contains <h3></h3> and <p></p> or other block elements. The sidebar should be placed after the page heading. The page heading should either be a single <h1> element or an <hgroup> element with nested heading elements.

Form fields and buttons should use bootstrap's CSS convesions.

12.4. Using timestamps to control state transitions

12.4.1. Intent

To define a view of a single workflow task in a long-running process. The application data is represented as RDF data and the resource is an instance of a class that is required to be presented to the user. A typical state-change is represented as the monotonically increasing assertion of time-stamps. This helps to avoid the possibility of inconsistent states and removes the need for an RDF deletion.

12.4.2. Motivation

Applications often need to transition through a series of states, performing one significant task after another, and indicating to the user which tasks have been completed and what task is next. For example, an application may transition through state A, B, C and D. In a non-monotonic programming environment such as Java, one might use a state variable to indicate the current state, and (non-monotonically) modify this variable as the state changes:

currentState = S1;   // Initial state
  [ Perform some task T1 ]
currentState = S2;
  [ Perform another task T2 ]
currentState = S3;
  [ Perform yet another task T3 ]
currentState = S4;

However, if the state is being stored in RDF, changing the state this way is not so convenient, because it means that a /:currentState/ property must be continually deleted and re-asserted:

INSERT DATA { :app :currentState :S1 }   # Initial state
## Perform some task T1 ##
DELETE WHERE { :app :currentState ?s }
INSERT DATA { :app :currentState :S2 }
## Perform another task T2 ##
DELETE WHERE { :app :currentState ?s }
INSERT DATA { :app :currentState :S3 }
## Perform another task T3 ##
DELETE WHERE { :app :currentState ?s }
INSERT DATA { :app :currentState :S4 }

Such timestamps can also be useful for display to the user or for logging progress.

This style of programming also meshes nicely with the way state transitions are handled in the REST programming style. Several years ago Paul Prescod posted a nice explanation of this to a mailing list. (If anyone can provide a link, please do so.) In lieu of that, he has a pretty good description here: http://www.prescod.net/rest/state_transition.html .

12.4.3. Applicability

Consider using this pattern where the state of a resource must change over time and the resource is to be represented as RDF metadata.

12.4.4. Implementation

The view is constructed as a Callimachus XHTML template with RDFa properties. The subject of these properties, in both the head and body, is the task resource denoted by '?this'. Stateful properties are not displayed directly but are consumed by javascript and used to update the displayed status. The date-time of completion is shown using the standard datetime-locale layout. The status may change while the view page is open, so the javascript in the head reloads the page after a suitable interval.

12.4.5. Sample Code

The application metadata defines the relationship between the class of resource and the RDFa template:

@prefix eg: <http://example.com#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix calli: <http://callimachusproject.org/rdf/2009/framework#>.

eg:MyStatefulClass rdfs:subClassOf calli:Viewable ; calli:view <my-stateful-class.xhtml> .

The RDFa XHTML template my-stateful-class.xhtml contains:

 <?xml version="1.0" encoding="UTF-8" ?>
 <html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:eg="http://example.com#">
   <head>
      <title resource="?this">{rdfs:label}</title>
      <script>setTimeout(function() {document.location.reload(false)}, 300000)</script>
   </head>
   <body resource="?this">
     <h1 property="rdfs:label" />
     <div id="status">
       <span property="eg:startedT1At" content="?t1">
          Step 1 since <time class="abbreviated">{?t1}</time>
       </span>
       <span property="eg:startedT2At" content="?t2">
          Step 2 since <time class="abbreviated">{?t2}</time>
       </span>
       <span property="eg:startedT3At" content="?t3">
          Step 3 since <time class="abbreviated">{?t3}</time>
       </span>
       <span property="eg:finishedAt" content="?t4">
          Finished since <time class="abbreviated">{?t4}</time>
       </span>
     </div>

     <script type="text/javascript"><![CDATA[
        // only show the last status
        $("#status>span:not(:last)").remove();
     ]]></script>

   </body>
 </html>

Part IV. Callimachus REST API

Overview

Most Callimachus features may be accessed via REST API calls, which makes it easy to integrate Callimachus with other applications.

This chapter provides a summary of features available via REST, examples of usage, and programmatic guidance for developers.

A. About the Callimachus REST API

REpresentational State Transfer (REST) is a resource-oriented architectural style commonly used on the World Wide Web.

RESTful manipulation of resources in Callimachus requires some caveats. Readers may think of some kinds of content as "file" oriented, such as a HTML or plain text file, a JPEG image or a Javascript document, and other types of more conceptual content as "data" or "metadata", such as a user, group, menu definition or concept. Callimachus' REST API makes similar distinctions between Binary Large Object (BLOB) content and RDF content; however, the distinctions are not always as you might expect. How should we treat an RDF document that is uploaded to Callimachus, represented as a "file" in Callimachus' folder interface and yet whose contents are stored in an RDF database? Appendices B: BLOB Resource Types and C: RDF Resource Types list the various content types in Callimachus and associates them with the appropriate segments of the API. Please read carefully :)

Examples are provided that use a fictitious Callimachus authority (http://example.com:8080), fictitious URL paths, and fictitious parameters. This is intentional to encourage you to discover the correct URLs in accordance with this documentation. Any specific URL patterns we might otherwise document would be subject to change in future releases. Keep in mind that the service URLs may be on different hosts than the requested URI. You will thus not be able to copy-and-paste the examples directly into your browser; you will need to change the examples to match your environment. Examples requiring authentication show a username of "john"; your name may be different, so you will need to modify them as appropriate for your Callimachus username.

Examples show HTTP requests and responses, including relevant headers. Examples are also given that use the curl command-line utility, which is available for all major operating systems. See http://curl.haxx.se/ for details on curl.

NB: Callimachus includes (as of version 0.15) a script to clear its server-side cache. It is possible under some circumstances (e.g. removing triples from blank resources using the sparql endpoint) for the server-side cache to become stale. A systems administrator may run the command <installation directory>/bin/callimachus-reset.sh (or .bat) if server-side caching problems are suspected.

Authentication

Some functionality may only be accessed by authenticated users. Which functionality is restricted may be controlled by Callimachus' permissions system. However, by default the SPARQL endpoint and Create/Update/Delete functions are so restricted.

Callimachus uses HTTP Digest access authentication curl commands for authenticated commands require the --digest and --user parameters:

curl --digest --user john …

Correct URL Discovery

The URLs in the examples below are completely fictitious. HTTP does not transmit fragment identifiers, so the use of "#rel=..." in the examples below is mainly intended as a identifier of where the correct URL can be found or should be put. The correct URL itself can be discovered using an HTTP OPTIONS request or from an earlier response.


B. Browsing content

Callimachus supports iterative resource-oriented discovery of folder and "file" resources. Callimachus folders may be discovered and traversed using the REST API. Each folder may be introspected to discover its contents. Contents of folders may be either file-like resources (Binary Large Objects or BLOBs) or RDF resources (in RDF/XML or Turtle formats). BLOBs are stored in a BLOB store and RDF is stored in an RDF database. Folders are virtual constructs so you do not need to know what kind of resource you are dealing with; the interface abstracts one away from that information. The various resource types are described in Appendices.

General metadata regarding a Callimachus instance may be found by requesting an HTTP OPTIONS response from the top-level URL:

OPTIONS http://example.com:8080/ HTTP/1.1

The equivalent curl command is:

curl -i --digest --user john -X OPTIONS "http://example.com:8080/"

A typical response is shown below. Look specifically at the link: header:

HTTP/1.1 204 No Content
Age: 0
ETag: W/"274dde21-a038f4fe"
Last-Modified: Fri, 17 Feb 2012 15:24:45 GMT
Date: Fri, 17 Feb 2012 16:25:20 GMT
Cache-Control: public
access-control-allow-headers: Authorization,Host,Cache-Control,Location,Range,Accept,Accept-Charset,Accept-Encoding,
  Accept-Language,Content-Encoding,Content-Language,Content-Length,Content-Location,Content-MD5,Content-Type,
  If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since
access-control-allow-origin: *
allow: OPTIONS, TRACE, POST, GET, HEAD, DELETE, PUT
link: <http://example.com:8080/#rel=version-history>; rel="version-history"; type="application/atom+xml;q=0.5 text/html"
link: <http://example.com:8080/#rel=search>; rel="search"; type="application/opensearchdescription+xml"
link: <http://example.com:8080/#rel=describedby>; rel="describedby"; type="text/html"; title="RDF Describe"
link: <http://example.com:8080/#rel=contents>; rel="contents"; type="application/atom+xml;q=0.5"
link: <http://example.com:8080/#rel=..archive>; rel="http://callimachusproject.org/rdf/2009/framework#archive"
link: <http://example.com:8080/#rel=alternate&type=html>; rel="alternate"; type="text/html"
link: <http://example.com:8080/#rel=alternate&type=atom>; rel="alternate"; type="text/html application/atom+xml;q=0.5"
content-version: "274dde21"
vary: Accept,Access-Control-Request-Method
access-control-allow-methods: OPTIONS, TRACE, POST, GET, HEAD, DELETE, PUT
Accept-Ranges: bytes
Content-Length: 0
Server: Callimachus Server/Callimachus 0.15

To get a list of top-level resources, look for the Contents URL in the link: header with rel=”contents” (in this fictious case, http://example.com:8080/#rel=contents). Perform an HTTP GET on the URL using an Accept: header as noted in the type attribute (in this case, application/atom+xml), e.g.

GET http://example.com:8080/#rel=contents HTTP/1.1
Accept: application/atom+xml

The equivalent curl command is:

curl -H "Accept: application/atom+xml" "http://example.com:8080/#rel=contents"

Typical results will look like the following. Note that only the first one hundred resources are shown.

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:calli="http://callimachusproject.org/rdf/2009/framework#"
  xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:app="http://www.w3.org/2007/app">
        <id>http://example.com:8080/#rel=contents</id>
        <link href="http://example.com:8080/#rel=describedby" rel="describedby"/>
        <title>example.com:8080</title>
        <app:collection href="http://example.com:8080/#app:collection">
                <title>example.com:8080</title>
                <app:accept>text/plain</app:accept>
                <app:accept>application/rdf+xml</app:accept>
                <app:accept>text/turtle</app:accept>
                <app:accept>application/xhtml+xml</app:accept>
                <app:accept>application/font-woff</app:accept>
                <app:accept>application/sparql-query</app:accept>
                <app:accept>application/docbook+xml</app:accept>
                <app:accept>text/css</app:accept>
                <app:accept>text/xsl</app:accept>
                <app:accept>text/html</app:accept>
                <app:accept>image/gif</app:accept>
                <app:accept>image/vnd.microsoft.icon</app:accept>
                <app:accept>image/png</app:accept>
                <app:accept>image/svg+xml</app:accept>
                <app:accept>image/jpeg</app:accept>
                <app:accept>text/javascript</app:accept>
        </app:collection>
        <link href="http://example.com:8080/#rel=alternate&amp;type=atom" rel="alternate" type="application/atom+xml"/>
        <updated>2012-02-23T13:55:59.504Z</updated>
        <openSearch:totalResults>5</openSearch:totalResults>
        <link href="http://example.com:8080/#rel=search" rel="search" type="application/opensearchdescription+xml"/>
        <entry>
                <id>http://example.com:8080/.well-known/</id>
                <title>.well known</title>
                <updated>2012-02-17T15:02:22.556Z</updated>
                <icon>http://example.com:8080/callimachus/folder.png</icon>
                <link href="http://example.com:8080/auth/groups/users" rel="http://callimachusproject.org/rdf/2009/framework#reader" title="users"/>
                <link href="http://example.com:8080/auth/groups/staff" rel="http://callimachusproject.org/rdf/2009/framework#reader" title="staff"/>
                <link href="http://example.com:8080/auth/groups/admin" rel="http://callimachusproject.org/rdf/2009/framework#administrator" title="admin"/>
                <content src="http://example.com:8080/.well-known/"/>
                <link href="http://example.com:8080/.well-known/#rel=contents" rel="contents" type="application/atom+xml"/>
                <link href="http://example.com:8080/.well-known/#rel=..archive" rel="http://callimachusproject.org/rdf/2009/framework#archive" type="application/zip"/>
                <link href="http://example.com:8080/.well-known/#rel=alternate&amp;type=html" rel="alternate" type="text/html"/>
                <link href="http://example.com:8080/.well-known/#rel=describedby" rel="describedby"/>
                <link href="http://example.com:8080/.well-known/#rel=version-history" rel="version-history"/>
        </entry>
        <entry>
                <id>http://example.com:8080/callimachus/</id>
                <title>callimachus</title>
                <updated>2012-02-09T17:35:14.984Z</updated>
                <icon>http://example.com:8080/callimachus/folder.png</icon>
                <link href="http://example.com:8080/auth/groups/staff" rel="http://callimachusproject.org/rdf/2009/framework#reader" title="staff"/>
                <link href="http://example.com:8080/auth/groups/admin" rel="http://callimachusproject.org/rdf/2009/framework#administrator" title="admin"/>
                <content src="http://example.com:8080/callimachus/"/>
                <link href="http://example.com:8080/callimachus/#rel=contents" rel="contents" type="application/atom+xml"/>
                <link href="http://example.com:8080/callimachus/#rel=..archive" rel="http://callimachusproject.org/rdf/2009/framework#archive" type="application/zip"/>
                <link href="http://example.com:8080/callimachus/#rel=alternate&amp;type=html" rel="alternate" type="text/html"/>
                <link href="http://example.com:8080/callimachus/#rel=describedby" rel="describedby"/>
                <link href="http://example.com:8080/callimachus/#rel=version-history" rel="version-history"/>
        </entry>
        <entry>
                <id>http://example.com:8080/main-article.docbook</id>
                <title>main article</title>
                <updated>2012-02-06T01:27:09.545Z</updated>
                <icon>http://example.com:8080/callimachus/article.png</icon>
                <link href="http://example.com:8080/auth/groups/users" rel="http://callimachusproject.org/rdf/2009/framework#reader" title="users"/>
                <link href="http://example.com:8080/auth/groups/staff" rel="http://callimachusproject.org/rdf/2009/framework#editor" title="staff"/>
                <link href="http://example.com:8080/auth/groups/admin" rel="http://callimachusproject.org/rdf/2009/framework#administrator" title="admin"/>
                <link href="http://example.com:8080/main-article.docbook#rel=edit-media" rel="edit-media"/>
                <content src="http://example.com:8080/main-article.docbook" type="application/docbook+xml"/>
                <link href="http://example.com:8080/main-article.docbook#rel=alternate&amp;type=html" rel="alternate" type="text/html"/>
                <link href="http://example.com:8080/main-article.docbook#rel=describedby" rel="describedby"/>
                <link href="http://example.com:8080/main-article.docbook#rel=version-history" rel="version-history"/>
        </entry>
        <entry>
                <id>http://example.com:8080/sparql</id>
                <title>sparql</title>
                <contributor>
                        <name>James Leigh</name>
                        <uri>http://example.com:8080/user/james</uri>
                </contributor>
                <updated>2012-02-23T13:55:59.504Z</updated>
                <link href="http://example.com:8080/auth/groups/admin" rel="http://callimachusproject.org/rdf/2009/framework#administrator" title="admin"/>
                <content src="http://example.com:8080/sparql"/>
                <link href="http://example.com:8080/sparql#rel=alternate&amp;type=html" rel="alternate" type="text/html"/>
                <link href="http://example.com:8080/sparql#rel=describedby" rel="describedby"/>
                <link href="http://example.com:8080/sparql#rel=version-history" rel="version-history"/>
        </entry>
</feed>

The query above provided the contents and description of the top-level folder. The details may change in subsequent Callimachus releases. Resolving the URL of a folder will allow you to traverse the folder hierarchy.

Folders may be identified by the presence of an Atom feed with rel="contents" type="application/atom+xml" in a resource record. News readers may be used to track changes to Callimachus folders by subscribing to the alternate Atom feed (with rel="alternate" and type="application/atom+xml"), which will sort resources by last modified data. e.g.

<link href="http://example.com:8080/#rel=alternate&amp;type=atom" rel="alternate" type="application/atom+xml"/>


C. Bulk changes

The entire contents of Callimachus folders, including all BLOB and RDF resources, may be exported into a Callimachus Archive (CAR) file. A CAR file is a ZIP version 3 formatted file that contains Callimachus-specific metadata. Exporting a CAR file from a folder recursively creates an archive of that folder's contents (not the folder itself), including any subfolders.

Exportation of CAR files may be performed at runtime and may be used for "hot" backup of the contents of a Callimachus server. Please also note that exportation of large amounts of RDF content will increase server load and may best be scheduled during quiet usage periods.

Export

Performing an HTTP OPTIONS on a folder URL returns a link: header with rel=”...#archive”, a content type and the folder's Archive URL to be used to get an export of the folder's contents. Performing a GET on the Archive URL using an Accept: header as noted in the type attribute (generally application/zip) will download the folder's contents as a ZIP version 3 file containing Callimachus-specific content. This is called a Callimachus Archive (CAR) file.

To get an export of a folder called "/exportme/":

GET http://example.com:8080/exportme/#rel=..archive HTTP/1.1
Accept: application/zip
Authorization: Digest username="john", realm="http://example.com:8080/", ...

The equivalent curl command is:

curl --digest --user john -H "Accept: application/zip" "http://example.com:8080/exportme/#rel=..archive" > exportme.car

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 200 OK
Content-Disposition:  attachment;filename="test-example.com.car"
Content-Type:  application/zip
Server:  Callimachus Server/Callimachus 0.15

<Binary ZIP file content here>

NB: CAR files contain a folder's contents, including any subfolders and their contents. CAR files do not contain a top-level folder; a new folder must be first created when importing CAR files.

Import

CAR files do not contain a top-level folder and must thus be imported into an existing folder. Create a folder before importing a CAR into it. It is not recommended to import CAR files into the top-level folder due to the presence of folders and resources necessary to the operation of Callimachus.

Performing an HTTP OPTIONS on a folder URL returns a link: header with rel=”...#archive”, a content type and the folder's Archive URL to be used to import the folder's contents. Performing an HTTP PUT with a Content-Type: header of application/zip and a body of a CAR file will replace the contents of a folder.

To replace the contents of a folder called "/importme/" with the CAR file exportme.car, first make the folder "/importme/" and then:

PUT http://example.com:8080/importme/#rel=..archive HTTP/1.1
Content-Type: application/zip
Authorization: Digest username="john", realm="http://example.com:8080/", ...

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 204 No Content
Server: Callimachus Server/Callimachus 0.15
...

Delete

Performing an HTTP OPTIONS on a folder URL returns a link: header with rel=”...#archive”, a content type and the folder's Archive URL to be used to delete the folder's contents. Performing an HTTP DELETE will delete the entire contents of a folder recursively, but it will not delete the folder itself.

To delete the contents of a folder called /deleteme/:

DELETE http://example.com:8080/deleteme/#rel=..archive
Authorization: Digest username="john", realm="http://example.com:8080/", ...

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 204 No Content
Server: Callimachus Server/Callimachus 1.0
...


D. CRUD operations on BLOB content

Overview

This describes how to create, retrieve, update and delete BLOB content in Callimachus. 

BLOB files in Callimachus may include text or HTML pages, images, CSS stylesheets, etc. See Appendix for supported file types. However, bulk RDF instance data is also loaded via files and is thus treated as a BLOB for the purposes of this API, even though Callimachus will load it into an RDF database after ingestion.

To perform CRUD operations on BLOB content, first retrieve the Atom contents feed for the folder you want to operate in. See the section on Browsing Content above for details.

Operations

Create

Content may be created in a folder by issuing an HTTP POST to the folder's URL provided in the app:collection element of the folder's Atom contents feed. The body of the POST consists of the contents of the file you wish to upload. The HTTP header Content-Type: must be set appropriately for the type of file. Take note of the acceptable file types in Appendix. The file name you wish to create must be provided in the HTTP request header Slug:, whose value should be URI safe. See slug syntax.

The app:collection tag lists the MIME types that are acceptable to your Callimachus server.

For example, let's say you wanted to create an image called mylogo.png in the top-level folder. If the image file is located in a file of that name in the present working directory:

POST http://example.com:8080/#app:collection HTTP/1.1
Slug: mylogo.png
Content-Type: image/png
Authorization: Digest username="john", realm="http://example.com:8080/", ...

The equivalent curl command is:

curl --digest --user john --data-binary @mylogo.png -H "Content-Type: image/png" -H "Slug: mylogo.png" \
  "http://example.com:8080/#app:collection"

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 201 Created
Location:  http://example.com:8080/mylogo.png
Server:  Callimachus Server/Callimachus 0.15

NB: Callimachus Folders are RDF resources. See the section CRUD Operations on RDF Content for details on how to create folders.

Retrieve

Resources may be retrieved by performing an HTTP GET on the resource's edit media URL. A resource's edit media URL may be discovered by looking for the appropriate entry tag in the containing folder's Atom feed and then finding the link tag with rel="edit-media".

To retrieve the image created above:

GET http://example.com:8080/mylogo.png#rel=edit-media HTTP/1.1
Accept: image/png

The equivalent curl command is:

curl "http://example.com:8080/mylogo.png#rel=edit-media" > mylogo_copy.png

Update

Resources may be updated by performing an HTTP PUT on the resource's edit media URL. A resource's edit media URL may be discovered by looking for the appropriate entry tag in the containing folder's Atom feed and then finding the link tag with rel="edit-media".

The body of the PUT consists of the contents of the file you wish to upload. The HTTP header Content-Type: must be set appropriately for the type of the file.

To update the image created above:

PUT http://example.com:8080/mylogo.png#rel=edit-media HTTP/1.1
Content-Type: image/png
Authorization: Digest username="john", realm="http://example.com:8080/", ...

The equivalent curl command is:

curl --digest --user john --upload-file "mylogo.png" -H "Content-Type: image/png" \
  "http://example.com:8080/mylogo.png#rel=edit-media"

Normal HTTP response codes are used to indicate success or failure of the request.

Delete

Resources may be deleted by performing an HTTP DELETE on the resource's edit media URL. A resource's URL may be discovered by looking for the appropriate entry tag in the containing folder's Atom feed and then finding the link tag with rel="edit-media".

To delete the image created above:

DELETE http://example.com:8080/mylogo.png#rel=edit-media HTTP/1.1
Authorization: Digest username="john", realm="http://example.com:8080/", ...

The equivalent curl command is:

curl --digest --user john -I -X DELETE "http://example.com:8080/mylogo.png#rel=edit-media"

Normal HTTP response codes are used to indicate success or failure of the request. In this case, a successful delete is indicated by a 204 (No Content) response.


E. CRUD operations on RDF content

Overview

This describes how to create, retrieve, update and delete RDF content. 

Many resources in Callimachus are defined solely by RDF statements. These include folders, users, groups and concepts, but not bulk RDF instance data (see the section CRUD Operations on BLOB Content for those). See Appendix for supported RDF resource types.

Operations

Create

RDF resources are created by performing an HTTP POST to the URL enclosing folder's describedby URL with a Content-Type ofapplication/sparql-update and a body of a SPARQL INSERT DATA command. The response will include a Location: header with the URL of the resource created. The RDF data needs to include a supported rdf:type (see Appendix for details). This approach may only be used to insert one resource at a time (a single identified RDF Subject; additional resources may be inserted if they are blank nodes or hash URIs off of the identified Subject).

As a reminder, the enclosing folder's describedby URL may be found via its Atom feed (where the attribute rel=="describedby"). See the Browsing Content section for more details.

If you wanted to make a folder called "test" at the top level, first create a file with the appropriate SPARQL INSERT DATA query. We'll save this file with a name of "testcreate.ru":

BASE <http://example.com:8080/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX calli: <http://callimachusproject.org/rdf/2009/framework#>

INSERT DATA {
    <test/> a calli:Folder, </callimachus/Folder> ;
        rdfs:label "test" .
}

The HTTP POST looks like this:

POST http://example.com:8080/#rel=describedby HTTP/1.1
Content-Type: application/sparql-update
Authorization: Digest username="john", realm="http://example.com:8080/", ...

BASE <http://example.com:8080/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX calli: <http://callimachusproject.org/rdf/2009/framework#>

INSERT DATA {
    <test/> a calli:Folder, </callimachus/Folder> ;
        rdfs:label "test" .
}

The equivalent curl command is:

curl --digest --user john --data-binary @testcreate.ru -H "Content-Type: application/sparql-update" \
  "http://example.com:8080/#rel=describedby"

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 201 Created
Location:  http://example.com:8080/test/

Retrieve

Performing an HTTP OPTIONS on an RDF resource's created URI returns a link: header with rel=”decribedby” and the resource's DescribedBy URL. Performing an HTTP GET on the DescribedBy URL with an Accept: header of text/turtle or application/rdf+xml will return an RDF representation of the resource.

For a folder called "/test":

OPTIONS http://example.com:8080/test/ HTTP/1.1

The equivalent curl command is:

curl -I -X OPTIONS http://example.com:8080/test/

Results would look like:

HTTP/1.1 204 No Content
Link: <http://example.com:8080/test/#rel=version-history>; rel="version-history"; type="application/atom+xml;q=0.5 text/html"
Link: <http://example.com:8080/test/#rel=describedby>; rel="describedby"; type="text/html"; title="RDF Describe"
Link: <http://example.com:8080/test/#rel=contents>; rel="contents"; type="application/atom+xml;q=0.5"
Link: <http://example.com:8080/test/#rel=alternate&type=html>; rel="alternate"; type="text/html"
Link: <http://example.com:8080/test/#rel=..archive>; rel="http://callimachusproject.org/rdf/2009/framework#archive"
Link: <http://example.com:8080/test/#rel=alternate&type=atom>; rel="alternate"; type="text/html application/atom+xml;q=0.5"

Performing an HTTP GET on the DescribedBy URL returns the RDF. In this case, the Turtle format is requested. The result would be a Turtle document with the triples used in the Create section, above.

GET http://example.com:8080/test/#rel=describedby HTTP/1.1
Accept: text/turtle

The equivalent curl command is:

curl -H "Accept: text/turtle" "http://example.com:8080/test/#rel=describedby"

Normal HTTP response codes are used to indicate success or failure of the request.

Update

Performing an HTTP OPTIONS on an RDF resource's created URI returns a link: header with rel=”decribedby” and the resource's describedby URL. See also the discussion regarding HTTP 303 responses from a created URI in the Retrieve section, above. Performing an HTTP PATCH on the describedby URL with an Content-Type: header of application/sparql-update and a body of a SPARQL DELETE INSERT will update the resource.

NB: Updating a Folder, User, Group etc, has the potential to negatively impact internal Callimachus state: Be Careful!

To update the RDF definition of the "/test/" folder, first create a SPARQL DELETE INSERT query and put it into a file (in this case we'll call the file "testupdate.ru"). The contents of the file might look like this:

BASE <http://example.com:8080/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
​DELETE {
        </test/> rdfs:label ?label .
}
INSERT {
        </test/> rdfs:label "Test Folder" .
}
WHERE {
        </test/> rdfs:label ?label .
}

The HTTP command is then:

PATCH http://example.com:8080/test/#rel=describedby HTTP/1.1
Content-Type: application/sparql-update
Authorization: Digest username="john", realm="http://example.com:8080/", ...

BASE <http://example.com:8080/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

DELETE {
        </test/> rdfs:label ?label .
}
INSERT {
        </test/> rdfs:label "Test Folder" .
}
WHERE {
        </test/> rdfs:label ?label .
}

The equivalent curl command is:

curl --digest --user john -X PATCH --data-binary @testupdate.ru -H "Content-Type: application/sparql-update" \
  "http://example.com:8080/test/#rel=describedby"

Normal HTTP response codes are used to indicate success or failure of the request:

HTTP/1.1 204 No Content
Server: Callimachus Server/Callimachus 0.1
...

Delete

Performing an HTTP OPTIONS on an RDF resource's created URI returns a link: header with rel=”decribedby” and the resource's describedby URL. See also the discussion regarding HTTP 303 responses from a created URI in the Retrieve section, above. Performing an HTTP DELETE on the DescribedBy URL will delete the resource.

To delete the "/test/" folder:

DELETE http://example.com:8080/test/#rel=describedby HTTP/1.1
Authorization: Digest username="john", realm="http://example.com:8080/", ...

The equivalent curl command is:

curl --digest --user john -I -X DELETE "http://example.com:8080/test/#rel=describedby"

Normal HTTP response codes are used to indicate success or failure of the request. In this case, a successful delete is indicated by a 200 (OK) or 204 (No Content) response.


F. Searching content

Here we will explore two RESTful ways of searching for content using Callimachus:

Keyword searches

Keyword searches may be performed on certain RDF properties. See Appendix A for a list of RDF properties that may be searched.

An OpenSearch description document may be discovered by resolving the top-level OPTIONS and looking for the Search URL. Find the link:header with rel="search" (See the section Browsing Content for details). Search results are returned in an Atom document augmented with OpenSearch response elements.

Perform an HTTP GET on the Search URL. Provide an Accept: header including its associated content type. For example:

GET http://example.com/#rel=search HTTP/1.1
Accept: application/opensearchdescription+xml

The equivalent curl command is:

curl -H "Accept: application/opensearchdescription+xml" "http://example.com/#rel=search"

Which will result in:

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>example.com</ShortName>
<Url type="application/atom+xml" template="http://example.com/#rel=search&amp;searchTerms={searchTerms}"/>
</OpenSearchDescription>

You may then perform a subsequent HTTP GET on the Template URL using the content type specified (in the Url tag's template and typeattributes), substituting your search terms for "{searchTerms}". Note that keyword searches require authentication. To actually perform a keyword search on, for example, the word "Callimachus":

GET http://example.com/#rel=search&searchTerms=Callimachus HTTP/1.1
Accept: application/atom+xml
Authorization: Digest username="john", realm="http://example.com/", ...

The equivalent curl command is:

curl --digest --user john -H "Accept: application/atom+xml" "http://example.com/#rel=search&searchTerms=Callimachus"

Results will look like:

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:calli="http://callimachusproject.org/rdf/2009/framework#"
  xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:app="http://www.w3.org/2007/app">
        <id>http://example.com/#rel=search&amp;searchTerms=Callimachus</id>
        <title>example.com:8080</title>
        <updated>2012-02-23T13:55:59.504Z</updated>
        <entry>
                <id>http://example.com/callimachus/images/callimachus-icon.ico</id>
                <link href="http://example.com/callimachus/images/callimachus-icon.ico#rel=alternate&amp;type=html" rel="alternate"
  type="text/html"/>
                <title>callimachus icon</title>
                <updated>2012-02-24T01:25:04.753Z</updated>
                <content src="http://example.com/callimachus/images/callimachus-icon.ico" type="text/xsl"/>
        </entry>
        <entry>
                <id>http://example.com/callimachus/callimachus-ontology.ttl</id>
                <link href="http://example.com/callimachus/callimachus-ontology.ttl#rel=alternate&amp;type=html" rel="alternate"
  type="text/html"/>
                <title>callimachus ontology</title>
                <updated>2012-02-24T01:24:55.979Z</updated>
                <content src="http://example.com/callimachus/callimachus-ontology.ttl" type="text/xsl"/>
        </entry>
        ...
</feed>

See the OpenSearch description for details on the OpenSearch description document syntax and the OpenSearch response elements.

SPARQL queries

The SPARQL Query Language may be used to query RDF content. Requesting Callimachus' SPARQL endpoint via an HTTP GET with an Accept: header of text/html or application/xhtml+xml (as a browser should) will return an HTML form suitable for human-centric queries. The SPARQL endpoint may also be directly used via REST calls as described below.

The location of the SPARQL endpoint may be discovered by resolving Callimachus' VoID description and parsing out its location.

GET http://example.com/.well-known/void HTTP/1.1
Accept: application/rdf+xml

Note that this and other responses may respond with an HTTP 303 (See Other) response directing you to another location via the Location:header:

HTTP/1.1 303 See Other
Location: http://example.com/.well-known/void#rel=describedby
Content-Length: 0
...

Resolve the URL provided there for the canonical location of the VoID description:

GET http://example.com/.well-known/void#rel=describedby HTTP/1.1
Accept: application/rdf+xml

The equivalent curl command is:

curl -L -H "Accept: application/rdf+xml" "http://example.com/.well-known/void"

A typical response looks like:

HTTP/1.1 200 OK
Age:  0
Etag:  W/"5811c8ee-7566acc1"
Last-Modified:  Fri, 24 Feb 2012 14:49:19 GMT
Date:  Fri, 24 Feb 2012 17:14:01 GMT
Content-Type:  application/rdf+xml
Cache-Control:  public,max-age=868
Access-Control-Allow-Origin:  *
content-version:  "5811c8ee"
Content-Encoding:  gzip
Vary:  Accept,Accept-Charset
Content-MD5:  jUThXJZm7pQvWlmF6OKTNw==
Accept-Ranges:  bytes
Content-Length:  423
Server:  Callimachus Server/Callimachus 0.15-SNAPSHOT

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
        xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:foaf="http://xmlns.com/foaf/0.1/"
        xmlns:void="http://rdfs.org/ns/void#"
        xmlns:audit="http://www.openrdf.org/rdf/2009/auditing#">

<rdf:Description rdf:about="http://example.com/.well-known/void">
        <audit:revision rdf:resource="http://example.com/change/t1358bd5c49cx0"/>
        <rdf:type rdf:resource="http://rdfs.org/ns/void#DatasetDescription"/>
        <rdfs:label>void</rdfs:label>
        <foaf:primaryTopic rdf:resource="http://example.com/.well-known/void#dataset"/>
</rdf:Description>

<rdf:Description rdf:about="http://example.com/.well-known/void#dataset">
        <rdf:type rdf:resource="http://rdfs.org/ns/void#Dataset"/>
        <foaf:homepage rdf:resource="http://example.com/"/>
        <void:sparqlEndpoint rdf:resource="http://example.com/sparql"/>
        <void:rootResource rdf:resource="http://example.com/"/>
        <void:openSearchDescription rdf:resource="http://example.com/#rel=search"/>
        <void:uriSpace rdf:resource="http://example.com/"/>
</rdf:Description>

</rdf:RDF>

The SPARQL endpoint URL is provided in the void:sparqlEndpoint tag.

Use the SPARQL Protocol to perform queries via REST. See the SPARQL Protocol specification for URL parameters and the SPARQL Query Language specification for details of the query language.

curl --digest --user john --data-urlencode query@test.rq -H accept:application/sparql-results+xml http://example.com/sparql
curl --digest --user john --data-urlencode update@test.ru http://example.com/sparql


Part V. Conclusion and appendices

Conclusion

We hope that you have found this manual useful and welcome comments you may have to improve it.

A. List of searched labels

The following RDF properties may be searched.

Common QName URI
og:title http://ogp.me/ns#title
dc:title http://purl.org/dc/elements/1.1/title
dcterms:title http://purl.org/dc/terms/title
gr:legalName http://purl.org/goodrelations/v1#legalName
rss:title        http://purl.org/rss/1.0/title
fb:type.object.name        http://rdf.freebase.com/ns/type.object.name
sioc:name http://rdfs.org/sioc/ns#name
gn:alternateName http://www.geonames.org/ontology#alternateName
gn:name http://www.geonames.org/ontology#name
gn:officialName http://www.geonames.org/ontology#officialName
gn:shortName        http://www.geonames.org/ontology#shortName
rdfs:label http://www.w3.org/2000/01/rdf-schema#label
skos:altLabel http://www.w3.org/2004/02/skos/core#altLabel
skos:hiddenLabel http://www.w3.org/2004/02/skos/core#hiddenLabel
skos:prefLabel http://www.w3.org/2004/02/skos/core#prefLabel
vcard:additional-name        http://www.w3.org/2006/vcard/ns#additional-name
vcard:family-name http://www.w3.org/2006/vcard/ns#family-name
vcard:fn http://www.w3.org/2006/vcard/ns#fn
vcard:given-name http://www.w3.org/2006/vcard/ns#given-name
vcard:label http://www.w3.org/2006/vcard/ns#label
vcard:nickname http://www.w3.org/2006/vcard/ns#nickname
vcard:organization-name http://www.w3.org/2006/vcard/ns#organization-name
vcard:organization-unit http://www.w3.org/2006/vcard/ns#organization-unit
skosxl:literalForm http://www.w3.org/2008/05/skos-xl#literalForm
foaf:name        http://xmlns.com/foaf/0.1/name

B. BLOB Resource Types

Here are the BLOB resource types that you can use in Callimachus.

Resource type Content type
Article application/docbook+xml
Font application/font-woff
PDF application/pdf
NamedGraph application/rdf+xml (goes into RDF and BLOB store)
NamedQuery application/sparql-query
Page application/xhtml+xml
Pipeline application/xproc+xml
XQuery application/xquery
AnimatedGraphic image/gif
Photo image/jpeg
NetworkGraphic image/png
VectorGraphic image/svg+xml
IconGraphic image/vnd.microsoft.icon
Style text/css
HypertextFile text/html
Script text/javascript
TextFile text/plain
GraphDocument text/turtle (goes into RDF and BLOB store)
Transform text/xsl

C. RDF Resource Types

Here are the default RDF resource types used in Callimachus. Users can create their own RDF resource types by creating a Callimachus class.

Resource type Content type Required Property
SKOS Concept skos:Concept, </callimachus/1.0/types/Concept> skos:prefLabel
Folder calli:Folder, </callimachus/1.0/types/Folder> rdfs:label
Group calli:Party, calli:Group, </callimachus/1.0/types/Group> rdfs:label

NB: Classes require compilation and are not manipulatable via the REST API.


D. PURL FAQ

Here are some questions and answers about PURLs derived from our online book Linked Enterprise Data.

What is a PURL?

A PURL is a persistent URL - it provides a permanent address for a web resource. PURLs provide a way of letting a third party (i.e. a PURL service) manage the resolution of URLs. As well PURLs provide metadata for resources.

How do PURLs differ from regular URLs?

Unlike a regular URL that simply provides an address to a web resource, a PURL redirects the browser to another Web resource.

Why use PURLs?

PURLs ensure that clients can rely on the same Web address to get a web resource, even if the location of that resource changes. They allow the decentralized management and real-time administration of persistent identifiers (i.e. curation). As well, PURL services can solve the Web’s back link problem for content important enough to warrant its use.

What is the structure of a PURL?

The component parts of a PURL corresponds to the specification for a valid URL. They are as follows:

Image source: PURL.org

Part Function
Scheme informs the browser which protocol to use (i.e. HTTP)
Host informs the browser which server to connect to
Domain hierarchical information that separates PURLs and allows for PURLs to have different maintainers. The PURL domain is analogous to the resource path in a URL.
PURL name the name of the PURL itself
PURL id the combination of the PURL domain with the PURL name forms the PURL id

How are PURLs categorized?

PURLs are categorized into types depending on how they respond to a HTTP request.

What are some prerequisites for creating PURLs?

Since PURLs require a domain to hold them, a domain must first be created before any PURLs may be placed in them. A domain maintainer is responsible for administering a PURL domain record, while a domain “writer” is allowed to add or remove PURLs from a domain.

What examples are there of public PURL services?

A public PURL service has been operated by the Online Computer Library Center since 1995.

Who can create a PURL service?

A PURL service may be created by any organization.

What is the relation between PURLs and linked data?

PURLs have been used to address persistent identifier needs in the library and Linked Data communities for the past fifteen years. Many Linked Data vocabularies are hosted at purl.org including the Dublin Core element set and FOAF.

What are the alternatives to using PURLs for persistent identification?

Other persistent identifier schemes include Digital Object Identifiers (DOIs), Life Sciences Identifiers (LSIDs) and INFO URIs.

How do PURLs compare with these other persistent identifier schemes?

While some other schemes such as DOIs do support curation, DOIs are seen as too commercial. LSIDs are functionally similar to PURLs since they may be mapped to a URL scheme and an administration service. INFO URIs provide neither real-time resolution, nor real-time administration.

What are some weakness of PURLs?

PURLs are vulnerable to changes in Domain Name System (DNS) registrations and dependencies on the host computer. As well, a failure to resolve a PURL could lead to an ambiguous state: did the PURL fail to resolve because of a network failure or because the resource did not exist?


E. Callimachus Support

3 Round Stones offers commercial support and private virtual cloud hosting for enterprises running Callimachus.

Commuity support may be access through our mailing list.