-
Notifications
You must be signed in to change notification settings - Fork 23
Application development manual
- Table of Contents
- Customize generic application
- Customizing the form generator
- Other services
The operations to create a business application with the semantic_forms web framework are described below in the logical order.
We remind that the generic application is perfectly usable out of the box, see User_manual. However, it is better to preload common RDF vocabularies and related form specifications and I18N translations, see: preloading-rdf-content .
The more basic README information (run locally from sources or from distribution, setting a IDE project, RDF and Lucene database administration) is here:
https://github.com/jmvanel/semantic_forms/tree/master/scala/forms_play#play-framework-implementations
The forms receipe is cooked fresh at each HTTP request!
Case of existing instance:
instance URI |
form specification |----> form
ontology |
overriden labels |
Case of creating new instance:
class URI, or |
form specification |----> form
ontology |
overriden labels |
The ontologies are to be stored in the database. They specify basically:
- properties having rdfs:domain and rdfs:range.
- classes which are the domain and/or range of properties
For instance, the property foaf:currentProject goes from class foaf:Person to class foaf:Project .
Just like any data, the ontologies are managed by the semantic cache.
They can be loaded either by the top page field in the generic application
( see navigating and
loading semantic data
),
or offline by the tdb.tdbloader
Jena utility (see database administration).
An ontology (RDF vocabulary) can be created with any tool:
- with Protégé ontology editor
- in Turtle with a text editor and syntax coloring (Vim, gedit, ...)
We don't have yet the ability within semantic_forms
to create or edit an RDF vocabulary; this related to issue #24
https://github.com/jmvanel/semantic_forms/issues/24
By default, an automatic form generated in semantic_forms contains all the available RDF properties for given OWL class, for a creation form. For an pre-filled form (modification form), the form contains all the available RDF triples in the triple database.
A form specification allows to:
- specify which RDF properties, and in in which order, will be displayed for which OWL class
- specify details of how a property will be displayed for edition ( mainly, use DBPedia lookup )
Here is an example of a form specification that is loaded by program
deductions.runtime.sparql_cache.PopulateRDFCache
It says "for foaf:Person, for an empty form (creation form), use only there properties in this order" :
<personForm>
form:classDomain foaf:Person ;
form:showProperties (
foaf:givenName foaf:familyName
foaf:homepage
foaf:mbox
foaf:phone
foaf:img
foaf:topic_interest
foaf:knows
foaf:currentProject
cco:expertise
) .
See foaf.form.ttl for the complete file.
As you can see, a form specification basically is an ordered list of RDF properties. A form specification has an URI that is used in the /form web service. It is stored in the SPARQL database.
We don't have yet the ability within semantic_forms
to create or edit a form specification; this is related to issues :
https://github.com/jmvanel/semantic_forms/issues/28
https://github.com/jmvanel/semantic_forms/issues/22
However, there is a useful utility that writes a skeleton of a form specification from a given OWL class: FormSpecificationsFromVocabApp
This is the vintage, and ever valid, RDF service.
Live hosted URI's, eg. http://semantic-forms.cc:9112/ldp/semantic_forms,
return RDF, one of the 3 syntaxes according to the HTTP header "Accept".
This is called content negotiation.
There is also the service /download
which does the same thing but via a parameter "syntax" in the URL; see in a /display web page the links: Data export: Triplets Turtle - Triples JSON-LD - Triplets RDF / XML .
Here are the services specified by the SPARQL protocol W3C recommandations:
-
/sparql
: SPARQL query -
/update
: SPARQL update -
/load
: SPARQL 1.1 Graph Store ( see below )
To run /update
, you must be logged in as a user, just like when you do /edit
.
This user can be any one. There is a script that does everything: connection + /update
:
rupdate.sh
in https://github.com/jmvanel/semantic_forms/tree/master/scala/forms_play/dist/script . There is also a Python script rupdate.py .
There is a partial implementation of LDP (Linked Data Platform); the service is at '/ldp' .
It reacts to GET, POST, PUT and OPTIONS HTTP requests.
The prefix '/ldp/' is also used for URI's created by /create
forms.
Notable differences from the W3C recommandation:
- when PUTting or POSTing to relative URI
/a/b/my.ttl
, the container/a/b/
does not have to be created in advance - storing non-RDF data (e.g. images) is not implemented
LDP is a copious specification, and only the fundamental features are implemeted at the moment. The official test suite is used to track implemeted features.
The correspondance between the SPARQL database and the LDP services is thus: when PUTting or POSTing to relative URI /a/b/my.ttl
, the corresponding absolute URI will become a graph in SPARQL database, whose content will be the content sent by LDP protocol.
The /tools page has a link at bottom left.
This page is an RDF views and queries testing tool, since you can launch different tools on the same graph via a SPARQL query.
For a SPARQL construct query, these views are available:
- plain Turtle
- geographical map,
- table
For a SPARQL SELECT query, these views are available:
- plain table
- history
Once your view is tested, you can add a link to it in a Web page created in SF itself through the HTML editor.
This page is also a real RDF visual tools comparison laboratory, since you can launch different tools on the SPARQL seerver:
- YasGUI
- Sparklis,
- SPARQL surveyor
It is possible to create applications from the zip release, by calling web services from JavaScript, so without recompiling the Play! application. Several services are used for this:
-
/form
, /form-data
-
/create-data
, -
/sparql-data
, and -
/files
.
The /save
service is called by default from the forms generated by /edit
, /form
, /display?Edit=edit
.
The HTML names of the input fields are the URL-encoded string from the original triples (in Turtle) from the database. So the server is able to associate the user input with the original triple.
The /form
web service is the easiest way to generate forms within the layout of your application pages.
That is, you get the semantic_forms
form in HTML without the top and bottom of page present in the generic semantic_forms
application.
Here is an example of a web page using JavaScript to call the 3 different variants of the /form web service: http://ldp.virtual-assembly.org:9111/assets/example1.html There a 3 variants:
- Display existing data about a subject URI
- Create a new instance of a given OWL class
- Modify (edit) existing data
The HTML + JS source code is here: https://github.com/jmvanel/semantic_forms/blob/master/scala/forms_play/public/example1.html
Here is a fragment of JavaScript in this page:
// Edition: give URI instance (FOAF profile), and form specification URI
loadForm(
'/form?displayuri=' + encodeURIComponent( 'http://jmvanel.free.fr/jmv.rdf#me' ) +
'&formuri=' + encodeURIComponent( 'http://deductions-software.com/ontologies/forms#personForm' ) +
'&Edit=yes',
'edit' );
The /form-data
web service is the most flexible way to generate forms within the layout of your application pages.
This service outputs the raw data in JSON , the same data from which the form in HTML is generated in the generic semantic_forms
application.
Here is an example of calling the service: get the raw data for a view of a FOAF profile:
http://localhost:9000/form-data?displayuri=http://jmvanel.free.fr/jmv.rdf%23me
There you get the default form specification for the foaf:Person class. If you want another form specification do this:
http://localhost:9000/form-data?displayuri=http://jmvanel.free.fr/jmv.rdf%23me&formuri=http://www.virtual-assembly.org/ontologies/1.0/forms%23PersonForm
The (facultative) ) added HTTP parameter formuri is the URI of the form specification. If the form specification is not self-hosted, it must be loaded somewhere into the database, like any data or ontology; see link for loading RDF content into the database
Adding this to previous URL specifies to add or use RDF content in database located in PRIV/ directory (otherwise in default directory TDB).
&database=PRIV
Adding this to previous URL results in a edition form:
&Edit=yes
Like the /form-data
web service, the /create-data
service returns a "rich" JSON data structure described here.
It takes the same HTTP parameters as the /create web page:
uri=
formuri=
For example:
Like the /create
service, it produces a input form for creating ar instance of given class. But it has no web page header.
NOT YET IMPLEMENTED.
This format represents a list of triples, that is an RDF graph, but it's not JSON-LD; the form fileds are an array of flat JSON structures. It contains exactly the strings a,d images displayed by the forms in SF application. It has :
- all the information JSON-LD has ("subject", "property", "value")
- URI's in extenso (no prefixes), simpler for JSON developers, and not needing a JavaScript RDF library.
- computed data ready for I18N displaying: labels ("subjectLabel", "valueLabel", "label" for property), images ("thumbnail", if available)
Hopefully it can be reused also by non-RDF applications, to share web components.
Here is a JSON fragment gotten from the /form-data
service:
{
"subject" : "http://jmvanel.free.fr/jmv.rdf#me",
"title" : "Jean-Marc Vanel",
"thumbnail" : "http://jmvanel.free.fr/images/jmv_id.jpg",
"formURI" : "http://www.virtual-assembly.org/ontologies/1.0/forms#PersonForm",
"formLabel" : "forms#PersonForm",
"fields" : [
{
"subject" : "http://jmvanel.free.fr/jmv.rdf#me",
"subjectLabel" : "Jean-Marc Vanel",
"property" : "http://xmlns.com/foaf/0.1/firstName",
"label" : "firstName",
"comment" : "The first name of a person.",
"mandatory" : false,
"value" : "Jean-Marc",
"type" : "http://www.w3.org/2000/01/rdf-schema#Literal",
"widgetType" : "Text WidgetType",
"openChoice" : true,
"cardinality" : "0:*",
"htmlName" : "%3Chttp%3A%2F%2Fjmvanel.free.fr%2Fjmv.rdf%23me%3E+%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FfirstName%3E+%22Jean-Marc%22+.%0A"
},
{
"subject" : "http://jmvanel.free.fr/jmv.rdf#me",
"subjectLabel" : "Jean-Marc Vanel",
"property" : "http://xmlns.com/foaf/0.1/schoolHomepage",
"label" : "schoolHomepage",
"comment" : "A homepage of a school attended by the person.",
"mandatory" : false,
"value" : "http://www.ens-cachan.fr/",
"type" : "http://xmlns.com/foaf/0.1/Document",
"widgetType" : "URI WidgetType",
"openChoice" : true,
"cardinality" : "0:*",
"htmlName" : "%3Chttp%3A%2F%2Fjmvanel.free.fr%2Fjmv.rdf%23me%3E+%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FschoolHomepage%3E+%3Chttp%3A%2F%2Fwww.ens-cachan.fr%2F%3E+.%0A",
"valueLabel" : "http://www.ens-cachan.fr/",
"isImage" : false
},
{
"subject" : "http://jmvanel.free.fr/jmv.rdf#me",
"subjectLabel" : "Jean-Marc Vanel",
"property" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
"label" : "type",
"comment" : "The subject is an instance of a class.",
"mandatory" : false,
"value" : "http://xmlns.com/foaf/0.1/Person",
"type" : "http://www.w3.org/2000/01/rdf-schema#Class",
"widgetType" : "URI WidgetType",
"openChoice" : true,
"cardinality" : "0:*",
"htmlName" : "%3Chttp%3A%2F%2Fjmvanel.free.fr%2Fjmv.rdf%23me%3E+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3C%3E+.%0A",
"valueLabel" : "Person",
"isImage" : false
}
]}
The htmlName JSON key above is, as the name implies, an HTML name parameter that can the used as a name in an HTML form, for the /save service. This name is an URL-encoded triple in N-Triple (Turtle) syntax. This way the server knows which original triple has been modified.
The /sparql-data
service, like the /sparql
and /sparql-form
, takes in input a SPARQL query, as HTTP parameter query.
Like the /form-data
web service, the /sparql-data
service returns a "rich" JSON data structure described above.
http://localhost:9000/sparql-data?query=PREFIX+foaf%3A+%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%3E%0D%0ACONSTRUCT+{%3FP+foaf%3Aphone+%3FPH}WHERE+{GRAPH%20?G%20{%3FP+foaf%3Aphone+%3FPH+%3B+a+foaf%3APerson}}
The service /files
allows to deploy static files in local files/
directory and sub-directories. This is where you will deploy your specific application files like example1.html above. The files are served like Apache does: dynamically added files, even during runtime, are served.
Using plain Scala XHTML templates, or Play! style templates, it is possible to call the method corresponding to the /form web service: ApplicationFacade's method htmlFormElemJustFields() .
Look at the code in the package deductions.runtime.html .
When you can, in your client application, generate RDF string content, the simplest way to store it in SF is the SPARQL 1.1 Graph Store HTTP Protocol with POST and PUT. The GET portion of the Graph Store HTTP Protocol is not implemented, but a SPARQL query allows you to do it:
CONSTRUCT {? S? P? O} WHERE {GRAPH <graph_uri> {? S? P? O}}
The services are on relative URI's : /load
, /sparql
.
For load, the URL prefix is /load?graph=
, and
forms_play/dist/scripts/rload_wget.sh is an example script for loading a given TTL file to given load service in given graph (of user "bbb"). Here is an example of calling the script:
rload_wget.sh \
~/Documents/node69.csv.ttl http://localhost:9000/load user:bbb
The /load-uri
service
There is also the convenient /load-uri
service that loads content of given URI String into TDB in graph of same name.
It can be used in shell scripts to load a bunch of URI's , e.g. :
https://github.com/GrottoCenter/Karstlink-ontology/blob/master/scripts/load-grotto-entrances.sh
It is also used by the Scala script SPARQLquery2SFcacheApp, which, from a SPARQL query to another endpoint, loads URI's returned by the query into SF; in the end it is like if a user had pasted all those URI's and clicked on "Display". It amounts to make linked copies of all these semantic URI's into SF .
There is also the W3C's LDP protocol with POST, PUT, GET that does as much and more than the Graph Store HTTP Protocol. The "plus" part is not implemented in SF (like listing a container). Let's say that the Graph Store HTTP Protocol sticks more to how SF works.
/lookup uses the same HTTP API as dbPedia lookup, but for a completion in the browser language, and by class (typically foaf:Person and foaf:Organization).
If one loads dbPedia data in SF (see how-to here: mirroring dbPedia ), it is possible to obtain a Lookup service compatible with original dbPedia lookup.