Velocity Writer
- Last Updated: May 29, 2026
- 6 minute read
- Semaphore
- Documentation
The velocity writer uses the Apache Velocity template engine to render the rulebases.
The following properties are configurable on the velocity writer
<bean id="AstronautRules" class="com.smartlogic.publisher.velocity.VelocityWriter" >
<property name="rulebaseOutputDirectory" value="${results.directory}/${model.name}/velocity"/>
<property name="useRulebaseClassDirectories" value="true"/>
<property name="fileNameTemplate" value="FileNameTemplate.vm" />
<property name="rulebaseTemplate" value="Astronaut.vm" />
<property name="templateDirectory" value="${config.directory}/${model.name}/templates" />
<property name="rulebaseClassName" value="Astronaut" />
<property name="rulebaseClassNameSource" value="fixed" />
<property name="pakFilePath" value="${results.directory}/${model.name}/pakstore/Astronaut.tar.gz" />
</bean>
Most of these properties the same as for the kid writer (rulebaseOutputDirectory, rulebaseClassSourceName, rulebaseClassName, templateDirectory, rulebaseOutputDirectory, useRulebaseClassDirectories are the same as for the Kid Writer.
The rulebaseTemplate property is the name of the file in the template directory that will be used to render the concept or concept scheme. The fileNameTemplate is the name of the file in the template directory that will be used to define the name of the generated rulebase files.
When rendering the file name using the filename template, the following objects are passed to the velocity context.
- Concept or Concept Scheme - this can be accessed as using the $concept variable within the context
- Language - this can be accessed using the $language variable within the context. The language has a “code” field that contains the two letter ISO code for the language for which rulebases are currently being output.
- Semaphore Model - this is the complete model (all concepts and concept schemes regardless of whether they are part of the current collection filter). It can be accessed via the variable $model. It can be used to look up structural aspects of the model.
- Rulebase Class Name - a string containing the name of the rulebase class currently being generated. This can be accessed using the variable $rulebaseClass
- Logger - this contains no information. However, you can use this for debugging your output or checking model structure whilst outputting rules.
The logger has five methods available, “trace”, “debug”, “info”, “warn” and “error” each of which takes a single string as it’s argument. Each of these will generate a log message at the corresponding level. By default, any message at info and above will be sent to the screen and any message at debug and above will be sent to the publisher log file. Note, if the “error” method is called whilst rendering any concept, then once all the rulebases have been generated, the publisher will stop in a failed state, rulebases will not be pushed to the classification server instances and any SES indexes will not be made live.
Note, from version 5.6 onwards, the default pak file format is tar.gz so the file suffix should reflect this.
Concept Methods
The concept object has a number of methods available which are also available on a set of concepts
1) getRelatedConcepts(<list of relationship references>) - generates a set of concepts related by any of the listed relationships. If no list of relationship references is supplied then all related terms are returned.
2) getParentConcepts(<list of relationship references>) - a specialization of getRelatedConcepts - only return parent concepts
3) getChildConcepts(<list of relationship references>) - a specialization of getRelatedConcepts - only return child concepts
4) getDescendantConcepts(<list of relationship references>) - a return all children, grandchildren etc via the optionally specified relationship
5) getAssociatedConcepts(<list of relationship references>) - a specialization of getRelatedConcepts - only return associated concepts
6) getLabels($language, <list of relationship references> - generates a set of labels related by any of the listed relationships. If no list of relationship references is supplied then all labels are returned. Note, if prefLabel is requested, then only the prefLabel in the provided language will be returned. If there is no prefLabel in the supplied language then the language neutral prefLabel will be returned. If there is no prefLabel in the supplied language or language neutral then no prefLabel will be returned. For all other labels, the labels in the supplied language and language neutral will be returned.
7) getMetadata(<list of metadata type references>) - generates a set of metadata value objects.
Each of the set returning methods will return an empty set if there are no objects matching the filter. None of these methods will return a null object.
Note, all the sets returned by these methods have an additional method first() - this returns the first element of the set. As the ordering within the model is arbitrary, the identity of the first element of the set is also arbitrary. (It is deterministic though, for the same model, the “first” element of each set will be the same). Note, if the set returned is empty then first() will return a null object. You need to check that the data returned is not null before referencing any of its methods.
The <list of relationship references> should be presented as a space separated list of either relationship type URIs or local names (typically the part of the URI after the #). Appending * to the relationship type URI or local name will include relationship types that are sub properties of the indicated relationship type as well as that relationship type. Appending + to the relationship type URI or local name will include relationship types that a sub-properties of the indicated relationship type but not that relationship type.
The sets returned by any of the concept returning methods will also have any of these methods available. Therefore,
$concept.getRelatedConcepts(“crewed”).getRelatedConcepts(“launched-from”)
will return all the concepts that are related via the “launched-from” relationship to concepts that are related to the root concept by the “crewed” relationship. If at any stage there are no such concepts, then an empty set will be returned.
Other methods available on a concept but not a set of concepts
- “$concept.defaultLabel” will return the default label of the concept, this is the concept’s label in English if available, language neutral if available (and language English not available) or it’s value in any language (if English and language neutral are not available). This can be used to generate labels specific to that concept (though the concept identifier should be used to ensure uniqueness)
- $concept.uri - the URI of the concept
- $concept.identifier - normally the GUID of the Concept but if a different identifier has been specified in Knowledge Model Management then this will be used here instead.
Label Methods
The label and set of labels objects have a method “getVariants” that takes one optional argument - the word types being requested. The Word Types is identical to that for the kid writer. If no filter is specified then all variants will be returned.
Another method available on the set of labels object is “filterByBehaviour”. This will return the labels that have the rulebase behaviour attribute in the editor interface matching the one string argument for the method. For example
- .filterByBehaviour(“Treat as exact phrase only”) will return all the labels in the set that have been marked as “Treat as exact phrase only”.
- .filterByBehaviour(“^Treat as exact phrase only”) will return all the labels in the set that have not been marked as “Treat as exact phrase only”.
- .filterByBehaviour(“Treat as exact phrase only|Treat as sentence”) will return all the labels in the set that have been marked as “Treat as exact phrase only” or “Treat as sentence”.
Note, out of the box, the only rulebase behaviours available are “Treat as exact phrase only” and “Allow phrase variants (default)”. Other values may be added by importing to the model’s triple sets as follows:
<http://www.smartlogic.com/2014/08/semaphore-core#RulebaseBehaviourIgnore>
rdf:type <http://www.smartlogic.com/2014/08/semaphore-core#RulebaseBehaviour> ;
<http://www.smartlogic.com/2014/08/semaphore-core#rank> 0 ;
rdfs:label "Ignore"@en ;
.
Where <http://www.smartlogic.com/2014/08/semaphore-core#rulebasebehaviourignore> is the URI of the setting value and “Ignore” is the label to be shown in the Knowledge Model Management, and in the filtering operations.
Variant Methods
The variant and set of variants objects have one method “getPreclusions”. This returns the set of preclusions that preclude any of the variants in the variant set. Note, however, that if a term appears as a variant, then it will not appear as a preclusion (so if the set of variants is “vice president” and “president”, then “vice president” will not appear in the set of preclusions even though it does preclude the term “vice president”).
Two methods are supplied on the variant “getStemming(<integer>)” takes a single integer argument. If the label from which the variant has been derived has been marked as “stem” then 1 will be returned, if it has been marked as “do not stem” then 0 will be returned. If the label has not been marked as either, then the supplied value will be returned. Its use would generally be in a text not stem=“${variant.getStemming(1)” would output the stemming for this variant, with stemming on as default.
getCaseSensitivity(<integer>) works the same way as getStemming, except that it represented the case sensitivity of the associated label.
$variant.value returns the text contents of the variant.
A typical output format would therefore be:
<phrase data="${variant.value}" stem="${variant.getStemming(0)}" case="${variant.getCaseSensitivity(0)}" />
Preclusion Methods
A preclusion object has the same methods available as the variant object, so a preclusion item would be output as:
<phrase data="${preclusion.value}" stem="${preclusion.getStemming(0)}" case="${preclusion.getCaseSensitivity(0)}"/>