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

2.9. Home Folder Edit Tab

The Edit tab of the Home Folder serves as a control dashboard for many crucial functions within Callimachus. 

2.9.1. Access

To access the Home Folder Edit tab simply navigate to the Home Folder via the Main Menu and click the "Edit" tab.

2.9.2. Components
Realm Settings

Realm settings determine are applied across an entire Callimachus instance and control some of the fundamental access and presentation aspects.

Layout

Layout is the extra markup that is applied to every xhtml template within a Callimachus instance. This is the easiest way to apply common layout and styling across your Callimachus pages and applications. Creating a custom Layout is as easy as clicking the icon next to "Layout" and customizing the file as desired. 

Once the file is created you can edit that file and upon saving the layout will be updated across the Callimachus instance.

Callimachus utilizes the Bootstrap framework which makes both formatting and styling much easier for everyday developers. Check out Bootswatch for free Bootstrap themes that will integrate with Callimachus seamlessly. The theme can be either downloaded locally or referenced via a <link> tag. In your Callimachus Layout file simply paste the link underneath {calli:styles-href(<link rel="stylesheet" />)} in this manner:


{calli:styles-href(<link rel="stylesheet" />)}
<link rel="stylesheet" type="text/css" href="http://bootswatch.com/2/flatly/bootstrap.min.css" />
Allowed Origins

Allowed origins are origins from which scripts can make requests to a Callimachus instance. For example, if Callimachus was installed at http://host.example.com and had an Allowed Origin of http://allowed.example.com, scripts located on allowed.example.com could make requests to host.example.com. If you do not want your Callimachus instance to be made available to other origins then the only Allowed Origin should be the origin at which your instance is installed. 

This origin configuration is in line with the CORS specification. 

Authentication

Different authentication options can be managed from this tab. A list of the authentication mechanisms currently applied to the Callimachus instance are rendered by default. 

Authentication options can be added via the icon next to "Authentication." They can be removed by clicking the small "x" next to the authentication option. Be aware that by clicking this "x" you are only removing the authentication mechanism as an option for logging in, but not deleting the authentication configuration itself.

Credentials

Credentials are managed via the Home Folder Edit tab. A list of the credentials currently applied to the Callimachus instance are rendered by default. 

Credentials can be added via the icon next to "Credentials." They can be removed by clicking the small "x" next to the credential listing. Be aware that by clicking this "x" you are only removing the credential from use in the current instance, but not deleting the credential configuration itself.

Directory Index

Directory index settings determine how requests directly to the Home Folder should be handled.

Type

The type is the response code that is sent. For more information on exactly what these types represent read the PURL documentation.

Content Location

Content location is the resource that should be returned to the browser when the Home Folder is requested. This is the best way you can set the home page for your Callimachus instance. Generally this is some sort of landing or index page for your application or system.

Cache Control

Cache control is used to control how often the content will be refreshed for users of a Callimachus instance. The value entered will determine exactly how the system responds to multiple requests for the same resource over a given period of time. For a list of the available values for this field please see the specification section "cache-response-directive". An example value would be "max-age=3600".  


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. RDF Datasource

3.7.1. Description

An RDF Datasource is a SPARQL endpoint service that gives you the ability to define and access additional repositories within a single deployment. For example /sparql is the Datasource that gives you read/write access to the default Sesame repository that Callimachus uses. By creating a a new Datasource you are creating a new, empty Sesame native store within your Callimachus instance.

3.7.2. Managing RDF Datasources
Creating an RDF Datasource

Steps for creating an RDF Datasource in Callimachus:

1. Click the "Create" button and choose "Datasource"

2. Fill out the relevant fields in the Datasource create form
Field Description Sample Value
Label Value used for title of Datasource New Datasource
Comment Value used for description of Datasource. Appears in top right corner when viewing the Datasource. A new instance of a Datasource
SPARQL Query Whether or not the Datasource allows Read operations against it. Checked
SPARQL Update Whether or not the Datasource allows Write operations against it.  Checked

3. Click "Create" at the bottom of the page

After clicking create you will be brought to a page viewing your new Datasource. From here you can perform any number of operations which are described in more detail in Using a Datasource.

Editing an RDF Datasource

Once an RDF Datasource has been created you can go back and edit any of the values you entered by selecting the "Edit" tab when viewing the RDF Datasource. You can change both the Label and the Comment as well as whether or not Read and Write operations can be performed against the Datasource.

Note: If you plan to use this RDF Datasource in Named Queries or Pipelines, be sure to set the the appropriate permissions under the Main menu by selecting "Permissions" and adding the "System" user to the "Editor" group. 

Deleting an RDF Datasource

You can delete an RDF Datasource at any time by navigating to the "Edit" tab of the desired RDF Datasource.

Warning! If you delete an RDF Datasource, any data you have loaded into it will also be deleted.

3.7.3. Using an RDF Datasource

Callimachus RDF Datasources expose all SPARQL 1.1 commands and most SPARQL Protocol and Graph Store HTTP Protocol (using indirect graph identification) requests. The most common you probably will find yourself using to get started are LOAD and SELECT. The interface is just a large textarea in which you can type your commands. It looks like this:

This RDF Datasource is now saved to the Callimachus instance and can be accessed programatically via FROM clauses in SPARQL queries and XProc Pipelines, for example. Also, if you are working with a small dataset you can perform the following query to ensure the RDF Datasource is working as expected:

SELECT DISTINCT ?type WHERE { 
    ?thing a ?type 
} ORDER BY ?type LIMIT 50

3.8. Domain

3.8.1. Definition

Callimachus Domains represent a set of network agents (i.e. all authenticated users). This differs from a User Group in that user groups are defined by named users whereas a Domain can be defined by more generalized attributes such as authenticated or unauthenticated.

3.8.2. Purpose

Domains provide a way to assign resource permissions to a set of network agents which can simplify resource permissions. This can greatly help generalize resource permissions.

3.8.3. Usage

To create a Domain click the "Create Menu" and select "Domain". 

Upon creating a Domain you initially set only the Label and Description. Once the Domain is saved, you can select the "Edit" tab and set a number of new fields:

Field Description
Anonymous access from Reverse domain lookup suffix for agents that can interact with the resources without authentication. This can be used for resources you want to be publicly available.
Authenticated access from Reverse domain lookup suffix for authenticated agents that can interact with the resources. 
Deny access from Reverse domain lookup suffix for agents that cannot interfact with the resources. This setting overrides other settings.

Examples of Domains within Callimachus can be found in /auth/groups/ and are:

  • everyone
    • Represents all authenticated users by setting "Authenticated access from" to "." which signifies access is allowed from any network.
  • public
    • Represents all possible users (unauthenticated included) by setting "Anonymous access from" to ".". 
  • system
    • Represents the local Callimachus system by setting "Anonymous access from" to "localhost". 

3.9. Graph document

3.9.1. Definition

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

3.9.2. Purpose

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

3.9.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.9.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.9.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.10. HTML Files

A Hypertext File is an HTML file served verbatim within Callimachus. This means that the normal JavaScript and CSS that is applied to Callimachus Pages (XHMTL files) is omitted when the page is rendered. Hypertext Files are ideal in Callimachus when you want to serve a page that will appear or function as a visually separate page or application.

In order to view an HTML page ensure that the URL ends in .html, rather than .html?view. If the URL is appended with ?view the page will be rendered within the contents section of the Callimachus layout. 

View within contents section:

http://example.com/resource.html?view

View as stand-alone HTML page:

http://example.com/resource.html

3.11. Named query

3.11.1. Definition

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

3.11.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.11.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.11.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.12. Page

3.12.1. Definition

A Callimachus Page is an XHTML5 compliant web page.

3.12.2. Purpose

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

3.12.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.13. Pipeline

3.13.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.13.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.13.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.13.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.14. PURL

3.14.1. Definition

A Persistent URL or PURL is a permanent identifier for a web resource. It provides a permanent address for a web resource. PURLs provide a way of letting a service manage the resolution of URLs. As well PURLs provide metadata for resources.

Other persistent identifier schemes include Digital Object Identifiers (DOIs), Life Sciences Identifiers (LSIDs) and INFO URIs. 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.

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 can lead to an ambiguous state.

3.14.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. Unlike a regular URL that simply provides an address to a web resource, a PURL redirects the browser to another Web resource.

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.

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 Coreelement set and FOAF.

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

3.14.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.
Parameters in PURLs

Parameters can be passed to and from PURLs on the query string. For example, a call can be made to an existing PURL with parameters like this:

POST existing-purl?first=Joe&last=Bloggs

These variables that are passed in can then be passed on to the content target location of the PURL using bracket notation.

existing-pipeline.xpl?results&first={first}&last={last}

The variable names inside the curly brackets should match the variable names used in the query string when the PURL is called. This notation will pass along a URL-encoded version of the parameter's value. If you want to pass along an unencoded version insert a plus sign before the variable name.

/{+last}/{+first}.txt
3.14.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.14.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.14.6. Support for partial PURLs

Callimachus does not implement "Partial PURLs" as of the 1.2 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.15. Script

3.15.1. Definition

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

3.15.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.15.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.16. Style

3.16.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.16.2. Creating styles

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

3.16.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.16.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.17. XSL Transform

3.17.1. Definition

An XSL Transform is a document utilizing XSLT which gives you the ability to transform XML documents into other formats such as HTML, plain text, or even a different XML structure. Transforms are extremely useful for restructuring data into a new format or serialization.

3.17.2. Creating an XSL Transform

To create a transform click the "Create" button and select "Transform". 

Here you are presented with a text editor into which you can type your transform.

Click "Create" and your Transform will be saved. You can go back at any point to Edit the Transform by selecting the "Edit" tab. 

3.17.3. Sample XSL Transform
Step 1 - Obtain original XML document

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="example.xsl"?>
<Article>
  <Title>My Article</Title>
  <Authors>
    <Author>Mr. Foo</Author>
    <Author>Mr. Bar</Author>
  </Authors>
  <Body>This is my article text.</Body>
</Article>
Step 2 - Write XSL Transform

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>

  <xsl:template match="/">
    Article - <xsl:value-of select="/Article/Title"/>
    Authors: <xsl:apply-templates select="/Article/Authors/Author"/>
  </xsl:template>

  <xsl:template match="Author">
    - <xsl:value-of select="." />
  </xsl:template>

</xsl:stylesheet>

This Transform capatures the title of the article and prints it out prepended with "Article - " by accessing the value located within the <title> tag using select="/Article/Title/". The same mechanism is used to access the authors of the article except since there are multiple values instead of simply obtaining the raw value it is passed along to a template for printing, as can be seen on the line showing <xsl:template match="Author">.

Step 3 - Output document

Article - My Article
Authors:
- Mr. Foo
- Mr. Bar

This is obviously a very simple example but you can use these principles to start transforming your data however is necessary.

Example source: https://developer.mozilla.org/en-US/docs/XSLT_in_Gecko/Basic_Example

3.18. User Group

3.18.1. Definition

A User Group is a collection of Callimachus users.

3.18.2. Purpose

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

3.18.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.18.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.18.5. Adding Users

To allow group members access from any location list the members in the Members field.

3.19. XQuery

3.19.1. Definition

XQuery is a query language that offers the ability to quickly and easily retrieve XML resources for rendering and presentation. Callimachus Layouts are XQuery files that provide a template for how content should be displayed.

3.19.2. Usage

The most common usage of XQuery files is as the Callimachus Layout. There are a number of very useful functions defined in the Callimachus XQuery Reference, many of which are used in the default layout.

3.19.3. Sample

xquery version "1.0" encoding "utf-8";

import module namespace calli = "http://callimachusproject.org/rdf/2009/framework#" at "/callimachus/layout-functions.xq";

<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>
    <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,target-densityDpi=device-dpi"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="icon" href="/favicon.ico" />
    {calli:styles-href(<link rel="stylesheet" />)}
    {calli:scripts-src(<script type="text/javascript" />)}
    <!--[if lt IE 9]>
        <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    {calli:head-nodes()}
</head>
<body>
    {calli:body-attributes()}
    <div class="until-navbar-large">
        <div class="navbar navbar-static-top hidden-iframe">
            <header class="navbar-inner">
                <div class="container">
                    {calli:home-href(<a class="brand">Callimachus</a>)}
                    <menu type="toolbar" class="nav pull-right">
                        <li class="hidden-login">
                            {calli:login-href(<a>Sign in</a>)}
                        </li>
                        <li class="hidden-logout dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                <i class="icon-cog"></i>
                                <i class="caret"></i>
                            </a>
                            <menu type="list" class="dropdown-menu">
                                <li>{calli:folder-href(<a>Home folder</a>)}</li>
                                <li>{calli:changes-href(<a>Recent changes</a>)}</li>
                                <li class="divider"></li>
                                <li><a href="http://callimachusproject.org/">About Callimachus</a></li>
                                <li><a href="http://callimachusproject.org/docs/1.0/getting-started-with-callimachus.docbook?view">Getting started</a></li>
                                <li><a href="http://groups.google.com/group/callimachus-discuss">Send feedback</a></li>
                                <li class="divider"></li>
                                {calli:head-links(<li><a /></li>,<li class="divider" />)}
                                <li>{calli:whatlinkshere-href(<a>What links here</a>)}</li>
                                <li>{calli:relatedchanges-href(<a>Related changes</a>)}</li>
                                <li>{calli:permissions-href(<a>Permissions</a>)}</li>
                                <li>{calli:introspect-href(<a>Introspect resource</a>)}</li>
                                <li><a href="javascript:print()">Print this page</a></li>
                                <li class="divider"></li>
                                <li>{calli:profile-href(<a>Account</a>)}</li>
                                <li>{calli:logout-href(<a>Sign out</a>)}</li>
                            </menu>
                        </li>
                    </menu>
                    <div class="navbar-search pull-right hidden-logout">{calli:lookup-form('Lookup...')}</div>
                </div>
            </header>
        </div>
        <div class="container">
            <nav class="breadcrumb hidden-iframe">{calli:breadcrumb-links(<a class="muted"/>, <span class="divider">&#187;</span>, <span class="active"/>)}</nav>
            {calli:body-hgroup()}
            {calli:body-sidebar(<div class="sidebar pull-right" />)}
            {calli:activate-nav(<nav class="hidden-logout hidden-iframe nav-tabs">
                {calli:view-href(<a tabindex="1" onclick="location.replace(href);return false">View</a>)}
                {calli:edit-href(<a tabindex="2" onclick="location.replace(href);return false">Edit</a>)}
                {calli:discussion-href(<a tabindex="3" onclick="location.replace(href);return false">Discussion</a>)}
                {calli:describe-href(<a tabindex="4" onclick="location.replace(href);return false">Describe</a>)}
                {calli:history-href(<a tabindex="5" onclick="location.replace(href);return false">History</a>)}
            </nav>)}

            <div class="tab-content">
                {calli:error-alert(<div class="alert alert-error alert-block">
                    <button type="button" class="close" data-dismiss="alert">×</button>
                    <h4>Oops!</h4>
                </div>)}
                {calli:body-nodes()}
            </div>
        </div>
    </div>

    <div class="navbar navbar-large navbar-relative-bottom hidden-iframe">
        <footer class="navbar-inner">
            <div class="container">
                {calli:generator-p(<p class="pull-right navbar-text" />)}
                {calli:lastmod-time(<p class="navbar-text">This resource was last modified at <time class="abbreviated"/></p>)}
            </div>
        </footer>
    </div>
</body>
</html>


Chapter 4. Callimachus Account Management

This describes Callimachus user accounts and their configuration options.

4.1. User Account

Accessing and configuring your user account is very simple, but depends heavily on what type of authentication was used to create your account. If you elected to login via an external service such as Google, Facebook, or Yahoo! then you have not created a new account on that Callimachus instance. In that case, any configuration should take place wherever the account is hosted.

However, if you have signed in via Digest Authentication (by creating a local Callimachus account) then you have a set of configuration options available to you within the Callimachus environment. You also have a dedicated account page from which you can alter these configurations. 

4.1.1. Access

To access your Callimachus User Account click on the Main Menu in the upper right of your Callimachus instance. At the bottom of the menu, just above "Sign out" will be a menu option pointing to your user account. The label will display however you signed in - via email: joe@example.com or via username: joe.

The resulting behavior however will differ based on authentication type.

Digest Authentication:

Clicking the profile link will take you to your dedicated Callimachus User Account. This page contains such information as full name, username and groups you belong to on the system. 

Non-Digest Authentication:

Clicking the profile link will do one of two things:

  • Take you to your account page on the external site with which you authenticated
  • Download the account file used for authentication on the external site

This behavior depends on how the external site is configured. For example, Facebook will take you to your Facebook profile page while Google will download the profile file associated with your account.

4.1.2. Configuration
Digest Authentication:

Configuration of digest accounts is accomplished via both the "View" and the "Edit" tab of the profile page. From the "View" tab you can click the Main Menu in the upper right of your Callimachus instance and select "Change password or email" to change the email associated with your account as well as the password used to access it.

From the "Edit" tab you can directly edit:

  • Full name
  • Additional information

Your username cannot be changed once the account has been created. If you want to change your username a new account will need to be created.

Non-Digest Authentication:

All configuration of non-digest authenticated accounts must take place on the external site. 

4.2. Account Invitations

4.2.1. Description

Account invitations are exactly what they sound like. They are the mechanism by which you can invite someone to create an account on your Callimachus instance. To invite a user navigate to the group to which you want them to belong (groups are found in /auth/groups/), select the "Edit" tab, and click the icon next to "Members". This will pop-up a dialog box for you to fill out with relevant information about the new user.

When a user is invited they will be able to create an account with whatever authentication options you have made available on your instance. 

A user MUST accept an invitation (follow the link in the email sent) before they are granted any permissions by the group.

4.2.2. Resend Invitations

Sometimes people forget to check their email or an invitation is filed into the spam folder and lost forever. That's why Callimachus offers the ability to resend an existing invitation. Rather than having to delete the old account and create a new one, you can just resend an invitation to the person reminding them to create an account. To do this, navigate to the user's account page in /auth/invited-users/ and click the Main Menu in the upper right and select "Re-send invitation". 

At any time you can check the /auth/invited-users/ directory to see which users have been invited but have not yet created an account. This is an easy way to keep track of potential and actual users of your Callimachus instance. 

4.2.3. Revoke Invitations

Invitations can be also be revoked, as well as resent. To revoke an invitation, navigate to the invited user's account page in /auth/invited-users/ and click the "Edit" tab. At the bottom of the edit tab you can click the red "Revoke invitation" button which will invalidate the pending invitation. 

4.3. Permissions

4.3.1. Description

Callimachus Permissions is how administrators have the ability to control who sees what in a given Callimachus instance. Different levels of access can be defined on a per-group basis depending on how public or private you want your Callimachus instance to be.

4.3.2. Access

Permissions can be set on a per-resource basis by accessing the main menu and selecting "Permissions" when viewing any Callimachus resource.

4.3.3. Usage

Callimachus Permissions offers five levels of increasing access:

  • Reader
    • Readers can view a read-only copy of the resource
  • Subscriber
    • Subscribers can view, see the history, and discuss the resource
  • Contributor
    • Contributors can create new resources in that defined space and edit the newly created resources
  • Editor
    • Editors can make changes using the edit tab and create new resources in that defined space
  • Administrator
    • Administrators can view, create and modify using any available operation

Under each of these permission levels different user groups can be assigned. For example, take a look at the default permission settings for the home folder (/?view). 

The following statements can be asserted from permissions edit tab:

  • The Public and System user groups have been given permission to view the Home Folder
  • The Everyone user group has been given permission to view the Home Folder, its history, and make comments on the resource discussion tab
  • The Users user group has been given permission to create and edit new resources in the Home Folder
  • The Power and Staff user groups have been given permission to create and edit new and existing resources in the Home Folder
  • The Admin user group has been given permission to perform any available operation on the Home Folder.

New user groups can be created and assigned custom permissions in this fashion.


Chapter 5. Callimachus Authentication

Callimachus allows for multiple authentication configurations including Facebook, Google, and Yahoo!. These can be useful for account management or for making your applications easily available to the public.

All forms of authentication are managed via the Authentication Manager which can be found under the "Edit" tab of the home folder. From here you can add, remove, and modify different forms of authentication for your Callimachus instance.

5.1. Digest Password Authentication

Digest password is the local authentication mechanism in Callimachus. It uses HTTP Digest Access Authentication, which never sends the user's password in cleartext. Unlike the other Cookie-based mechanisms available, which are vulnerable to session hijacking because they reuse the same token over and over, digest is based on a simple challenge-response paradigm, which passes a different token for every request and is the strongest mechanism provided for unencrypted HTTP requests.

The digest manager stores user names and a password digest in the configured User folder. Every password digest is salted with the configured Auth name. In some cases the Auth name may also be shown to user as part of a login prompt.

5.2. Facebook Authentication

Facebook authentication manager allows Callimachus Realms to authenticate user agents through an existing Facebook app. Any Facebook user is permitted to authenticate (provided they agree to share their email address). To configure Facebook authentication follow the following steps.

Step Action
1. Create a basic Facebook Application for authentication.
2. Obtain the Facebook App ID and Facebook App Secret for later use. These are displayed at the top of the Application page and can be reached by clicking the main menu dropdown on Facebook and selecting "Manage Apps". 
3. Configure your Facebook Application to communicate with your Callimachus instance. Under "Edit App", enter the URL of your Callimachus instance into the Site URL field of the "Website with Facebook Login" tab and hit "Save Changes".
4. Navigate to the Home Folder and click the "Edit" tab.
5. Click the icon next to "Authentication" to open the Authentication Manager and select "Faceboook authentication".
6. Provide a label, the Facebook App Id, the Facebook Secret, and a comment.
7. Save the form to complete the Facebook authentication setup

You should now be able to login to the instance using your Facebook account.

5.3. Google Authentication

The Google authentication mechanism allows any user agent (i.e. anybody) to authenticate using their Google account. Google distinguishes user identities by what realm they are logging into. Use the same OpenID realm pattern across different realms to have the realms share the same set of user identities. You will need to sent out an invitation to every user for every realm pattern to ensure users have correct access to every realm. Change the origin of the registration link in the invitation to match the invitation to the realm.

When filling out the New OpenID Manager dialog box, refer to the definitions below of the input boxes and their suggested values.

Term Definition Sample Value
Label Name for the authentication scheme. Google Accounts
OpenID Endpoint URL The URL against which the Google Accounts are authenticated. It is rare that this value will need to change. https://www.google.com/accounts/o8/ud
OpenID Realm Pattern A pattern that represents the part of URL-space for which an OpenID Authentication request is valid. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with your Google account
Authentication Button The image used for display purposes on the sign-in page.

An OpenID realm pattern is a pattern that represents the part of URL-space for which an OpenID Authentication request is valid. A realm pattern is designed to give the end user an indication of the scope of the authentication request. Google will present the authority portion of the realm pattern when requesting the end user's approval for an authentication request. The realm pattern is used by Google to allow the end user to automate approval of authentication requests for realms of this pattern.

A realm pattern is a URL, with the following changes:

  • A realm MUST NOT contain a URI fragment
  • A realm MAY contain a wild-card at the beginning of the URL authority section. A wild-card consists of the characters "*." prepended to the DNS name in the authority section of the URL.

5.4. Yahoo! Authentication

The Yahoo! authentication mechanism allows any user agent (i.e. anybody) to authenticate using their Yahoo! account. Yahoo! uses the same user identifier regardless of realm. The OpenID realm pattern is used to allow the end user to automate approval of authentication requests for realms of this pattern and the authority of the pattern is presented to the user.

The configuration process is identical to that of setting up Google Authentication, just with different values.

Term Definition Sample Value
Label Name for the authentication scheme. Yahoo! accounts
OpenID Endpoint URL The URL against which the Yahoo! Accounts are authenticated. It is rare that this value will need to change. https://open.login.yahooapis.com/openid/op/auth
OpenID Realm Pattern A pattern that represents the part of URL-space for which an OpenID Authentication request is valid. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with your Yahoo! account
Authentication Button The image used for display purposes on the sign-in page.

A realm pattern is a URL, with the following changes:

  • A realm MUST NOT contain a URI fragment
  • A realm MAY contain a wild-card at the beginning of the URL authority section. A wild-card consists of the characters "*." prepended to the DNS name in the authority section of the URL.

5.5. Other OpenID Provider Authentication

The OpenID provider authentication mechanism allows an user agent to authenticate using an external provider, such as a J2EE Servlet.

Term Definition Sample Value
Label Name for the authentication scheme. Other accounts
OpenID Endpoint URL The URL of the endpoint or servlet. http://example.com/servlets/servlet/AuthServlet
OpenID Realm Pattern A pattern that is passed to the endpoint as openid.realm query parameter. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with another account
Authentication Button The image used for display purposes on the sign-in page.

5.6. Custom J2EE Authorization

An external endpoint must support three modes for HTTP GET requests: checkid_setup, check_authentication, and checkid_immediate. The mode is indicated in the query string parameter "openid.mode".

5.6.1. Checkid Setup

The checkid_setup mode is called from the user agent Web browser. The endpoint should redirect the user to an login screen, if needed, and provide their name, email, and a unique identifier through redirecting the user to the return_to URL provided in the query string parameter "openid.return_to".


if ("checkid_setup".equals(request.getParameter("openid.mode"))) {
    // called by user agent to be redirected to login screen (as needed)
    String url = request.getRequestURL().toString();
    String return_to = request.getParameter("openid.return_to");
    StringBuilder sb = new StringBuilder("LoginServlet");
    sb.append("?return_to=").append(URLEncoder.encode(return_to));
    sb.append("&op_endpoint=").append(URLEncoder.encode(url));
    response.setStatus(303);
    response.setHeader("Location", sb.toString());
}

To have a J2EE application prompt the user agent to login, put a Servlet in a security-contraint. Shown here is LoginServlet protected by a realm in WEB-INF/web.xml.


<security-constraint>
  <display-name>Make sure all users have logged in before accessing the LoginServlet</display-name>
  <web-resource-collection>
     <web-resource-name>Protected Area</web-resource-name>
     <url-pattern>/servlets/servlet/LoginServlet</url-pattern>
  </web-resource-collection>
  <auth-constraint>
     <!-- Anyone with one of the listed roles may access this area -->
     <role-name>tomcat</role-name>
     <role-name>role1</role-name>
  </auth-constraint>
</security-constraint>

Once the user agent has authenticated/logged in, their name, email, and a persistent unique identifier must be sent to the return_to URL. The format of the response must conform to OpenID Authentication Response. The fullname and email must conform to OpenID Attribute Exchange Fetch Response Format.


// called by user agent to be redirected back after logging in
String return_to = request.getParameter("return_to");
String op_endpoint = request.getParameter("op_endpoint");
StringBuilder sb = new StringBuilder(return_to);
if (return_to.indexOf('?') > 0) {
    sb.append('&');
} else {
    sb.append('?');
}
sb.append("openid.ns=http://specs.openid.net/auth/2.0");
if (this.isAuthorized(request)) {
    String id = (String) request.getSession(true).getAttribute("id");
    if (id == null) {
        id = request.getSession(true).getId();
        request.getSession(true).setAttribute("id", id);
    }
    String user_fullname = this.getUserFullName(request);
    String user_email = this.getUserEmail(request);
    String user_uri = this.getUserIdentifier(request);
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    String now = df.format(new Date());
    sb.append("&openid.mode=id_res");
    sb.append("&openid.op_endpoint=").append(URLEncoder.encode(op_endpoint));
    sb.append("&openid.claimed_id=").append(URLEncoder.encode(user_uri));
    sb.append("&openid.identity=").append(URLEncoder.encode(user_uri));
    sb.append("&openid.return_to=").append(URLEncoder.encode(return_to));
    sb.append("&openid.ns.ax=http://openid.net/srv/ax/1.0");
    sb.append("&openid.ax.mode=fetch_response");
    sb.append("&openid.ax.type.email=http://axschema.org/contact/email");
    sb.append("&openid.ax.type.fullname=http://axschema.org/namePerson");
    sb.append("&openid.ax.value.email=").append(URLEncoder.encode(user_email));
    sb.append("&openid.ax.value.fullname=").append(URLEncoder.encode(user_fullname));
    sb.append("&openid.response_nonce=").append(now).append(URLEncoder.encode(id));
} else {
    sb.append("&openid.mode=cancel");
}
response.setStatus(303);
response.setHeader("Location", sb.toString());

In the above example the user agent session ID is encoded in the openid.response_nonce parameter that is sent to the return_to URL, this will later be used to verify the information is valid.

5.6.2. Check Authentication

Once the user agent has been authenticated, the system must verify the information directly to the external endpoint. In order for a Servlet endpoint to access the necessary HttpSession information, an HttpSessionListener can be used to track the local user agent sessions. A listener must be registered in WEB-INF/web.xml.


<listener>
    <listener-class>SessionTracker</listener-class>
</listener>

public class SessionTracker implements HttpSessionListener {
  public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    ServletContext ctx = session.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    if (sessions == null) {
        synchronized (ctx) {
            sessions = (Map) ctx.getAttribute("active-sessions");
            if (sessions == null) {
                sessions = Collections.synchronizedMap(new HashMap<String, HttpSession>());
            }
            ctx.setAttribute("active-sessions", sessions);
        }
    }
    String id = (String) session.getAttribute("id");
    if (id == null) {
        id = session.getId();
        session.setAttribute("id", id);
    }
    sessions.put(id, session);
  }
  public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    ServletContext ctx = session.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    if (sessions != null) {
        sessions.remove(session.getId());
    }
  }    
}

The system will sent a GET request to the external endpoint and pass all the parameters that it was sent for verification. The endpoint must verify that all of the parameters are correct and none of them have been modified in transit. The response must comply with Verifying Directly with the OpenID Provider.


if ("check_authentication".equals(request.getParameter("openid.mode"))) {
    // called by client for session validation
    String user_fullname = request.getParameter("openid.ax.value.fullname");
    String user_email = request.getParameter("openid.ax.value.email");
    String user_uri = request.getParameter("openid.identity");
    String response_nonce = request.getParameter("openid.response_nonce");
    String sessionId = response_nonce.substring(response_nonce.indexOf('Z') + 1);
    ServletContext ctx = request.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    HttpSession session = sessions == null ? null : sessions.get(sessionId);

    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.print("ns:http://specs.openid.net/auth/2.0\n");
    if (session != null
            && user_fullname.equals(this.getUserFullName(session))
            && user_email.equals(this.getUserEmail(session))
            && user_uri.equals(this.getUserIdentifier(session))) {
        out.print("is_valid:true\n");
    } else {
        out.print("is_valid:false\n");
    }
}
5.6.3. Checkid Immediate

If the validation fails the system will redirect their user agent to the endpoint with the mode checkid_immediate. This is similar to checkid_setup, but indicates the endpoint should redirect the user directly back to the system without any user prompts. If the user is not logged in, the response should contain the mode setup_needed to indicate the user must login before proceeding, otherwise a mode of id_res with updated credentials (as with checkid_setup) should be returned.


if ("checkid_immediate".equals(request.getParameter("openid.mode"))) {
    // called by user agent to be immediately redirected back
    String return_to = request.getParameter("openid.return_to");
    String op_endpoint = request.getRequestURL().toString();
    StringBuilder sb = new StringBuilder(return_to);
    if (return_to.indexOf('?') > 0) {
        sb.append('&');
    } else {
        sb.append('?');
    }
    sb.append("openid.ns=http://specs.openid.net/auth/2.0");
    if (this.isAuthorized(request)) {
        String id = request.getSession(true).getId();
        String user_fullname = this.getUserFullName(request);
        String user_email = this.getUserEmail(request);
        String user_uri = this.getUserIdentifier(request);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        String now = df.format(new Date());
        sb.append("&openid.mode=id_res");
        sb.append("&openid.op_endpoint=").append(URLEncoder.encode(op_endpoint));
        sb.append("&openid.claimed_id=").append(URLEncoder.encode(user_uri));
        sb.append("&openid.identity=").append(URLEncoder.encode(user_uri));
        sb.append("&openid.return_to=").append(URLEncoder.encode(return_to));
        sb.append("&openid.ns.ax=http://openid.net/srv/ax/1.0");
        sb.append("&openid.ax.mode=fetch_response");
        sb.append("&openid.ax.type.email=http://axschema.org/contact/email");
        sb.append("&openid.ax.type.fullname=http://axschema.org/namePerson");
        sb.append("&openid.ax.value.email=").append(URLEncoder.encode(user_email));
        sb.append("&openid.ax.value.fullname=").append(URLEncoder.encode(user_fullname));
        sb.append("&openid.response_nonce=").append(now).append(URLEncoder.encode(id));
    } else {
        sb.append("&openid.mode=setup_needed");
    }
    response.setStatus(303);
    response.setHeader("Location", sb.toString());
}

5.7. Credentials

5.7.1. Description

Credentials are the username and passwords that should be used for outgoing requests from scripts, queries, or pipelines within a given realm. For example in order to be able to take any action against most servers you need to authenticate yourself. You can do this by hardcoding your username and password into the query string but that is a clunky solution and a potential security risk. That is why Callimachus allows you to store credentials system-wide and whenever one of your scripts, queries, or pipelines is challenged for authentication Callimachus will check your credentials for the proper login information. 

5.7.2. Configuration
Create a Credential

To setup Credentials for your system navigate to the Home Folder and click the "Edit" tab. From here click the icon next to "Credentials" and fill in the form with the appropriate values.

Field Explanation Sample Value
Authority This is the host name of the service. Must be entered in format authority:port or authority if the port is 80. people.example.com
Username The username used to authenticate against the service specified in Authority. username
Password The password tied to the username used to authenticate against the service specified in Authority. password

After filling in the form, click Create and your credentials will be saved. Don't forget to hit "Save" on the Home Folder itself or the relationship will not be created.

Edit a Credential

If you typed the password for a given credential incorrectly you can find it in /auth/credentials. From there click the "Edit" tab and retype the password. If you wish to rename a Credential or change the Authority or Port you will need to delete that Credential and create a new one. 

Remove or Delete a Credential

Removing a Credential means that it no longer applys to your Callimachus instance. The Credential itself stil exists in /auth/credentials and can be reapplied at a later time if you desire. 

Deleting a Credential, on the other hand, removes the Credential entirely from the system along with any relationships to the system it may have. This cannot be undone and if you do so unintentionally you can recreate it via the Create menu. 

5.7.3. Usage

Now that credentials have been stored in your Callimachus instance, you can access that system without explicitly authenticating each and every time. For example, rather than having to write a query like this:


PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT ?name WHERE {
  ?myself a foaf:Person
    ; ​foaf:knows ?person .
  
  SERVICE <http://username:password@people.example.com/sparql> { 
    ?person foaf:name ?name . 
  } 
}

which exposes in plain text both your username and password, you can write a query like this:


PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT ?name WHERE {
  ?myself a foaf:Person
    ; ​foaf:knows ?person .
  
  SERVICE <http://people.example.com/sparql> { 
    ?person foaf:name ?name . 
  } 
}

that doesn't include that information. Callimachus takes care of the authentication behind the scenes.


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

6.1. Resource Create Template

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

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

6.2. Resource Edit Template

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

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

6.3. Resource View Template

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

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

6.4. Named Query Template

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

6.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)
6.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 7. Callimachus Template Language

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

7.1. Evaluation Context

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

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

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

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

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

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

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

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

7.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 8. Patterns for Scripting Edit and Create Templates

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

8.1. Input Patterns

8.1.1. Overview

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

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

8.2. Manipulation Patterns

8.2.1. Overview

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

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

8.3. Selection Patterns

8.3.1. Overview

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

8.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>
8.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>
8.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>
8.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 9. Patterns for Scripting View Templates

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

9.1. Display Patterns

9.1.1. Overview

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

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

9.2. Formatting Patterns

This describes four ways of formatting data in View templates:

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

9.3. Navigation Patterns

9.3.1. Overview

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

9.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 10. 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.

10.1. Finding linked data

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

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

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

10.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 11. 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.

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

11.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 }

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

11.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 '>'.

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

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

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

11.3. Results from named queries

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

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

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

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

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

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

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

11.5. Chart Wizard

11.5.1. Overview

Callimachus' Chart Wizard exists to make visualizations of your data easy to explore, develop, and include in other documents. No JavaScript to write or frameworks to learn - the Chart Wizard provides a friendly user interface that allows you to create and customize a wide variety of charts and visualizations for any properly structured queries contained within Callimachus.

11.5.2. Interface

Visualizations are based on data and data is surfaced and organized via queries. For that reason, the Chart Editor is only available when you are on the ?view template for an existing query. Once there, the Chart Editor is opened by clicking the Main Menu (top right) in the top right of the screen and selecting "Edit visualization". 

At this point the Wizard is opened in a dialog box in front of whatever Named Query you were previously viewing. The dialog box is intentionally minimal to allow you to test multiple visualizations and see the results in real-time in the query view page. This allows for rapid iteration and testing of potential visualizations without having to compile or embed unsuccessful attempts. 

The Wizard is composed of two sections: the Visualization Selector and the Chart Options pane. 

Visualization Selector

When you select "Edit visualization" from the main menu the dialog box will appear. From here try selecting different visualizations and take notice of how the query view page (behind the dialog box) which was once a simple table, changes to reflect the selections made in the chart wizard.

Callimachus' chart wizard also offers the ability to create Google Charts via an integration of the Google Charts Editor. To see what options are available via Google Charts select "More... (Google Charts)" from the bottom of the menu to open the editor. Documentation on the Google Charts Editor is below.

Chart Options pane

Many of the Visualizations can be further customized once they are selected. For some visualizations, X and Y axes or label and value settings will need to be specified. Once the mandatory configuration is completed, many optional configurations exist. Attributes such as color, gradient scaling, and legends can be added with ease. Just as with changing visualization types, any changes to the attributes are reflected in the actual query view behind the chart wizard. Try out some of the different options and see what works best before saving the final product.

Here you can see we have taken a basic line chart and assigned the following configurations:

  • Assigned the key column to represent the results of the ?label variable returned in the query
  • Assigned the value column to represent the results of the ?count variable returned in the query
  • Set the chart to display the labels from the key column
  • Set the chart to display a legend of all key column values
Google Charts Editor
Start tab

This tab is simple yet powerful. Callimachus' Chart Wizard will actually introspect the structure of the Named Query's results and suggest charts that may make the most sense for the underlying data. Also, if applicable, this tab allows users to set the first column of results as labels for any resulting charts.

Charts tab

The Charts tab houses the full collection of available charts and visualizations (full list below). Simply click a chart option to populate the preview area to the right. If a chart would not render properly based on the underyling data the option is greyed out and the preview area offers some guidance on how the data must be structured in order for that chart to be used.

Customize tab

The Customize tab gives you the ability to fine-tune your chart to whatever level of granularity you desire. Each specific chart has it's own respective set of configuration options available under the "Customize" tab in the Chart Wizard. Some are more configurable than others but in general you will be able to edit aspects such as color, font, title, legend, and more. Just as in the Charts tab, any changes made here are immediately reflected in the preview pane to the right.

11.5.3. Chart Types
  • Table
    • Bootstrap
    • Datatable
    • Google Charts
  • Bar 
    • Dimple
    • Google Charts -> Basic
    • Google Charts -> Stacked
  • Line
    • Dimple
    • Google Charts -> Basic
    • Google Charts -> Smooth
    • Google Charts -> Combo
    • Google Charts -> Radar
  • Area
    • Dimple
    • Google Charts -> Basic
    • Google Charts -> Stacked
    • Google Charts -> Stepped
  • Pie
    • NVD3
    • Google Charts -> Basic
    • Google Charts -> Three dimensional
    • Google Charts -> Donut
  • Map
    • Google Charts -> Region
    • Google Charts -> Marker
  • Column
    • Google Charts -> Basic
    • Google Charts -> Stacked
  • Scatter 
    • Google Charts -> Basic
    • Google Charts -> Bubble
  • Trend
    • Google Charts -> Spark
    • Google Charts -> Time
    • Google Charts -> Motion
    • Google Charts -> Candlestick
  • Other
    • Google Charts -> Gauge
    • Google Charts -> Org Chart
    • Google Charts -> Tree map
    • Google Charts -> Table
11.5.4. Integration into Applications

There are two ways in which these charts can be integrated into Callimachus pages and applications. The first is via the @view template notation on Named Query templates and the second is through embedded iFrames.

Named Query View Template

If you click "Save settings..." at the bottom of the Chart Editor and save the chart, that chart's new URL is set as the @view template for the Named Query the chart is based on. If you create another visualization for that same Named Query, the @view template will be updated to the most recent visualization.

Note: Previously created visualizations have not been deleted, they are just not assigned as the @view template for the Named Query. The visualization itself still exists.

If you want to keep the visualization but do not want it applied as the @view template for the Named Query, simply edit the Named Query and remove the URL following @view at the top of the page.

iFrame

Another way to integrate the visualizations into different pages and applications is via iFrames. This allows for ultimate flexibility since iFrames can be independetly styled and layed out on the page. Use the URL of the visualization as the @src attribute for the iFrame and you're done!

<iframe src="/my-first-chart.xhtml?view" />
11.5.5. Sample Query

Want to try out the Chart Editor quickly? Upload this sample query which lends itself well to a large number of the chart options. 

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

SELECT ?label (COUNT(?type) AS ?count) {

    ?resource a ?type .

    ?type rdfs:label ?label .
} GROUP BY ?label ORDER BY DESC(?count) LIMIT 30

Chapter 12. Using XProc

12.1. Callimachus Pipeline

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

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

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

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

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

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

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

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

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

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

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

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

12.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 13. Some Best Practices to Follow

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

13.1. Handling multiple languages

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

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

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

13.2. Naming Callimachus resources

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

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

13.3. Guidelines for page layout

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

13.4. Using timestamps to control state transitions

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

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

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

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

13.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 Reference

Chapter 14. JavaScript Reference

See Mozilla's JavaScript Reference for a reference to the language itself.

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

14.1. calli.createResource

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

14.1.2. Signature

calli.createResource( event, [src] )

Parameter Description
event HTML click event
src (optional) URL of the page to display in the dialogue.
14.1.3. Example

<a href="Person?create" title="Create a Person"
      onclick="return calli.createResource(event)"
      class="ui-icon ui-icon-newwin" />

14.2. calli.deleteResource

14.2.1. Description

Issues a HTTP DELETE request to the current resource (i.e. current form action target). 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.
14.2.2. Signature

calli.deleteResource( event, [redirect] )

Parameter Description
event HTML click event
redirect (optional) URL to redirect browser to
14.2.3. Example

<button type="button" onclick="calli.deleteResource(event)" class="btn btn-danger">Delete</button>

14.3. calli.saveResourceAs

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

14.3.2. 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
14.3.3. Example

<form method="POST" action="" enctype="application/rdf+xml" typeof="foaf:Person"
    onsubmit="return calli.saveResourceAs(event,calli.slugify($('#label').val()))">

14.4. calli.selectResource

14.4.1. Purpose

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

14.4.2. Signature

calli.selectResource( event, [src] )

Parameter Description
event HTML click event
src (optional) URL of the page in the dialogue
14.4.3. Example

<a href="/scheme/medimus/top" title="Browse Mediums"
    onclick="return calli.selectResource(event)"
    class="ui-icon ui-icon-folder-open" />
14.4.4. 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

14.5. calli.addResource

14.5.1. Description

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

14.5.2. Signature

calli.addResource (event, [container] )

Parameter Description
event HTML click event
container (optional) CSS selector of container element
14.5.3. 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>

14.6. calli.insertResource

14.6.1. Description

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

14.6.2. Signature

calli.insertResource( event )

Parameter Description
event HTML drop event
14.6.3. Example

<div id="related" dropzone="link string: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}}}
));

14.7. calli.removeResource

14.7.1. Description

Removes an RDFa resource from the page.

14.7.2. Signature

calli.removeResource( event )

Parameter Description
event HTML click event
14.7.3. 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>

14.8. calli.error

Presents the given string (or the message or the description property of the given object) to the user using the calli:error-alert template of the layout.


try {
    throw "error message";
} catch (e) {
    calli.error(e);
}

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

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

14.11. 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 15. XProc Reference

XProc is a W3C recommended XML Pipeline Language.

Callimachus provides the following steps that can be used by importing the /callimachus/library.xpl file. <p:import href="/callimachus/library.xpl" />

15.1. calli:decode-text

The calli:decode-text step removes encoding of text. This step behaves like p:unescape-markup, but only decodes it and does not convert text to XML.


<p:declare-step type="calli:decode-text">
    <p:input port="source" sequence="true" primary="true" />
    <p:option name="content-type" select="'text/plain'"/>
    <p:option name="encoding"/>
    <p:option name="charset"/>
    <p:output port="result" sequence="true" />
</p:declare-step>
Option Description Example
content-type The content-type of the data to be decoded application/sparql
charset The character set of the encoded text UTF-8
encoding

One of the following encodings

  • base64
  • base32
  • hex
  • binary
  • quoted-printable
  • www-form-urlencoded
base64

15.2. calli:render-html

The calli:render-html step populates a template using RDF data. The data is retrived using the calli:sparql step.


<p:declare-step name="render-html" type="calli:render-html">
    <p:serialization port="result" media-type="text/html" method="html" doctype-system="about:legacy-compat" />
    <p:input port="source" sequence="true" primary="true" />
    <p:input port="parameters" kind="parameter" primary="true" />
    <p:input port="query" sequence="false" />
    <p:input port="template" sequence="false" />
    <p:output port="result" sequence="true" primary="true" />
    <p:option name="output-base-uri" select="''" />
    <p:option name="endpoint" select="''" />
</p:declare-step>

The RDF data can be provided in the source port as RDF/XML or with the provided SPARQL endpoint.

The SELECT query (and its parameters) are used to select the (exactly one) variable and zero or more bindings. The actualy SPARQL Query sent to the endpoint will be created as a combination of the provided query and the properties and relationships referenced in the template.

15.3. calli:sparql

The calli:sparql step produces application/sparql-results+xml from RDF data.


<p:declare-step type="calli:sparql">
    <p:input port="source" sequence="true" primary="true" />
    <p:input port="query" sequence="true" />
    <p:input port="parameters" kind="parameter" primary="true"/>
    <p:option name="output-base-uri" />
    <p:option name="endpoint" />
    <p:output port="result" sequence="true" />
</p:declare-step>

The RDF data can be provided in the source port as RDF/XML or with the provided SPARQL endpoint.

The SELECT parameters are populated in the query before evaluating the query against the data source.


Chapter 16. XQuery Reference

XQuery is a W3C recommended XML Query Language.

Callimachus provides the following functions that can be used by importing the /callimachus/layout-functions.xq file. import module namespace calli = "http://callimachusproject.org/rdf/2009/framework#" at "/callimachus/layout-functions.xq";

16.1. calli:head-nodes

Copies the XML nodes from the template's <head> element.


<head>
    {calli:head-nodes()}
</head>

16.2. calli:body-attributes

Copies the template's body attributes. It is important that this function be called directly after an element start tag, although some whitespace is permitted.


<head>
    {calli:head-nodes()}
</head>
<body>
    {calli:body-attributes()}
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    </div>
</body>

16.3. calli:body-sidebar

Returns a copy of the given element with the template's /html/body/div[@id='sidebar'] contents inside, or nothing, if no sidebar exists in the template.


{calli:body-sidebar(<div class="sidebar pull-right" />)}

16.4. calli:body-hgroup

Copies the template's h1 or hgroup element.


<body>
    {calli:body-hgroup()}
</body>

16.5. calli:body-nodes

Copies the templates body XML nodes that follow the h1, hgroup, and sidebar elements (or all nodes if none exist).


<div class="tab-content">
    {calli:body-nodes()}
</div>

16.6. calli:head-links

Copies the @href and other links from the template's <link> element that include a @title. The attributes are copied to the first given element and the @title is used as the content. The second given element is also returned if the template has titled <link> elements at all.


<menu type="list">
    {calli:head-links(<li><a /></li>,<li class="divider" />)}
</menu>

16.7. calli:styles-href

Adds an @href, of the default style sheet, to the given element.


{calli:styles-href(<link rel="stylesheet" />)}

16.8. calli:scripts-src

Adds @src, of the default script bundle, to the given element.


{calli:scripts-src(<script type="text/javascript" />)}

16.9. calli:lookup-form

Returns an HTML search form, searching the current realm, with the given string as a placeholder.


<div class="navbar-search pull-right hidden-logout">{calli:lookup-form('Lookup...')}</div>

16.10. calli:breadcrumb-links

Creates a placeholder for breadcrumbs that will use the given link element, an optional divider, and active element. @href and text content will be added to the given link element.


<nav class="breadcrumb">{calli:breadcrumb-links(<a class="muted"/>, <span class="divider">&#187;</span>, <span class="active"/>)}</nav>

16.11. calli:activate-nav

Create a placeholder element that will add @class="active" and remove @href and @onclick, to any <a> element with a @href of the query string (starting with '?').


{calli:activate-nav(<nav class="nav-tabs">
    <a href="?view">View</a>
    <a href="?edit">Edit</a>
</nav>)}

16.12. calli:lastmod-time

Create a place holder element that will subsitute the <time> element within the given element with the last modification timestamp of the resource, or nothing if unknown.


<footer>
    {calli:lastmod-time(<p>This resource was last modified at <time class="abbreviated"/></p>)}
</footer>

16.13. calli:error-alert

Creates an error template that will be used by calli.error. An error message is appended to a copy of the given element.


{calli:error-alert(<div class="alert alert-error alert-block">
    <button type="button" class="close" data-dismiss="alert">×</button>
    <h4>Oops!</h4>
</div>)}

16.14. calli:generator-p

Appends markup about Callimachus to the given element.


<footer>
    {calli:generator-p(<p class="pull-right" />)}
</footer>

16.15. calli:home-href

Adds an @href to the given element that links to the home folder's directory target.


<header>
    {calli:home-href(<a>Callimachus</a>)}
</header>

16.16. calli:folder-href

Adds an @href to the given element for the view page of the home folder.


<menu type="list" class="dropdown-menu">
    <li>{calli:folder-href(<a>Home folder</a>)}</li>
</menu>

16.17. calli:changes-href

Adds an @href to the give element that links to the recent changes for the current realm.


<menu type="list" class="dropdown-menu">
    <li>{calli:folder-href(<a>Home folder</a>)}</li>
    <li>{calli:changes-href(<a>Recent changes</a>)}</li>
</menu>

16.18. calli:view-href

Adds @href to the given element that links to the view page of the current resource.


<nav class="nav-tabs">
    {calli:view-href(<a>View</a>)}
    {calli:edit-href(<a>Edit</a>)}
    {calli:discussion-href(<a>Discussion</a>)}
    {calli:describe-href(<a>Describe</a>)}
    {calli:history-href(<a>History</a>)}
</nav>

16.19. calli:edit-href

Adds @href to the given element that links to the edit page of the current resource.


<nav class="nav-tabs">
    {calli:view-href(<a>View</a>)}
    {calli:edit-href(<a>Edit</a>)}
    {calli:discussion-href(<a>Discussion</a>)}
    {calli:describe-href(<a>Describe</a>)}
    {calli:history-href(<a>History</a>)}
</nav>

16.20. calli:discussion-href

Adds @href to the given element that links to the discussion page of the current resource.


<nav class="nav-tabs">
    {calli:view-href(<a>View</a>)}
    {calli:edit-href(<a>Edit</a>)}
    {calli:discussion-href(<a>Discussion</a>)}
    {calli:describe-href(<a>Describe</a>)}
    {calli:history-href(<a>History</a>)}
</nav>

16.21. calli:describe-href

Adds @href to the given element that links to the describe page of the current resource.


<nav class="nav-tabs">
    {calli:view-href(<a>View</a>)}
    {calli:edit-href(<a>Edit</a>)}
    {calli:discussion-href(<a>Discussion</a>)}
    {calli:describe-href(<a>Describe</a>)}
    {calli:history-href(<a>History</a>)}
</nav>

16.22. calli:history-href

Adds @href to the given element that links to the history page of the current resource.


<nav class="nav-tabs">
    {calli:view-href(<a>View</a>)}
    {calli:edit-href(<a>Edit</a>)}
    {calli:discussion-href(<a>Discussion</a>)}
    {calli:describe-href(<a>Describe</a>)}
    {calli:history-href(<a>History</a>)}
</nav>

16.23. calli:whatlinkshere-href

Adds @href to the give element that links to the what-links-here page of the current resource.


{calli:whatlinkshere-href(<a>What links here</a>)}

16.24. calli:relatedchanges-href

Adds @href to the given element that links to the related changes page of the current resource.


{calli:relatedchanges-href(<a>Related changes</a>)}

16.25. calli:permissions-href

Adds @href to the given element that links to the permission page of the current resource.


{calli:permissions-href(<a>Permissions</a>)}

16.26. calli:introspect-href

Adds @href to the given element that links to the introspect page of the current resource.


{calli:introspect-href(<a>Introspect resource</a>)}

16.27. calli:login-href

Adds attributes to the given element that are needed to activate the login process.


<menu type="toolbar">
    <li class="hidden-login">{calli:login-href(<a>Sign in</a>)}</li>
</menu>

16.28. calli:profile-href

Adds attributes to the given element that will link to the current user's identifier/profile page. The content of the element will be replace.


{calli:profile-href(<a>My account</a>)}

16.29. calli:logout-href

Adds attributes to the given element that will initiate the logout sequence when clicked.


{calli:logout-href(<a>Sign out</a>)}

Chapter 17. SPARQL Reference

SPARQL is a W3C recommended query language for RDF.

17.1. keyword:phone

All of the words in the values of the listed properties will also be indexed using the predicate keyword:phone that can be used to search for resources by label word.


PREFIX keyword:<http://www.openrdf.org/rdf/2011/keyword#>

SELECT ?resource
WHERE {
    ?resource keyword:phone ?soundex
    FILTER sameTerm(?soundex, keyword:soundex("example"))
    FILTER EXISTS { ?resource ?p ?term FILTER regex(?term, keyword:regex("example")) }
}

17.2. keyword:soundex

The keyword:soundex SPARQL function converts the given string into a soundex code (comatible with keyword:phone).

17.3. keyword:regex

The keyword:regex SPARQL function provides a accent/case-insensitive regular expression that can be used to further filter the match.

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

Chapter 18. Callimachus REST API

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.

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

18.1.1. 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 …
18.1.2. 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.

18.2. 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"/>

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

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

18.3.2. 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
...
18.3.3. 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
...

18.4. CRUD operations on BLOB content

18.4.1. 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
18.4.2. 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.

18.4.3. 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
18.4.4. 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.

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

18.5. CRUD operations on RDF content

18.5.1. 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
18.5.2. 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/
18.5.3. 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.

18.5.4. 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
...
18.5.5. 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.

18.6. Searching content

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

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

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

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

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