PEARL: the ProjEction of Annotations Rule Language

Introduction

One of the main features of CODA is PEARL (ProjEction of Annotations Rule Language): a transformation language from Feature Structures to RDF.

In the specific technological context of CODA, PEARL is used to project UIMA annotations (expressed as feature structures specified by a UIMA Type System and stored in a UIMA CAS) onto RDF graph patterns. The language is however generic enough to be adopted in other similar environments (such as GATE) using feature structures to represent annotations.

Core elements of the language are Projection Rules, enabling users to describe matches over sets of annotations produced by UIMA Analysis Engines over streams of unstructured information, and to specify how the matched annotations will be transformed into RDF triples.
PEARL combines the mechanism of UIMA features paths (to extract revelant information from UIMA annotations) with a subset of the SPARQL syntax to describe patterns for generating RDF triples.
We describe here the structure of a typical projection document (a document containing a set of projection rules) and then we give a list of concise examples to show the expressiveness of this language.

Structure of a PEARL document

A projection document (containing PEARL rules) begins with Prefix Declarations followed by one or more Projection Rules.

			
prefix ...

rule ... {
	...
}	
		

Prefix Declaration

At the beginning of the Projection Document each prefix used to shorten a URI in the projection rules is bound to a namespace.

			
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

rule ... {
	...
}
			
		

Projection Rules

The rest of the projection document specifies a set of projection rules. There are various types of rules (see Advanced Concepts later); this section of the manual only deals with standard projection rules.

A Projection Rule specification starts with a rule declaration, followed by its definition, which is composed of the following sections: nodes, graph and where. The graph section is the only mandatory section in a rule definition.

Rule Declaration

Each rule starts with a declaration, introduced by the keyword "rule", and ends before the curly bracket "{", which begins its definition.

			
...

rule it.uniroma2.art.uima.imdb.IMDBFilmCast id:cast dependsOn ... {
	...
}
			
		

The first element in the declaration, following the rule keyword, is a reference to a type (e.g. it.uniroma2.art.uima.imdb.IMDBFilmCast) from the adopted UIMA Type System: any UIMA annotation of that type (or any annotation which is a subtype of the specified type, depending on the CODA configuration) will trigger the use of this rule.

The rule identifier (cast in the above example) follows the type declaration, and is an hook that can be used to reference the rule from other rules, according to different relationships of dependency. These relationships can be declared in an optional list following the rule identifier, and are introduced by the keyword dependsOn (see Advanced Concepts section).

Nodes

The Nodes section is the locus for declaring and creating the nodes which will be used in the generated RDF statements. Though not being mandatory, it provides the actual RDF nodes which will be composed (in the following graph section) into the graph populating the target dataset.

Each node declaration is composed of:

Conversions are applied to the annotation elements identified by the feature path, in order to produce well-formed RDF terms.

A set of conversion functions (shortly: converters) are available for applying different transformations to the input features. Converters are identified by URIs (corresponding to a contract of the conversion function) and can be invoked by specifying their URI between round brackets after the node type in the node declaration. The section on converters provides more details about their usage, while the appendix of this PEARL manual lists available converters in CODA, together with their description; also, the developer manual provides a dedicated section where third party developers may learn how to extend CODA with new converters.

If no converter is specified after the uri or literal reserved words, a default converter is implicitly invoked.

			
prefix 	xsd:	<http://www.w3.org/2001/XMLSchema#>
prefix 	cdbk:	<http://art.uniroma2.it/book/coda#>

rule it.uniroma2.Book id:book1   {
	nodes = {
		book		uri(cdbk:isbn)		isbn
		title		plainLiteral		title
		author		uri			author
		authorName	literal^^xsd:string	author
	}
	...

}
			
		

In the example above, a rule allows to create an RDF description of a book, by converting information extracted by an UIMA Analysis Engine.

There are four node declarations. The placeholder author will host a URI constructed from the feature author of the current annotation with a simple sanitization and by prepending the default namespace. The placeholder book will contain a URI constructed from the value of the feature isbn by invoking a converter implementing the contract cdbk:isbn. This contract declares a function which turns a isbn into a suitable URI. The two other placeholders, title and authorName, will host respectively a plainLiteral and a xsd:string typed literal.

Graph

The graph section contains the true projection over the target dataset graph, by describing a graph pattern which is dynamically populated with unified node names and variables (see next paragraph on the where section). The graph pattern consists of a set of triples, where the first element is the subject, the second is the predicate and the third the object of an RDF statement. Each single element in the graph may be one of the following: a node placeholder, a variable, an RDF node or an abbreviation. Inside a graph pattern, placeholders, defined in the nodes section of the current or of other referenced projection rules (when using the dependsOn construct the placeholder contains a single . and when using the a binding, two .. are placed), are identified by the prefixed symbol "$". RDF nodes can be referenced in graph patterns through the usual notation for URIs (or qnames) and literals.

The abbreviations are represented by a finite list of words that can be used in place of explicit reference to RDF resources. This list includes, for instance, the standard abbreviation from the RDF Turtle format - also adopted in the SPARQL query language - which assumes the character "a" to be interpreted as rdf:type.

			
prefix 	my: <http://art.uniroma2.it/imdb#>
prefix 	xsd: <http://www.w3.org/2001/XMLSchema#>
prefix 	owl: <http://www.w3.org/2002/07/owl#>
			
rule it.uniroma2.art.uima.imdb.IMDBFilm id:film {
	nodes = {
		filmId		uri			title
		filmTitle	literal^^xsd:string	title
		year		literal^^xsd:integer	year
	}
				
	graph = {
		$filmId		a		my:Film	.
		$filmId		my:title	$filmTitle	.
		$filmId		my:releasedIn	$year		.
	}
}

 

Advanced Concepts

Converters

Converters are a very powerful tool of PEARL for generating URIs and literal by following different conventions, adapting annotated content or simply generating random identifiers. Converters represent an extensible part of the language. Each converter is in fact realized by a java class, implementing an interface which represents the contract for the function. Converters may be added to an existing CODA system by deploying a dedicated OSGi bundle inside its installation or by enabling automatic download of converters from the Web. In this latter case, the URI of the converter contract is used to locate the contract on the Web and to access concrete implementations hosted on OBR repositories.

Converter Contracts

Converters are indirectly referred by means of a URI which identifies the desired behavior (a contract) instead of a concrete implementation. In a certain sense a contract identifies a set of functionally equivalent converters, possibly differing for nonfunctional properties, such as resource consumption, performance with respect to the task, or even licensing terms. The exact behavior represented by a contract is expressed in terms of specifications in natural language (as usual in contracts for service or methods), provided through standard metadata properties (e.g. dcterms:description) and it is actually the URI of the contract that provides the sole semantic anchor. For instance, the contract <http://art.uniroma2.it/coda/contracts/default> is described as “the procedure invoked by default for transforming a UIMA value into a valid RDF term”.

Converter Resolution

In fact, the input/output behavior of contracts is difficult to express in a formal language. The PEARL execution logic is kept separate from the contract resolution process as contract references are resolved into suitable converters by the Component Provider. Converters are bundled complying with the OSGi specification and stored in repositories organized according to the OBR (OSGi Bundle Repository) architecture. OBR repositories maintain metadata about the hosted bundles including their name, version, provided capabilities and requirements. A CODA converter is advertised on OBR repositories as a service
capability, which holds the contract URI, and the Java interface for interrogating the converter. OBR requirements are instead populated with the non-functional properties of the converters.
The Component Provider follows a two-step procedure for resolving contracts into suitable converters. At first it uses the OBR Client to access a known set of OBR repositories (starting from the CODA Local Repository) looking for a candidate whose metadata match the contract. If no candidate is found, the Component Provider relies on its Discoverer module to explore the Web looking for additional repositories. The Discoverer exploits the fact that PEARL specifications are self-describing and, moreover, grounded in the Web of Data, since the required contracts are mentioned through dereferenceable URIs. In compliance with the Linked Data principles, the Discoverer obtains through those URIs an RDF description of the contract, including a list of authoritative repositories of known implementations. This architecture enables autonomous configuration of CODA systems, disburdening the user from manual settings prior to the execution of a PEARL projection. This is especially valuable when reusing PEARL documents written by third parties, as in open and distributed scenarios.

Converter Syntax

Some specific converters can be used simply as described in the Nodes section:

book		uri(cdbk:isbn)		isbn

In the example above, the value of the UIMA feature isbn is processed through the odbk:isbn converter and the resulting URI is stored in the book RDF node.

From version 1.2 of CODA, the converter specification has been extended with the capability to accept parameters for customizing the conversion format.

The parameters handed to the converters need to be specified between square brackets. Different type of parameters are accepted, such as String, integers etc.. and also complex constructs such as maps can be passed as a parameter.

In the following example, a new converter contract, called randIdGen, is beind invoked. randIdGen allows for the generation of random URIs (precisely, random localnames for a given baseuri), with customizable patterns which depend on the role of the generated resource (e.g. a skos concept, a skosxl label, an owl class etc...). The following invocation:

xlabelName		uri(coda:randIdGen['xLabel', {lexicalForm = "Rome"@en, lexicalizedResource = $city}]) city/name .

passes by first the value xLabel, which is a known role for indicating resources of type: skosxl:Label, and then, through a map (expressed as a list of attribute/value pairs among braces) it informs the converter that the lexical form for the xLabel is "Rome"@en and the resource to be lexicalized is a node (previously declared in the Nodes section) called city.

The standard pattern of the randIdGen converter for xLabels:

xl_$ {lexicalForm.language}_$ {rand()}

ignores the URI of the lexicalized resource and uses instead the language of the lexicalForm in order to build the random URI for the generated resource. rand() is a random generator which, again by default, produces an 8-digit exadecimal number. In this case, the produced localname would be something of the form:

xl_en_233d4f6a

Where

As for the graph section, the (optional) where section contains a graph pattern: the purpose of this graph pattern is to link newly extracted data with information which is already present in the target dataset (i.e. the dataset which will be updated with the triples generated by CODA).

The specified graph pattern is thus matched over the target dataset to retrieve already existing nodes by means of variable unification (variables are identifiable by a prefixed "?" symbol), so that the variables substitutions can be reused in the already described graph section.

In this sense, it is much close to the purpose of the WHERE statement in a SPARQL CONSTRUCT query. The unification mechanism allows to assign values to variables by constraining them on the basis of information which is thought to be present in the dataset: these substitutions are then applied to the graph pattern of the graph section to project data over the target dataset.

			
prefix my: <http://IMDB#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
			
rule it.uniroma2.art.uima.imdb.IMDBFilm id:film {
	nodes = {
		filmId		uri			title
		filmTitle	literal^^xsd:string	title
	}
				
	graph = {
		$filmId		a			my:Film	.
		?filmId		my:title		$filmTitle	.
	}

	where = {
		?filmId		my:title		$filmTitle .
	}
}

In the WHERE section of the above example we define a variable, filmId, (by means of the ? symbol, not to be confounded with the $ of placeholders for generated nodes). The clause in the WHERE should return the subject of triples having the retrieved $filmTitle as object of the my:title predicate.

Note that, if the value is not retrieved, the WHERE will fail. However, a fallback mechanism in CODA will use the value held by the placeholder with the same name of the unistantiated variable.

Conditions for rule triggering

Normally, when deciding which rule(s) to apply, only the UIMA annotation type is considered. A more advanced mechanism for selecting which rule to apply can be implemented through the use of conditions. A dedicated conditions section allows to specify a list of values which should or should not be hold by a given feature structure.

Thus, when the UIMA type specified in the rule definition matches the current annotation, if the conditions section is present, all the conditions in it are checked first and, only if all of them are satisfied, the rule is applied.

Each condition has three elements:

An example of how to use conditions is:

			
prefix my: <http://IMDB#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
			
rule it.uniroma2.art.coda.test.ae.type.Person id:person {
	conditions = {
		name			IN		["Andrea", "Armando"] .
	}
	nodes = {
		personName		uri			name 
	}
	graph = {
		$personName		a			my:Person .
	}
}

In this case CODA will apply this rule ONLY if the value contained in the feature path name is contained in the list ["Andrea", "Armando"] , so if its value is either Andrea or Armando.

conversely:

			
prefix my: http://IMDB#;
prefix xsd: http://www.w3.org/2001/XMLSchema#;
prefix owl: http://www.w3.org/2002/07/owl#;
			
rule it.uniroma2.art.coda.test.ae.type.Person id:person {
	conditions = {
		name			NOT IN		["Andrea", "Armando"] .
	}
	nodes = {
		personName		uri			name 
	}
	graph = {
		$personName		a			my:Person .
	}
}

here CODA will apply this rule ONLY if the value contained in the feature path name is NOT contained in the list ["Andrea", "Armando"] , so if its value is neither Andrea nor Armando .

 

DependsOn

It is possible to state a dependency between two or more rules (and the annotions which trigger the use of these rules).

The rule referenced for the dependency is identified using its id. The rule stating the dependency on the first one declares it by means of the keyword dependsOn in its declaration, followed by the type of dependency. In the current implementation the following types of dependency are provided:

Some of these dependencies, have optional parameters. Here are the depencendy with the optional paramters:

In the example below we use last as the dependency type. This means that when CODA will use the second rule it will look back to the other annotation until it finds on in which the first rule was used. At this point CODA will consider this other annotation as the target of this particular instance of dependency, so the application of the second rule for the given annotation depends on the other annotation just found. Once the "link" between these two rules has been establish the rules that stated the dependency is now able to use the placeholder defined and initialized in the other rules. The syntax to use the other placeholder is quite similar to using a local placeholder, the only different is that before the placeholder name is form using the other rule's id followed by . and followd by the placeholder defined in the other rule. The second rule use the placeholder $film.filmId from the first rule in its second suggested triple.

			
prefix 	my: http://IMDB#;
prefix 	xsd: http://www.w3.org/2001/XMLSchema#;
prefix 	owl: http://www.w3.org/2002/07/owl#;
			
rule it.uniroma2.art.uima.imdb.IMDBFilm id:film {
	nodes = {
		filmId		uri		movieId					
	}
	graph= {
		$filmId		a		my:Film	.
	}
};
			
rule it.uniroma2.art.uima.imdb.IMDBFilmCast id:cast dependsOn last(film) {
	nodes = {
		actorId		uri		actorsList/personId
	}
	graph= {
		$actorId	a		my:Actor.
		$actorId	my:actedId	$film.filmId .	
	}
};
			
		

An example on how to state and use the dependency mechanism can be seen in this example or in the demo

 

Bindings

This optional section is used to define bingings with other UIMA annotation. The bindings are a particular type of dependency that are used to establish a connection with an inner annotation (an annotation that can be reach using a specific feature path) by refering to a lazy rule.
They are used when we don't want to mix different values contained in several placeholder. An example could be a list of Annotations regarding several person. In this case it is important not to mix the first name of a person with the last name of another person, but these information should always remain linked together when CODA suggest RDF triples.

			
prefix 	my:	<http://art.uniroma2.it/ontology#>

lazy rule it.uniroma2.Person id:person   {
	nodes = {
		personId		uri			id
		firstName		plainLiteral		firstName
		secondName		plainLiteral		secondName
	}
}

rule it.uniroma2.People id:people   {
	bindings = {
		singlePerson	personList	person
	}
	nodes = {
		city		uri		mainCity
	}
	graph = {
		$singlePerson..personId		my:livesIn	$city .
		$singlePerson..personId		a		my:Person .
		$singlePerson..personId		my:name		$singlePerson..firstName .
		$singlePerson..personId		my:lastName	$singlePerson..secondName .
		
	}
}
			
		

In this example let's assume that we have an annotation of type rule it.uniroma2.People which has two features: mainCity (with a single value) and personList (which is a list of annotation of type rule it.uniroma2.People ). We want to associate (in RDF) to each person his/her own name and last name. This can be accomplish using the bingding construct. Each $singlePerson (defined in the bindings section) refer to a single annotation and in the graph section we are able to access its inner values using the .. , so we can link with the desired property ( my:name or my:lastName) each personId with his/her own name.

 

Use of the OPTIONAL clause in the graph section

A write operation of a graph pattern GP into a graph G succeeds if all the three elements (subject, predicate, object) of the triples in GP are bound (instantiated). A triple may not be fully instantiated for various reasons: for instance, a failed match on the WHERE section might leave a variable uninstantiated, or a missing value for a UIMA feature referenced in a node declaration may leave the placeholder for the generated RDF node empty.

A whole projection rule succeeds if all the write operations in the GRAPH section succeed (i.e the whole graph is fully instantiated).

The OPTIONAL clause may be used to wrap a given subgraph of the graph specified in the GRAPH section, in order to make it non mandatory for the succesfull production of the triples to be generated.

			
prefix 	my: http://art.uniroma2.it/imdb#;
prefix 	xsd: http://www.w3.org/2001/XMLSchema#;
prefix 	owl: http://www.w3.org/2002/07/owl#;
			
rule it.uniroma2.art.uima.imdb.IMDBFilm id:film {
	nodes = {
		filmId		uri			title
		filmTitle	literal^^xsd:string	title
		year		literal^^xsd:integer	year
		description	literal^^xsd:string	description
	}
				
	graph = {
		$filmId		a			my:Film	.
		$filmId		my:title		$filmTitle	.
		$filmId		my:releasedIn		$year		.
		OPTIONAL { 
			$filmId		my:description	$description	.
		}
}

In the above case, if the movie description is not available in the UIMA feature structure, then the whole application of the rule is not compromised, and the sole triples out of the OPTIONAL are still written.

 

Lists and FeaturePaths

PEARL allows to use all the values of the features which satisfy a particular FeaturePath. In the example below:

			
prefix 	my: http://IMDB#;
prefix 	xsd: http://www.w3.org/2001/XMLSchema#;
prefix 	owl: http://www.w3.org/2002/07/owl#;
			
rule it.uniroma2.art.uima.imdb.IMDBFilm id:film {
	nodes = {
		filmId		uri		movieId					
		actorId		uri		actorsList/personId
	}
	graph= {
		$filmId		a		my:Film	.
		$actorId	a		my:Actor.
		$actorId	my:actedId	$filmId .	
	}
};

The second placeholder, actorId, does not contain just a single value, but a list of values. As the name of the feature may suggests, actorList contains a list of value (and these values are not primitive values, such as string or integer). The syntax to put inside a placeholder a list of value is the same one as to consider just a single one for features which has just one value. It is also possible to use a specific position inside the List/Array using the syntax actorList[i], where i stands for the position we wish to use (starting from 0 and not from 1). This particular notation (not using a specific position) is extremely useful in the cases:

 

Regexes

It is possibile to express simple or complex regexes of UIMA annotation in PEARL.

Each Regex is composed of two parts:

Let's first see how the forRegex rules are defined. Each forRegex rule has only the nodes part and no graph section. An example is:

			
forRegex rule it.uniroma2.art.coda.test.ae.type.City id:city {
		
	nodes = {
		cityName		uri 		name
	}
} ;

This forRegex is used by a Regex rule, when its id, city, is refered to. Thanks to this rule, the value in the featture path name is placed, coverted into a URI, in the placeholder cityName. Then the placeholder will be used in the regex itself.

The Regex rule has a different syntax than any other rules sees up to this point. An example of such rule is:

			
regex id:firstRegex [person as firstPerson] [5 city as firstCity]->
	graph = {
		$firstPerson..personName		a				my:Person .
		$firstCity..cityName			a				my:City .
		$firstCity..cityName			my:linkedTo			$firstCity..cityName .
	} ;

A Regex rule is introduced by the word regex followed by its id. Then, there is the regex itself. Each element of the regex in placed int a couple of [ ] . An element is composed of 2 or 3 part (3 or 4 if we count che mandatory word as):

After the regex part, there is a -> followed by the graph section. This section is similar to the graph section of the other rules, the only difference is that there are no direct placeholder (since there is no nodes section), and all the used placeholder are in the for $LOCAL_RULE_ID_NAME..PLACEHOLDER

The regex support the typical regex operators (*, +, ? and |), which should be placed outside each element

It is even possible to use regexes with conditions (in the forRegex rule, see the conditions section)

 

Appendix

Available converters

CODA provides a set of converters to generate URI or Literal resources.

In addition to the default converters, described in the sammary table below, there are mainly two kinds of converters, only available for the URI:

Here it is a table that shows an overview of the available CODA converters

(default activated converter) uri Default URI converter. Generates a URI concatenating the baseUri to the given input. If the input string is already a URI, it returns the same.
DefaultContract DefaultConverter
(default activated converter) literal Default Literal converter. Simply returns the given insput as a Literal.
DefaultContract DefaultConverter
coda:detGen-ConceptId uri Deterministic converter. Generates a URI concatenating a c_ prefix with a 16-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSConceptContract DeterministicIdGenForSKOSConceptConverter
coda:detGen-ConceptId-trunc4 uri Deterministic converter. Generates a URI concatenating a c_ prefix with a 4-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSConceptContract DeterministicIdGenForSKOSConceptConverterTrunc4
coda:detGen-ConceptId-trunc8 uri Deterministic converter. Generates a URI concatenating a c_ prefix with a 8-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSConceptContract DeterministicIdGenForSKOSConceptConverterTrunc8
coda:detGen-ConceptId-trunc12 uri Deterministic converter. Generates a URI concatenating a c_ prefix with a 12-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSConceptContract DeterministicIdGenForSKOSConceptConverterTrunc12
coda:randGen-ConceptId uri Randomic converter. Generates a URI concatenating a c_ prefix with a 16-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSConceptContract RandomIdGenForSKOSConceptConverter
coda:randGen-ConceptId-trunc4 uri Randomic converter. Generates a URI concatenating a c_ prefix with a 4-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSConceptContract RandomIdGenForSKOSConceptConverterTrunc4
coda:randGen-ConceptId-trunc8 uri Randomic converter. Generates a URI concatenating a c_ prefix with a 8-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSConceptContract RandomIdGenForSKOSConceptConverterTrunc8
coda:randGen-ConceptId-trunc12 uri Randomic converter. Generates a URI concatenating a c_ prefix with a 12-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSConceptContract RandomIdGenForSKOSConceptConverterTrunc12
coda:detGen-XLabelId uri Deterministic converter. Generates a URI concatenating a xl_ prefix with a 16-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSXLLabelContract DeterministicIdGenForSKOSXLLabelConverter
coda:detGen-XLabelId-trunc4 uri Deterministic converter. Generates a URI concatenating a xl_ prefix with a 4-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSXLLabelContract DeterministicIdGenForSKOSXLLabelConverterTrunc4
coda:detGen-XLabelId-trunc8 uri Deterministic converter. Generates a URI concatenating a xl_ prefix with a 8-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSXLLabelContract DeterministicIdGenForSKOSXLLabelConverterTrunc8
coda:detGen-XLabelId-trunc12 uri Deterministic converter. Generates a URI concatenating a xl_ prefix with a 12-digits hexadecimal deterministic char sequence.
DeterministicIdGenForSKOSXLLabelContract DeterministicIdGenForSKOSXLLabelConverterTrunc12
coda:randGen-XLabelId uri Randomic converter. Generates a URI concatenating a xl_ prefix with a 16-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSXLLabelContract RandomIdGenForSKOSXLLabelConverter
coda:randGen-XLabelId-trunc4 uri Randomic converter. Generates a URI concatenating a xl_ prefix with a 4-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSXLLabelContract RandomIdGenForSKOSXLLabelConverterTrunc4
coda:randGen-XLabelId-trunc8 uri Randomic converter. Generates a URI concatenating a xl_ prefix with a 8-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSXLLabelContract RandomIdGenForSKOSXLLabelConverterTrunc8
coda:randGen-XLabelId-trunc12 uri Randomic converter. Generates a URI concatenating a xl_ prefix with a 12-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSXLLabelContract RandomIdGenForSKOSXLLabelConverterTrunc12
coda:randGen-DefinitionId uri Randomic converter. Generates a URI concatenating a def_ prefix with a 16-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSDefinitionContract RandomIdGenForSKOSDefinitionConverter
coda:randGen-DefinitionId-trunc4 uri Randomic converter. Generates a URI concatenating a def_ prefix with a 4-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSDefinitionContract RandomIdGenForSKOSDefinitionConverterTrunc4
coda:randGen-DefinitionId-trunc8 uri Randomic converter. Generates a URI concatenating a def_ prefix with a 8-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSDefinitionContract RandomIdGenForSKOSDefinitionConverterTrunc8
coda:randGen-DefinitionId-trunc12 uri Randomic converter. Generates a URI concatenating a def_ prefix with a 12-digits hexadecimal randomic char sequence.
RandomIdGenForSKOSDefinitionContract RandomIdGenForSKOSDefinitionConverterTrunc12

Grammar of the PEARL language

The antlr file containing the grammar used by CODA can be downloaded here

A simplified version of the language grammar, expressed in Backus-Naur form is shown here below:

			
prRules := prefixDeclaration* annotations? rules+ ;
prefixDeclaration := 'prefix' prefix_name ':' namespace ';';
annotations :=	'annotations' '=' '{' (annotationDefinition)+ '}';
annotationDefinition := 'Annotation' annotationName ;
metaAnnotation* := '@' metaAnnotationName ('(' parameter (',' otherParameter)* ')')?
rules := (rule|lazyRule)+ ;
rule := 'rule' uimaTypeName 'id:' idVal ('dependsOn' depend (',' depend)*)? '{' 
	bindingsClause? nodesClause? graphClause? whereClause?'}' ;
lazyRule := 'lazy' 'rule' uimaTypeName 'id:' idVal '{' nodesClause? '}' ;
depend := dependType '(' (depRuleIds | params) (',' (depRuleIds | params ) )* ')' 
	'as' depRuleIdAs ;
bindingsClause := 'bindings' '=' '{' bindingDef+ '}' ;
bindingDef :=  bindingId featurePath bindingRuleId ;
featurePath := featurePathElement ('/' featurePathElement)* ;
nodesClause := 'nodes' '=' '{' nodeDef+ '}' ;
nodeDef := nodeId projectionOperator featurePath ;
projectionOperator :=  ('uri' converters?) |  ('literal' '^^' iri converters?) | 
	('literal' langtag  converters?) | ('literal' converters?) ;
converters := '(' iri (',' iri)* ')' ;
graphClause := 'graph' '=' '{' graphElement+ '}' ;
graphElement :=  annotation* (graphTriple | optionalGraphElement) ;
annotation := '@' target ( '(' annotationName ')' ) '.' ;
graphTriple := graphSubject graphPredicate graphObject '.' ;
optionalGraphElement := 'OPTIONAL' '{' graphElement+ '}' ;
graphSubject := var |  iri | blankNode | placeholder ;
graphPredicate := var | iri | abbr | placeholder ;
graphObject := var | iri | literal | blankNode | placeholder ;
whereClause := 'where' '='  '{' graphElement+ '}' ;