<commit_before># Anno4j

> This library provides programmatic access the [W3C Web Annotation Data Model](http://www.w3.org/TR/annotation-model/) (formerly known as the [W3C Open Annotation Data Model](http://www.openannotation.org/spec/core/)) to allow annotations to be written from and to local or remote SPARQL endpoints. An easy-to-use and extensible Java API allows creation and querying of annotations even for non-experts.  

## Build Status
master branch: [![Build Status](https://travis-ci.org/anno4j/anno4j.svg?branch=master)](https://travis-ci.org/anno4j/anno4j) develop branch: [![Build Status](https://travis-ci.org/anno4j/anno4j.svg?branch=develop)](https://travis-ci.org/anno4j/anno4j)

## Features:

- Extensible creation of Web/Open Annotations based on Java Annotations syntax
- Built-in and predefined implementations for nearly all RDF classes conform to the W3C Web Annotation Data Model
- Created (and annotated) Java POJOs are transformed to RDF and automatically transmitted to local/remote SPARQL 1.1 endpoints using the SPARQL Update functionality
- Querying of annotations with path-based criteria
    - [x] Basic comparisons like "equal", "greater", and "lower"
    - [x] String comparisons: "equal", "contains", "starts with", and "ends with"
    - [x] Union of different paths
    - [x] Type condition
    - [x] Custom filters
    
## Outline
- [Introduction](#introduction)
- [Getting Started](#getting-started)
    - [Installation](#Installation)
    - [Configuration](#configuration)
    - [Create and Save Annotations](#create-and-save-annotations)
    - [Query for Annotations](#query-for-annotations)
    - [Transactions](#transactions)
    - [Graph Context](#graph-context)
    - [Input and Output](#input-and-output)
- [Example](#example)
- [Restrictions](#restrictions)
- [Contributors](#contributors)
- [License](#license)

## Introduction
Anno4j is a Java RDF library to easily cope with annotations conform to the Web Annotation Data Model / Open Annotation Data Model. The library provides an extensible way to create annotations while supporting bundles of pre-defined RDF class interfaces. Annotations are automatically persisted on (locally or remotely) connected [SPARQL (SPARQL Protocol and RDF Query Language)](http://www.w3.org/TR/sparql11-overview/) endpoints without having to issue any kind of SPARQL query. Besides the creation of annotations, Anno4j also provides an easy-to-use query API based on the path-based query language [LDPath](http://marmotta.apache.org/ldpath/).

The Web Annotation Data Model / Open Annotation Data Model specification describes a structured model and format to enable (web) annotations to be shared and reused across different hardware and software platforms. The model is based on [RDF (Resource Description Framework)](http://www.w3.org/TR/rdf11-primer/), the de-facto-standard model for publishing and interlinking data over the Web.

## Getting Started

### Installation

Add the maven dependency with the respective version (current major version is 2.3.0, Anno4j is in the oss.sonatype.org repository):

```xml
<dependency>
	<groupId>com.github.anno4j</groupId>
	<artifactId>anno4j-core</artifactId>
	<version>...</version>
</dependency>
```     

### Configuration

Unlike the first versions of Anno4j, the current state does not implement the singleton pattern anymore. Without the singleton pattern, 
it is now possible to use multiple Anno4j instances and consecutively multiple triple-stores. To create an Anno4j instance,
simply use the Anno4j class constructor:

```java
    Anno4j anno4j = new Anno4j();
```

The default configuration of Anno4j is set to a local in-memory SPARQL triple-store. Anno4j is based on [Sesame](http://rdf4j.org/). To connect to your personal
local or remote SPARQL endpoint, just create a corresponding repository object (see [here](http://rdf4j.org/sesame/2.7/docs/users.docbook?view#section-repository-api) for the Sesame documentation of repositories) 
and use the corresponding setter of your Anno4j instance.

```java
    anno4j.setRepository(new SPARQLRepository("http://www.mydomain.com/sparql"));
```       

For RDF creation, Anno4j needs a central instance to generate unique identifiers. The ID generator needs to implement 
the *org.openrdf.IDGenerator* interface. To activate your ID generator, create a respective object and set it in the Anno4j instance.

```java
    anno4j.setIdGenerator(new MyIDGenerator());
```       


### Create and Save Annotations

Anno4j uses [AliBaba](https://bitbucket.org/openrdf/alibaba/) to provide an easy way to create RDF by simply annotating Java interfaces with the *@IRI* Java annotation. To indicate for example that a given 
interface is an *Annotation* you need to add "@Iri(OADM.ANNOTAION)" directly above the class declaration. 

```java
	@Iri(OADM.ANNOTATION)
    public interface Annotation extends ResourceObject { ... }
```

OADM.ANNOTATION is a predefined constant for the IRI: *http://www.w3.org/ns/oa#Annotation* (Other predefined namespaces are 
declared in the *com.github.anno4j.model.namespaces* package). When a respective instance is then persisted via Anno4j (merely the creation of the object is enough, see below), the following triple describing the type relationship is created:

    <http://example.org/exampleAnnotation> rdf:type <http://www.w3.org/ns/oa#Annotation>
 
To specify other triples and corresponding relationships, the *@Iri* annotation has to be
added directly above the respective getter/setter pair of the interface. An example for the body of an OADM annotation, utilising the IRI *@Iri(OADM.HAS_BODY)*, would look like this:

```java
    @Iri(OADM.HAS_BODY)
    Body getBody() {...};
    
    @Iri(OADM.HAS_BODY)
    void setBody(Body body) {...};
```

This would result in the following RDF triple:

    <http://example.org/exampleAnnotation> <http://www.w3.org/ns/oa#hasBody> <http://example.org/exampleBody>

Once the interface is set up with its type IRI as well as annotated getters and setters, instances of the respective interface can be created by using the *.createObject()* method. Anno4j automatically persists them at its respectively assigned triple-store. The creation of an annotation that we just defined above would look like this:

```java
	// Create Anno4j instance
	Anno4j anno4j = new Anno4j();

    // Simple Annotation and Body object
    Annotation annotation = anno4j.createObject(Annotation.class);
    
    // Modify the Annotation
    annotation.setBody( ... );
```

This would lead to the persistence of the annotation object and all of its annotated attributes to the preset repository.

### Query for Annotations

Anno4j also allows to query triple-stores without writing own SPARQL queries. Therefore it provides hibernate like criteria
queries to query against a particular class. Furthermore Anno4j supports a so-called fluent interface, that allows method chaining
and therefore helps the user to create their respective query more easily, as they are better to read and a query can be seperated into smaller bits and pieces for better convenience.

The following code shows how to get an instance of the *QueryService* (related to a given Anno4j object), which is responsible for all provided querying mechanisms. 
It also gives insight on how to use the method chaining ability of the fluent interface. 

However, before querying can happen, it is important to make sure that every namespace is known to the specific QueryService instance, if you intend to use abbreviations. A custom namespace can be registered with the following command, also displaying of how to create a QueryService ontop of a given Anno4j instance:

```java
	// Create QueryService object
	QueryService queryService = anno4j.createQueryService();
	
	// Register custom namespace with abbreviation ex
	queryService.addPrefix("ex", "http://www.example.com/schema#");
```

Using a custom namespace allows to apply its abbreviation when writing queries, so for example instead of writing *http://www.example.com/schema#SomeClass* you can write *ex:SomeClass*. Some namespaces are predefined and thereby always available without being specified. These are:

    oa:			<http://www.w3.org/ns/oa#>
    cnt:		<http://www.w3.org/2011/content#>
    dc:			<http://purl.org/dc/elements/1.1/>
    dcterms:	<http://purl.org/dc/terms/>
    dctypes:	<http://purl.org/dc/dcmitype>
    foaf:		<http://xmlns.com/foaf/0.1/>
    prov:		<http://www.w3.org/ns/prov/>
    rdf:		<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    rdfs:		<http://www.w3.org/2000/01/rdf-schema#>
    skos:		<http://www.w3.org/2004/02/skos/core#>

Once all namespaces are added, the next step consists of adding criteria to the QueryService, which will ultimately define the query that can be executed. This is done by using the *addCriteria(String ldPath)* method of the QueryService. The criteria in the *ldPath* parameter therefore must be conform to the [LDPath](http://marmotta.apache.org/ldpath/) specification. LDPath is a simple path-based query language similar to [XPath](https://www.w3.org/TR/xpath/) or [SPARQL Property Paths](https://www.w3.org/TR/sparql11-query/#propertypaths), that is particularly well-suited for querying and retrieving resources from a given RDF graph. LDPath offers a broad variety of tools to form comprehensive queries, extensive examples of how to use it in conjunction with Anno4j can be seen in the test suite found in the *com.github.anno4j.querying* package. A path criteria, testing if an Annotation has a Selector that is of the type *oa:FragmentSelector*, could look as follows:

    oa:hasTarget / oa:hasSelector[is-a oa:FragmentSelector]
    
Next to a solely path-based criteria, comparison criteria are also supported by using the *addCriteria(String ldPath, String value, Comparison comparison)* method. It allows to define the path to an RDF field that is then compared against the supported *value*/*comparison* constraint. The *value* is a basic datatype like numbers or a String, which will be compared against the value of the respective RDF field. Anno4j supports various comparison operators, such as:

- Equal (Comparison.EQ)
- Greater than (Comparison.GT)
- Greater than or equal (Comparison.GTE)
- Lower than (Comparison.LT)
- Lower than or equal (Comparison.LTE)
- String: contains (Comparison.CONTAINS)
- String: starts with (Comparison.STARTS_WITH)
- String: ends with (Comparison.ENDS_WITH)

If a comparison method is not provided, the query service will use Comparison.EQ by default. The following example code shows 
how the addCriteria function could be invoked to query for a specific value (starting from an Annotation, over the relationships *oa:hasBody* and *ex:value*) of a given body:

```java
    queryService.addCriteria("oa:hasBody/ex:value", "Example Value", Comparison.EQ);
```

After adding single or multiple criteria to the QueryService, its query can be executed. Therefore, the QueryService will automatically create a SPARQL query
according to the users' namespaces and criteria that have been defined and issues this query to retrieve the respective data from the defined triple store. To achieve this, the *.execute()* or *.execute(Class<T> type)* method has
to be invoked. The *type* parameter defines the RDF class that is used as starting point and return type for the given query. Its value is supposed to match a given Anno4j Java class. For example, one could add a specific body type (e.g. *EX.EXAMPLE_BODY*) which is also applied to the respective class), in order to start the query from there. If no *type* is supported, the default starting point is the Annotation (*OADM.ANNOTATION*).

A complete QueryService example can be seen in the following code snippet: 

```java
	QueryService queryService = anno4j.createQueryService();
   List<ExampleBody> result = queryService
        .addPrefix("ex", "http://www.example.com/schema#")
        .addCriteria("^oa:hasBody/dcterms:modified, "2016-01-28T12:00:00Z", Comparison.EQ)
        .addCriteria("ex:confidence", 0.5, Comparison.GT)
        .execute(ExampleBody.class);
```

After registering an own namespace *ex*, the query would select and return all those body objects, that ...

- ... are of the type *ExampleBody*,
- ... are associated with an Annotation node (backwards edge indcated by *^oa:hasBody*), that was modified at the exact date of "2016-01-28T12:00:00Z", and
- ... have a confidence value assigned (relationship *ex:confidence*), that is higher 0.5.

### Transactions

Anno4j's persistence and querying can be enhanced with a transactional behaviour. This means that the library runs their commands in atomic units of work. Consequenctly, one array of commands is either fully executed (*commited*) or not at all (*rolled back*). This enables the database to be consistent at every possible time.

Many of Anno4j's basic methods are set to auto-commit, but it also supports the *createTransaction()* method to create a transaction of your own, which needs to be started, and then committed or rolled back manually in order to have effect.

An exemplary code snippet can be seen here (note that the begin and commit of the transaction are essential!):

```java
	Anno4j anno4j = new Anno4j();
	
	Transaction transaction = anno4j.createTransaction();
	transaction.begin();
	
	// Create and query different things over the transaction
	transaction.createObject(...);
	QueryService qs = transaction.createQueryService();
	
	transaction.commit();
```

### Graph Context

Anno4j does support the RDF graph functionality which uses subgraphs and turns triples into quadruples to allow further structuring of ones data in a more fine-grained way. This can be done either at the Anno4j object or at the Transaction object directly. Two out of the four *createObject(...)* methods of the Anno4j class support an URI parameter called *context* which is uzilised for the subgraph. The Transaction class supports a *setAllContexts(URI context)* method to set a subgraph for the whole transaction.

```java
	URI uri = new URIImpl("http://www.somePage.com/");

	Annotation annotation = anno4j.createObject(Annotation.class, uri);
	
	Transaction transaction = anno4j.createTransaction();
	transaction.setAllContexts(uri);
```

### Input and Output

To improve the usability of the library, a small extension to the "ORM" (Object-RDF-Mapping) has been implemented. Users can parse their RDF triples formulated in various RDF serialisations to create the respective Java objects, as well as write their Java objects to serialised RDF triples. Among the available serialisations are rdf/xml, ntriples, turtle, n3, jsonld, rdf/json, etc.

In order to read a given RDF annotation (available as Java String), an *ObjectParser* object is needed. Its *.parse(String annotation, String uri, RDFFormat format)* requires the *annotation* as String, a *uri* for namespacing, and the supported *format* (The Java Class *RDFFormat* holds constant for all supported serialisations). It will then return a Java List of parsed Annotations. Important to note is, that all RDF nodes that are to be parsed need to be supported as respective Anno4j interfaces. The ObjectParser holds all parsed annotations in a local temporary memory store. In order to persist them to your respective database, they have to be read from the parser and be persisted "by hand" then. The following shows an example of how to read a turtle annotation.

```java   
String TURTLE = "@prefix oa: <http://www.w3.org/ns/oa#> ." +
            "@prefix ex: <http://www.example.com/ns#> ." +
            "@prefix dctypes: <http://purl.org/dc/dcmitype/> ." +
            "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ." +

            "ex:anno1 a oa:Annotation ;" +
            "   oa:hasBody ex:body1 ;" +
            "   oa:hasTarget ex:target1 .";
            
URL url = new URL("http://example.com/");

ObjectParser objectParser = new ObjectParser();
List<Annotation> annotations = objectParser.parse(TURTLE, url, RDFFormat.TURTLE);

objectParser.shutdown();
```

To write a given Anno4j Java object to respective RDF serialisations, the *ResourceObject* interface (which every Anno4j object descends from) supports a *.getTriples(RDFFormat format)* method, which returns the representation of the object as a Java String in the supported *format*. The following shows an example that writes a given annotation as turtle triples.

```java   
Annotation annotation = anno4j.createObject(Annotation.class);

// Add something to the Annotation

String annotationAsTurtle = annotation.getTriples(RDFFormat.TURTLE);
```

## Generating annotated Java files from an existing ontology

To make working with an existing RDFS ontology even easier, the Java classes required by Anno4j can be automatically generated.
In order to do so a `OntGenerationConfig` object must be created suiting your requirements.

This configuration object is then used to create the Java files:
```java
JavaFileGenerator generator = new RDFSJavaFileGenerator();
generator.addRDF("http://example.com/your_ontology.xml");

File outputDir = new File("/path/to/destination");
generator.generateJavaFiles(config, outputDir);
```

For each RDFS class a Anno4j resource object class and a support class is created.
If you want to have the ontology information persisted to your Anno4j underlying
triplestore, you can do so by passing the Anno4j object to the generator.

```java
Anno4j anno4j = new Anno4j();
anno4j.setRepository(...);
// ...
JavaFileGenerator generator = new RDFSJavaFileGenerator(anno4j);
```


### Language preferences

The purpose of the `OntGenerationConfig` basically is defining a preference for the languages to use for class names and JavaDoc.
Those are extracted from `rdfs:label` and `rdfs:comment` literals.

```
OntGenerationConfig config = new OntGenerationConfig();

// Set which language you prefer for class names and for JavaDoc:
config.setIdentifierLanguagePreference(new String[] {"en", "de"});
config.setJavaDocLanguagePreference(new String[] {"de"});
```

In this example only german JavaDoc should be generated, but the names of Java classes should be preferably in english.
See [BCP47](https://tools.ietf.org/html/bcp47) for the language codes.

### Validation of datatypes

Validation code can be automatically generated, checking that the value set for a property
is actually allowed by the datatype defined in the ontology.

For example a call `addFoo(-42)` for a property `foo` with datatype `xsd:nonNegativeInteger` will throw a `IllegalArgumentException`.
The generation of such checks can controlled by providing validators to the `OntGenerationConfig`.

```java
ValidatorChain validators = new ValidatorChain();
validators.add(new NotNullValidator());
config.setValidators(validators);
```
In this example only checks for the value being not null will be added to the generated method implementations.
If no validator chain is explicitly provided, checks for `null` and the XSD datatypes are generated.
If you want checks for your custom datatypes, you can implement the `Validator` interface.


## Example

The following will guide through an exemplary process of producing a whole annotation from scratch. The exemplary annotation that is
used is conform to the [complete example](http://www.w3.org/TR/2014/WD-annotation-model-20141211/#complete-example) that
is shown at the end of an older version of the [Web Annotation Data Model specification](http://www.w3.org/TR/annotation-model/). We adopted some of the values to newer namings, although most of the old ones are still supported as deprecated methods.

The first step is to create an annotation using the *.createObject* method of the Anno4j object, which will be typed accordingly 
(via the relationship *rdf:type* as an *oa:Annotation*) on its own:

```java
    Anno4j anno4j = new Anno4j();
    
    // Create the base annotation
    Annotation annotation = anno4j.createObject(Annotation.class);
```

Then, provenance information is supported for the annotation. The timestamps *oa:annotatedAt* and *oa:serializedAt* are
supported by simply filling the members of the Annotation class:

```java
	// formerly annotatedAt<commit_msg>Extended description of Java file generation.<commit_after># Anno4j

> This library provides programmatic access the [W3C Web Annotation Data Model](http://www.w3.org/TR/annotation-model/) (formerly known as the [W3C Open Annotation Data Model](http://www.openannotation.org/spec/core/)) to allow annotations to be written from and to local or remote SPARQL endpoints. An easy-to-use and extensible Java API allows creation and querying of annotations even for non-experts.  

## Build Status
master branch: [![Build Status](https://travis-ci.org/anno4j/anno4j.svg?branch=master)](https://travis-ci.org/anno4j/anno4j) develop branch: [![Build Status](https://travis-ci.org/anno4j/anno4j.svg?branch=develop)](https://travis-ci.org/anno4j/anno4j)

## Features:

- Extensible creation of Web/Open Annotations based on Java Annotations syntax
- Built-in and predefined implementations for nearly all RDF classes conform to the W3C Web Annotation Data Model
- Created (and annotated) Java POJOs are transformed to RDF and automatically transmitted to local/remote SPARQL 1.1 endpoints using the SPARQL Update functionality
- Querying of annotations with path-based criteria
    - [x] Basic comparisons like "equal", "greater", and "lower"
    - [x] String comparisons: "equal", "contains", "starts with", and "ends with"
    - [x] Union of different paths
    - [x] Type condition
    - [x] Custom filters
    
## Outline
- [Introduction](#introduction)
- [Getting Started](#getting-started)
    - [Installation](#Installation)
    - [Configuration](#configuration)
    - [Create and Save Annotations](#create-and-save-annotations)
    - [Query for Annotations](#query-for-annotations)
    - [Transactions](#transactions)
    - [Graph Context](#graph-context)
    - [Input and Output](#input-and-output)
- [Example](#example)
- [Restrictions](#restrictions)
- [Contributors](#contributors)
- [License](#license)

## Introduction
Anno4j is a Java RDF library to easily cope with annotations conform to the Web Annotation Data Model / Open Annotation Data Model. The library provides an extensible way to create annotations while supporting bundles of pre-defined RDF class interfaces. Annotations are automatically persisted on (locally or remotely) connected [SPARQL (SPARQL Protocol and RDF Query Language)](http://www.w3.org/TR/sparql11-overview/) endpoints without having to issue any kind of SPARQL query. Besides the creation of annotations, Anno4j also provides an easy-to-use query API based on the path-based query language [LDPath](http://marmotta.apache.org/ldpath/).

The Web Annotation Data Model / Open Annotation Data Model specification describes a structured model and format to enable (web) annotations to be shared and reused across different hardware and software platforms. The model is based on [RDF (Resource Description Framework)](http://www.w3.org/TR/rdf11-primer/), the de-facto-standard model for publishing and interlinking data over the Web.

## Getting Started

### Installation

Add the maven dependency with the respective version (current major version is 2.3.0, Anno4j is in the oss.sonatype.org repository):

```xml
<dependency>
	<groupId>com.github.anno4j</groupId>
	<artifactId>anno4j-core</artifactId>
	<version>...</version>
</dependency>
```     

### Configuration

Unlike the first versions of Anno4j, the current state does not implement the singleton pattern anymore. Without the singleton pattern, 
it is now possible to use multiple Anno4j instances and consecutively multiple triple-stores. To create an Anno4j instance,
simply use the Anno4j class constructor:

```java
    Anno4j anno4j = new Anno4j();
```

The default configuration of Anno4j is set to a local in-memory SPARQL triple-store. Anno4j is based on [Sesame](http://rdf4j.org/). To connect to your personal
local or remote SPARQL endpoint, just create a corresponding repository object (see [here](http://rdf4j.org/sesame/2.7/docs/users.docbook?view#section-repository-api) for the Sesame documentation of repositories) 
and use the corresponding setter of your Anno4j instance.

```java
    anno4j.setRepository(new SPARQLRepository("http://www.mydomain.com/sparql"));
```       

For RDF creation, Anno4j needs a central instance to generate unique identifiers. The ID generator needs to implement 
the *org.openrdf.IDGenerator* interface. To activate your ID generator, create a respective object and set it in the Anno4j instance.

```java
    anno4j.setIdGenerator(new MyIDGenerator());
```       


### Create and Save Annotations

Anno4j uses [AliBaba](https://bitbucket.org/openrdf/alibaba/) to provide an easy way to create RDF by simply annotating Java interfaces with the *@IRI* Java annotation. To indicate for example that a given 
interface is an *Annotation* you need to add "@Iri(OADM.ANNOTAION)" directly above the class declaration. 

```java
	@Iri(OADM.ANNOTATION)
    public interface Annotation extends ResourceObject { ... }
```

OADM.ANNOTATION is a predefined constant for the IRI: *http://www.w3.org/ns/oa#Annotation* (Other predefined namespaces are 
declared in the *com.github.anno4j.model.namespaces* package). When a respective instance is then persisted via Anno4j (merely the creation of the object is enough, see below), the following triple describing the type relationship is created:

    <http://example.org/exampleAnnotation> rdf:type <http://www.w3.org/ns/oa#Annotation>
 
To specify other triples and corresponding relationships, the *@Iri* annotation has to be
added directly above the respective getter/setter pair of the interface. An example for the body of an OADM annotation, utilising the IRI *@Iri(OADM.HAS_BODY)*, would look like this:

```java
    @Iri(OADM.HAS_BODY)
    Body getBody() {...};
    
    @Iri(OADM.HAS_BODY)
    void setBody(Body body) {...};
```

This would result in the following RDF triple:

    <http://example.org/exampleAnnotation> <http://www.w3.org/ns/oa#hasBody> <http://example.org/exampleBody>

Once the interface is set up with its type IRI as well as annotated getters and setters, instances of the respective interface can be created by using the *.createObject()* method. Anno4j automatically persists them at its respectively assigned triple-store. The creation of an annotation that we just defined above would look like this:

```java
	// Create Anno4j instance
	Anno4j anno4j = new Anno4j();

    // Simple Annotation and Body object
    Annotation annotation = anno4j.createObject(Annotation.class);
    
    // Modify the Annotation
    annotation.setBody( ... );
```

This would lead to the persistence of the annotation object and all of its annotated attributes to the preset repository.

### Query for Annotations

Anno4j also allows to query triple-stores without writing own SPARQL queries. Therefore it provides hibernate like criteria
queries to query against a particular class. Furthermore Anno4j supports a so-called fluent interface, that allows method chaining
and therefore helps the user to create their respective query more easily, as they are better to read and a query can be seperated into smaller bits and pieces for better convenience.

The following code shows how to get an instance of the *QueryService* (related to a given Anno4j object), which is responsible for all provided querying mechanisms. 
It also gives insight on how to use the method chaining ability of the fluent interface. 

However, before querying can happen, it is important to make sure that every namespace is known to the specific QueryService instance, if you intend to use abbreviations. A custom namespace can be registered with the following command, also displaying of how to create a QueryService ontop of a given Anno4j instance:

```java
	// Create QueryService object
	QueryService queryService = anno4j.createQueryService();
	
	// Register custom namespace with abbreviation ex
	queryService.addPrefix("ex", "http://www.example.com/schema#");
```

Using a custom namespace allows to apply its abbreviation when writing queries, so for example instead of writing *http://www.example.com/schema#SomeClass* you can write *ex:SomeClass*. Some namespaces are predefined and thereby always available without being specified. These are:

    oa:			<http://www.w3.org/ns/oa#>
    cnt:		<http://www.w3.org/2011/content#>
    dc:			<http://purl.org/dc/elements/1.1/>
    dcterms:	<http://purl.org/dc/terms/>
    dctypes:	<http://purl.org/dc/dcmitype>
    foaf:		<http://xmlns.com/foaf/0.1/>
    prov:		<http://www.w3.org/ns/prov/>
    rdf:		<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    rdfs:		<http://www.w3.org/2000/01/rdf-schema#>
    skos:		<http://www.w3.org/2004/02/skos/core#>

Once all namespaces are added, the next step consists of adding criteria to the QueryService, which will ultimately define the query that can be executed. This is done by using the *addCriteria(String ldPath)* method of the QueryService. The criteria in the *ldPath* parameter therefore must be conform to the [LDPath](http://marmotta.apache.org/ldpath/) specification. LDPath is a simple path-based query language similar to [XPath](https://www.w3.org/TR/xpath/) or [SPARQL Property Paths](https://www.w3.org/TR/sparql11-query/#propertypaths), that is particularly well-suited for querying and retrieving resources from a given RDF graph. LDPath offers a broad variety of tools to form comprehensive queries, extensive examples of how to use it in conjunction with Anno4j can be seen in the test suite found in the *com.github.anno4j.querying* package. A path criteria, testing if an Annotation has a Selector that is of the type *oa:FragmentSelector*, could look as follows:

    oa:hasTarget / oa:hasSelector[is-a oa:FragmentSelector]
    
Next to a solely path-based criteria, comparison criteria are also supported by using the *addCriteria(String ldPath, String value, Comparison comparison)* method. It allows to define the path to an RDF field that is then compared against the supported *value*/*comparison* constraint. The *value* is a basic datatype like numbers or a String, which will be compared against the value of the respective RDF field. Anno4j supports various comparison operators, such as:

- Equal (Comparison.EQ)
- Greater than (Comparison.GT)
- Greater than or equal (Comparison.GTE)
- Lower than (Comparison.LT)
- Lower than or equal (Comparison.LTE)
- String: contains (Comparison.CONTAINS)
- String: starts with (Comparison.STARTS_WITH)
- String: ends with (Comparison.ENDS_WITH)

If a comparison method is not provided, the query service will use Comparison.EQ by default. The following example code shows 
how the addCriteria function could be invoked to query for a specific value (starting from an Annotation, over the relationships *oa:hasBody* and *ex:value*) of a given body:

```java
    queryService.addCriteria("oa:hasBody/ex:value", "Example Value", Comparison.EQ);
```

After adding single or multiple criteria to the QueryService, its query can be executed. Therefore, the QueryService will automatically create a SPARQL query
according to the users' namespaces and criteria that have been defined and issues this query to retrieve the respective data from the defined triple store. To achieve this, the *.execute()* or *.execute(Class<T> type)* method has
to be invoked. The *type* parameter defines the RDF class that is used as starting point and return type for the given query. Its value is supposed to match a given Anno4j Java class. For example, one could add a specific body type (e.g. *EX.EXAMPLE_BODY*) which is also applied to the respective class), in order to start the query from there. If no *type* is supported, the default starting point is the Annotation (*OADM.ANNOTATION*).

A complete QueryService example can be seen in the following code snippet: 

```java
	QueryService queryService = anno4j.createQueryService();
   List<ExampleBody> result = queryService
        .addPrefix("ex", "http://www.example.com/schema#")
        .addCriteria("^oa:hasBody/dcterms:modified, "2016-01-28T12:00:00Z", Comparison.EQ)
        .addCriteria("ex:confidence", 0.5, Comparison.GT)
        .execute(ExampleBody.class);
```

After registering an own namespace *ex*, the query would select and return all those body objects, that ...

- ... are of the type *ExampleBody*,
- ... are associated with an Annotation node (backwards edge indcated by *^oa:hasBody*), that was modified at the exact date of "2016-01-28T12:00:00Z", and
- ... have a confidence value assigned (relationship *ex:confidence*), that is higher 0.5.

### Transactions

Anno4j's persistence and querying can be enhanced with a transactional behaviour. This means that the library runs their commands in atomic units of work. Consequenctly, one array of commands is either fully executed (*commited*) or not at all (*rolled back*). This enables the database to be consistent at every possible time.

Many of Anno4j's basic methods are set to auto-commit, but it also supports the *createTransaction()* method to create a transaction of your own, which needs to be started, and then committed or rolled back manually in order to have effect.

An exemplary code snippet can be seen here (note that the begin and commit of the transaction are essential!):

```java
	Anno4j anno4j = new Anno4j();
	
	Transaction transaction = anno4j.createTransaction();
	transaction.begin();
	
	// Create and query different things over the transaction
	transaction.createObject(...);
	QueryService qs = transaction.createQueryService();
	
	transaction.commit();
```

### Graph Context

Anno4j does support the RDF graph functionality which uses subgraphs and turns triples into quadruples to allow further structuring of ones data in a more fine-grained way. This can be done either at the Anno4j object or at the Transaction object directly. Two out of the four *createObject(...)* methods of the Anno4j class support an URI parameter called *context* which is uzilised for the subgraph. The Transaction class supports a *setAllContexts(URI context)* method to set a subgraph for the whole transaction.

```java
	URI uri = new URIImpl("http://www.somePage.com/");

	Annotation annotation = anno4j.createObject(Annotation.class, uri);
	
	Transaction transaction = anno4j.createTransaction();
	transaction.setAllContexts(uri);
```

### Input and Output

To improve the usability of the library, a small extension to the "ORM" (Object-RDF-Mapping) has been implemented. Users can parse their RDF triples formulated in various RDF serialisations to create the respective Java objects, as well as write their Java objects to serialised RDF triples. Among the available serialisations are rdf/xml, ntriples, turtle, n3, jsonld, rdf/json, etc.

In order to read a given RDF annotation (available as Java String), an *ObjectParser* object is needed. Its *.parse(String annotation, String uri, RDFFormat format)* requires the *annotation* as String, a *uri* for namespacing, and the supported *format* (The Java Class *RDFFormat* holds constant for all supported serialisations). It will then return a Java List of parsed Annotations. Important to note is, that all RDF nodes that are to be parsed need to be supported as respective Anno4j interfaces. The ObjectParser holds all parsed annotations in a local temporary memory store. In order to persist them to your respective database, they have to be read from the parser and be persisted "by hand" then. The following shows an example of how to read a turtle annotation.

```java   
String TURTLE = "@prefix oa: <http://www.w3.org/ns/oa#> ." +
            "@prefix ex: <http://www.example.com/ns#> ." +
            "@prefix dctypes: <http://purl.org/dc/dcmitype/> ." +
            "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ." +

            "ex:anno1 a oa:Annotation ;" +
            "   oa:hasBody ex:body1 ;" +
            "   oa:hasTarget ex:target1 .";
            
URL url = new URL("http://example.com/");

ObjectParser objectParser = new ObjectParser();
List<Annotation> annotations = objectParser.parse(TURTLE, url, RDFFormat.TURTLE);

objectParser.shutdown();
```

To write a given Anno4j Java object to respective RDF serialisations, the *ResourceObject* interface (which every Anno4j object descends from) supports a *.getTriples(RDFFormat format)* method, which returns the representation of the object as a Java String in the supported *format*. The following shows an example that writes a given annotation as turtle triples.

```java   
Annotation annotation = anno4j.createObject(Annotation.class);

// Add something to the Annotation

String annotationAsTurtle = annotation.getTriples(RDFFormat.TURTLE);
```

## Generating annotated Java files from an existing ontology

To make working with an existing RDFS ontology even easier, the Java classes required by Anno4j can be automatically generated.

Simply add your ontology data to a `RDFSJavaFileGenerator`. 
It does the inferencing, type checking and schema logic for you:
```java
OntGenerationConfig config = new OntGenerationConfig();
// Set your preferences with config (see below)...

JavaFileGenerator generator = new RDFSJavaFileGenerator();
generator.addRDF("http://example.com/your_ontology.rdf.xml");

File outputDir = new File("/path/to/destination");
generator.generateJavaFiles(config, outputDir);
```

For each RDFS class a Anno4j resource object class and a support class is created in `outputDir`.
Consider the following definition of a RDFS class in the input:

```xml
<rdfs:Class rdf:about="http://example.de/#Player">
    <rdfs:comment>A user playing a game.</rdfs:comment>
</rdfs:Class>

<rdf:Description rdf:about="http://example.de/#score">
    <rdfs:domain rdf:resource="http://example.de/#Player"/>
    <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"/>
</rdf:Description>
```

The following resource object class would be generated:

```java
/**
 * A user playing a game.
 * Generated class for http://example.de/#Player */
@Iri("http://example.de/#Player")
public interface Player extends ResourceObject {

    Set<Integer> getScores();
    
    void setScores(Set<Integer> scores);

    // ...
}
```

Furthermore a support class is generated implementing checks:
```java
// ...
/**
   *
   * @param scores The elements to set.
   * @throws IllegalArgumentException If values is not in the value space.
   * The value space is defined as:<ol>
   * 	<li>The value space is the infinite set {0,1,2,...}.</li>
   * </ol> */
  @Override
  public void setScores(Set<Integer> scores) {
    for(Integer current : scores) {
        if(current < 0) {
            throw new IllegalArgumentException("Value must be non-negative.");
        }
    }
  }
// ...
```

If you want to have the ontology information persisted to your Anno4j underlying
triplestore, you can do so by passing the Anno4j object to the generator.

```java
Anno4j anno4j = new Anno4j();
anno4j.setRepository(...);
// ...
JavaFileGenerator generator = new RDFSJavaFileGenerator(anno4j);
```


### Language preferences

The purpose of the `OntGenerationConfig` basically is defining a preference for the natural languages to use for class names and JavaDoc.
Those are extracted from `rdfs:label` and `rdfs:comment` literals.

```
OntGenerationConfig config = new OntGenerationConfig();

// Set which language you prefer for class names and for JavaDoc:
config.setIdentifierLanguagePreference(new String[] {"en", "de"});
config.setJavaDocLanguagePreference(new String[] {"de"});
```

In this example only german JavaDoc should be generated, but the names of Java classes should be preferably in english.
See [BCP47](https://tools.ietf.org/html/bcp47) for the language codes.

### Validation of datatypes

Validation code can be automatically generated, checking that the value set for a property
is actually allowed by the datatype defined in the ontology.

For example a call `addWeight(-42)` for a property `weight` with datatype `xsd:nonNegativeInteger` will throw a `IllegalArgumentException`.
The generation of such checks can be controlled by providing validators to the `OntGenerationConfig`.

```java
ValidatorChain validators = new ValidatorChain();
validators.add(new NotNullValidator());
config.setValidators(validators);
```
In this example only checks for the value being not null will be added to the generated method implementations.
If no validator chain is explicitly provided, checks for `null` and the XSD datatypes are generated.

#### Validators for custom datatypes

Maybe your ontology uses some datatypes that are not from the XSD vocabulary.
In this case you can define your own validators and add them to the `OntGenerationConfig`s
validator chain.
Assume there is a datatype `ex:oddInt` which has as value space all integers that are odd.
Lets define a validator class for this datatype:

```java
class OddIntegerValidator implements Validator {

    @Override
    public void addValueSpaceCheck(MethodSpec.Builder methodBuilder, ParameterSpec symbol, RDFSClazz range) {
        // Generate the value space check:
        methodBuilder.addStatement("int i = $T.parseInt($N.toString())", ClassName.get(Integer.class), symbol) // Convert to int
                     .beginControlFlow("if(i % 2 == 0)")
                     .addStatement("throw new $T($S)", ClassName.get(IllegalArgumentException.class), "Value must be odd.")
                     .endControlFlow();
    }

    @Override
    public String getValueSpaceDefinition(RDFSClazz clazz) {
        // Human readable value space definition as used in JavaDoc:
        return "Value must be an odd integer.";
    }

    @Override
    public boolean isValueSpaceConstrained(RDFSClazz clazz) {
        // This validator only constrains ex:oddInt:
        return clazz.getResourceAsString().equals("http://example.de/ont#oddInt");
    }
}
```
The first method generates the actual validation code. For details on the syntax see
[JavaPoet](https://github.com/square/javapoet).
The convention for validators is that they throw an `IllegalArgumentException` if the value is not in the datatypes value space.
Note also that Anno4j Java file generation maps all unknown datatypes (must be subclass of `rdfs:Literal`) to the Java type `CharSequence`.
Thus it may be necessary to convert types, as above with `Integer.parseInt()`.

The second method simply returns a human readable definition of the value space, which is used in generated JavaDoc.
The third method checks if the given class is covered by this validator (thus a check should be generated).

Now you can add an instance of your custom validator to the generation configuration object.

```java
ValidatorChain chain = ValidatorChain.getRDFSDefault();
chain.add(new OddIntegerValidator());
config.setValidators(chain);
```

The set- and add-methods of properties with `ex:oddInt` will now throw an exception if they get an value that is even.

```java
public void setHasOddNums(Set<? extends CharSequence> hasOddNums) {
    // ...
    for(CharSequence current : hasOddNums) {
      int i = Integer.parseInt(current.toString());
      if(i % 2 == 0) {
        throw new IllegalArgumentException("Value must be odd.");
      }
    }
    // ...
}
```

## Example

The following will guide through an exemplary process of producing a whole annotation from scratch. The exemplary annotation that is
used is conform to the [complete example](http://www.w3.org/TR/2014/WD-annotation-model-20141211/#complete-example) that
is shown at the end of an older version of the [Web Annotation Data Model specification](http://www.w3.org/TR/annotation-model/). We adopted some of the values to newer namings, although most of the old ones are still supported as deprecated methods.

The first step is to create an annotation using the *.createObject* method of the Anno4j object, which will be typed accordingly 
(via the relationship *rdf:type* as an *oa:Annotation*) on its own:

```java
    Anno4j anno4j = new Anno4j();
    
    // Create the base annotation
    Annotation annotation = anno4j.createObject(Annotation.class);
```

Then, provenance information is supported for the annotation. The timestamps *oa:annotatedAt* and *oa:serializedAt* are
supported by simply filling the members of the Annotation class:

```java
	// formerly annotatedAt
{'fraction_non_alphanumeric': 0.08786319408552616, 'fraction_numerical': 0.009393047347250624, 'mean_word_length': 4.394835737665171, 'pattern_counts': {'":': 0, '<': 80, '<?xml version=': 0, '>': 81, 'https://': 17, 'lorem ipsum': 0, 'www.': 51, 'xml': 9}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3882626', 'n_tokens_mistral': 12650, 'n_tokens_neox': 11967, 'n_words': 5260}