Velocity Tools

Velocity Tools are a collection of common functions that simplify the content manipulation process when using Velocity.  Below are explanations of each tool and code samples.

Date Tool

The Comparison Date Tool allows users to format numeric date values and compare them with other date values in a Velocity template. For example, let's say you have an Index Block that indexes a Folder and includes system metadata. Dates in Index Blocks are output in the Java timestamp format, which is Unix time format with 3 additional digits for milliseconds. With this tool, users can easily convert these Unix times to virtually any format they like with a very small amount of Velocity code.

The following example demonstrates how to perform a number of different operations using the Comparison Date Tool. Below the example are explanations for each line.  Note that a Date is actually a Java Date. See information regarding Java Dates for more details.


            #set ($originalDate = $_DateTool.getDate())  
    #foreach($item in $contentRoot.getChildren('system-page'))  
         #set ($pubDate = $_DateTool.getDate($item.getChild('last-published-on').value))  
         <p>Published Date: $_DateTool.format('medium', $pubDate)</p>  
         <p>Specially formatted date: $_DateTool.format('EEEEE MM/dd/yy', $pubDate)</p>  
         <p>Date comparison: $_DateTool.difference($pubDate, $originalDate)</p>  
    #end  
            

Note: The block used with this example must contain at least one 'system-page' element and must include system metadata.

Line-by-line explanation:

  1. Creates a new variable, $originalDate, which is a Date representing today's date.
  2. Begins iterating over the system-page children of the contentRoot.
  3. Creates a new variable, $pubDate, which is the Date representation of the current system-page's last published date.
  4. Outputs the current system-page's last published Date in a "medium" format. See definitions for friendly date formats like "medium".
  5. Outputs the current system-page's last published Date in a custom format specified using pre-defined formatting characters.  For specifics regarding these formatting characters, see date and time patterns.
  6. Computes the time difference between two Dates.  This example uses today's Date and the current system-page's last published Date.  By default, the difference() method will return a value that is the largest unit difference between the two Dates.  For example, if today's date were May 25, 2009 and the system-page's last published date were May 18, 2007; then the value returned from the difference() method would be 2 for 2 years difference.  For more information regarding the difference() method and all other available date comparison methods see ComparisonDateTool.

The Date Tool's getDate(String) method is not actually a part of the standard Date Tool supplied by Velocity.  It's purpose is very simple though.  It takes a string and converts it into a Java Date which makes it very easy to manipulate using other methods contained in the Date Tool.  Check out information regarding the Date Tool.

Display Tool

The Display Tool contains numerous convenience methods for formatting various types of data for display.  A few examples are provided below, and the full API documentation may be found here.

Displaying Lists:  The Display Tool list() method displays each item in the specified list of items, separated by the specified delimiter.


                #set ( $list = [1..5] )  
    <h2>Outputs all each list item, separated by the provided delimiter.</h2>  
    <p>Comma separated: ${_DisplayTool.list($list,",")}</p>  
            

Line-by-line explanation:

1.  Creates an array of numbers 1 through 5.
2.  Outputs a heading for our displayed list of numbers
3.  Outputs each number in the array, separated by a comma -- i.e. "1,2,3,4,5" 

Displaying text which may be singular or plural at run-time:  The Display Tool plural() method will automatically return the plural form of the specified singular word, if necessary, based on the specified integer value.  You may also explicitly specify the plural form of the word for words which do not follow standard pluralization rules.


                #set ( $list1 = ["apple","apple","apple","apple"] )  
    #set ( $list2 = ["apple"] )  
      
    <p>There ${_DisplayTool.plural($list1.size(),"is","are")}   
    ${list1.size()} ${_DisplayTool.plural($list1.size(),"apple")} in List 1</p>  
    <p>There ${_DisplayTool.plural($list2.size(),"is","are")}   
    ${list2.size()} ${_DisplayTool.plural($list2.size(),"apple")} in List 2</p> 
            

Line-by-line explanation:

1.  Creates an array containing 4 "apples"
2.  Creates an array containing 1 "apple"
3.  (blank)
4-5.  Outputs: "There are 4 apples in List 1"
6-7.  Outputs: "There is 1 apple in List 2" 

Stripping HTML tags:  The Display Tool stripTags() method allows you to strip HTML tags from text.


            #set ( $textWithHtml = "This is some text <strong>with HTML tags.</strong>" )  
<p>Text output directly: ${textWithHtml}</p>  
<p>Text with HTML tags stripped: ${_DisplayTool.stripTags($textWithHtml)}</p> 
            

Line-by-line explanation:

1.  Creates text variable containing HTML tags
2.  Outputs "Text output directly:  This is some text with HTML tags.
3.  Outputs "Text with HTML tags stripped:  This is some text with HTML tags." 

Truncating long text:  The Display Tool truncate() method allows you to truncate long text after a specified number of characters.  You may also specify that the truncation occur only after a complete word -- i.e. not in the middle of a word.


            #set ( $longText = "That is some really, really, really, long text you've got there." )  
<p>Full text: ${longText}</p>  
<p>Truncated text: ${_DisplayTool.truncate($longText,33,"...")}</p>  
<p>Truncated at word: ${_DisplayTool.truncate($longText,33,"...",true)}</p> 
            

Line-by-line explanation:

1.  Creates a variable, $longText, containing: "That is some really, really, really, long text you've got there."
2.  Outputs the full text of $longText
3.  Outputs:  "Truncated text: That is some really, really, r..."
4.  Outputs:  "Truncated at word:  That is some really, really,..."

Graceful display of null values:  The Display Tool alt() method checks the value of the given object and returns the specified alt text if the object is null, otherwise the original value is returned.


                #set ( $title = $_XPathTool.selectSingleNode($contentRoot,"//calling-page/system-page/title").value )  
    <p>${_DisplayTool.alt($title,"No Title Provided.")}</p>  
            

Note:  The index block used for the above example must have the "Append Calling Page Data" option selected, otherwise $title will always be null.

Line-by-line explanation:

1.  Sets a variable, $title, containing the contents of the current page's Title metadata field (if provided).
2.  Outputs the title of the current page, if one was provided, otherwise outputs "No Title Provided." 

Escape Tool

The Escape Tool contains programming language-specific escape functionality, as well as methods and properties for outputting safely escaped special characters within your Velocity scripts.  Some examples are shown below and the full API documentation may be found here

Escaping for XML:  The Escape Tool xml() method safely escapes any special characters specifically for XML output.  It is important to note than in almost all cases, the xml() method will be preferable to the html() method when escaping content within Cascade, due to Cascade's more strict XHTML validation of content.  This is true even when escaping content for HTML output within Cascade.


                #set ( $xml = $_XPathTool.selectSingleNode($contentRoot,"//calling-page/system-page/summary").value )  
    ##<p>${xml}</p>  
    <p>${_EscapeTool.xml($xml)}</p>  
            

Note:  The index block used for this example must have the "Append Calling Page Data" option selected, and the page on which this format executes should have data set for the "Summary" metadata field as described below.

Line-by-line explanation:

1.  Sets a text variable, $xml, containing the value of the current page's "Summary" metadata field.  For this example, edit the page to set the value of the Summary field to: "bread" & "butter" (with quotation marks included).
2.  (Commented out)  If un-commented, this line would attempt to output the contents of $xml un-escaped and would result in a run-time error because the un-escaped special characters are not valid XML.
3.  Outputs:  "bread" & "butter" with the quotation marks and ampersand characters safely escaped for XML output. 

Escaping for JavaScript:  The Escape Tool javascript() method safely escapes any special characters specifically for output within JavaScript code.


                #set ( $javascript = $_XPathTool.selectSingleNode($contentRoot,"//calling-page/system-page/teaser").value )  
    <script type="text/javascript">  
            // alert("${javascript}");  
        alert("${_EscapeTool.javascript($javascript)}");  
    </script>  
            

Note:  The index block used for this example must have the "Append Calling Page Data" option selected, and the page on which this format executes should have data set for the "Teaser" metadata field as described below.

Line-by-line explanation:

1.  Sets a variable, $javascript, containing the value of the current page's "Teaser" metadata field.  For this example, edit the page to set the value of the Teaser field to: I didn't say "Stop!" 
2.  Opening script tag.
3.  (Commented out)  If un-commented, this line will attempt to display the un-escaped value of $javascript in a pop-up alert, but will instead generate a JavaScript error and fail due to the un-escaped special characters.
4.  Outputs a JavaScript pop-up alert containing the text: I didn't say "Stop!" with all special characters safely escaped for JavaScript. 
5.  Closing script tag 

Pre-defined special characters:  The Escape Tool also provides several pre-defined, safely-escaped (for Velocity) special characters.


                <p>Dollar sign: ${_EscapeTool.dollar} OR ${_EscapeTool.d}</p>  
    <p>Hash (pound key): ${_EscapeTool.hash} OR ${_EscapeTool.h}</p>  
    <p>Single Quote: ${_EscapeTool.singleQuote} OR ${_EscapeTool.s}</p>  
    <p>Double Quote: ${_EscapeTool.quote} OR ${_EscapeTool.q}</p>  
    <p>Backslash: ${_EscapeTool.backslash} OR ${_EscapeTool.b}</p>  
    <p>Exclamation: ${_EscapeTool.exclamation} OR ${_EscapeTool.e}</p>  
            

Line-by-line explanation:

1.  Outputs a safely-escaped dollar sign ($).
2.  Outputs a safely-escaped hash (pound key) (#).
3.  Outputs a safely-escaped single-quote (').
4.  Outputs a safely-escaped double-quote (").
5.  Outputs a safely-escaped backslash (\).
6.  Outputs a safely-escaped exclamation mark (!). 

Field Tool

The Field Tool provides access to Java public constant values, which are otherwise inaccessible in Velocity scripts.  Some examples are shown below and the full API documentation for the tool may be found here.

Static variables are not natively accessible in Velocity – nor are there any plans to make them accessible natively in the future. As a result, constants such as Calendar.DAY_OF_WEEK, Calendar.MONTH, Calendar.YEAR, etc., are inaccessible in Velocity scripts. Among other things, this makes certain date manipulation functions in Velocity quite unintuitive. For example, adding/subtracting time:


                #set ( $calendar = $_DateTool.getCalendar() )  
    #set ( $today = $_DateTool.getDate() )  
    <p>Today = ${today}</p>  
    $calendar.setTime($today)  
    $calendar.add(6, 1)  
    <p>Tomorrow = ${calendar.getTime()}</p>  
            

Line-by-line explanation:

1.  Get a java.util.Calendar object using $_DateTool.
2.  Get a java.util.Date object representing the current system date/time. 
3.  Output the value of the current system date/time.
4.  Set the calendar's date/time to the current system date/time.
5.  Add 1 day to the calendar's date/time (6 is the value of the constant field Calendar.DAY_OF_YEAR, while 1 is the number of days we are incrementing the calendar's date/time value).
6.  Output the current system date/time, plus 1 day (i.e. tomorrow). 

Note that without Field Tool, one must simply know that the literal value of Calendar.DAY_OF_YEAR is 6.  Likewise, for any other portion of the date to be manipulated, the literal value of the appropriate constant must be known.  However, with Field Tool, the above could be accomplished without hard-coding the field value for Calendar.DAY_OF_YEAR like so:


                #set ( $calendar = $_DateTool.getCalendar() )  
    #set ( $today = $_DateTool.getDate() )  
    <p>Today = ${today}</p>  
    $calendar.setTime($today)  
    $calendar.add($_FieldTool.in($calendar).DAY_OF_YEAR, 1)  
    <p>Tomorrow = ${calendar.getTime()}</p>  
            

Line-by-line explanation:

1.  Get a java.util.Calendar object using $_DateTool.
2.  Get a java.util.Date object representing the current system date/time. 
3.  Output the value of the current system date/time.
4.  Set the calendar's date/time to the current system date/time.
5.  Add 1 day to the calendar's date/time, using $_FieldTool to access the value of the constant field Calendar.DAY_OF_YEAR.
6.  Output the current system date/time, plus 1 day (i.e. tomorrow).

Constant values may be accessed by passing in one of three values to the $_FieldTool.in() method: 

1.  An object reference to an instance of the class containing the desired constant value:


                ## set an object reference to a java.util.Calendar object  
    #set ( $calendar = $_DateTool.getCalendar() )  
    ## use that Calendar object reference to access the constant DAY_OF_YEAR  
    $_FieldTool.in($calendar).DAY_OF_YEAR 
            

2.  The fully-qualified Java class name (including package) of the class containing the desired constant value:


                ## directly access Calendar constants by specifying the   
    ## fully-qualified class name  
    $_FieldTool.in("java.util.Calendar").DAY_OF_YEAR  
            

3.  A literal value of the class type containing the desired constant value:


                ## because the literal 0 is of type Integer, it can be used to access   
    ## constants in the Integer class  
    $_FieldTool.in(0).MIN_VALUE  
            

Finally, in addition to core Java constants, the following Cascade-specific constant values have been made accessible via $_FieldTool, like so:


                #set ( $cascadeVersion = $_FieldTool.in("com.hannonhill.cascade.model.constants.SystemVersions").APP_VERSION )  
    #set ( $tinyMceVersion = $_FieldTool.in("com.hannonhill.cascade.model.constants.SystemVersions").TINYMCE_VERSION )  
    #set ( $dbUpdateVersion = $_FieldTool.in("com.hannonhill.cascade.model.constants.SystemVersions").DB_UPDATE_VERSION )  
    #set ( $copyrightYear = $_FieldTool.in("com.hannonhill.cascade.model.constants.SystemVersions").COPYRIGHT_YEAR ) 
            

1.  The Cascade application version
2.  The TinyMCE version
3.  The Cascade DB update version
4.  The Cascade copyright year

List Tool

The $_ListTool provides operations that can be performed on lists.


            ## Reverse a list
#set($reversedList = $_ListTool.reverse($list))

## remove all elements that don't have given property in given list (or property is empty) and returns them as a new list
#set($removedElements = $_ListTool.removeNull($list, "metadata.title"))

## To convert an array to a list to be able to use any of the above
#set($list = $_ListTool.toList($array))
            

Locator Tool and Query API

This tool is used to locate assets in Cascade Server dynamically. The returned assets are the Cascade Server API objects. To be able to determine what properties the returned objects have, developers can use the PropertyTool. For ease of use, the Locator Tool can be accessed just by the “_” character. The following methods are available:

  • locatePage(path)
  • locatePage(path, siteName)
  • locateFile(path)
  • locateFile(path, siteName)
  • locateFolder(path)
  • locateFolder(path, siteName)
  • locateBlock(path)
  • locateBlock(path, siteName)
  • locateSymlink(path)
  • locateSymlink(path, siteName)
  • locateReference(path)
  • locateReference(path, siteName)
  • locate(path, type)
  • locate(path, type, siteName)

Parameter “path” should be the full path to asset being located, excluding site name. It can but does not have to contain a leading forward slash. Functions without “siteName” parameter will locate assets in the site where the Format is located. To locate assets in the site where the currently rendered Page is located, use $currentPageSiteName pre-populated variable. Functions with “type” parameter accept an EntityType object, which can be one of the following:

  • TYPE_LINKABLE (includes pages, files and symlinks)
  • TYPE_PAGE
  • TYPE_FILE
  • TYPE_FOLDER
  • TYPE_BLOCK
  • TYPE_TEMPLATE
  • TYPE_REFERENCE
  • TYPE_SYMLINK
  • TYPE_FORMAT

Using any other type to locate an asset will result in an error.

One way of accessing the EntityType object is through the EntityIdentifier object, for example the following code will return Folder type:


            $currentPage.parentFolderIdentifier.type 
            
Another way to access the EntityType object is by directly accessing the constant from EntityTypes class using the FieldTool, for example the following code will return Folder type:

            $_FieldTool.in(“com.hannonhill.cascade.model.dom.identifier.EntityTypes”).TYPE_FOLDER 
            

The following example code will output a list of faculty member names, assuming that Pages in current Folder have proper Data Definition assigned:


            #set ( $currentFolder = $_.locateFolder($currentPage.parentFolderIdentifier.path.pathAsString ))  
<p>Faculty members:</p>  
<ul>  
#foreach($child in $currentFolder.children)  
    <li>  
        $child.getStructuredDataNode("bio/first").textValue  
        $child.getStructuredDataNode("bio/last").textValue  
    </li>  
#end  
</ul> 
            

In the example above, the current Folder could also be accessed using a much easier way, through the following code:


            #set ( $currentFolder = $currentPage.parentFolder ) 
            

An alternative way for locating the page could be:


            #set ( $callingPage = $_.locate($currentPagePath, $_FieldTool.in(“com.hannonhill.cascade.model.dom.identifier.EntityTypes”).TYPE_PAGE, $currentPageSiteName))
            
Query API

In addition to basic asset retrieval functionality, the Locator Tool also has the ability to search for assets based on a number of search criteria. The first step in using this api is to create a new query object like this:


                #set($query = $_.query())  
            

All executions of the query object require that either a Metadata Set or Content Type be specified on the query object itself.  To do this, use one of the following two methods:


            #set($query = $query.byMetadataSet("Blog"))  
#set($query = $query.byContentType("site://common/Standard Page")) 
            

The Metadata Set or Content Type is specified using the asset link format commonly used when linking between home area assets. Asset links begin with an optional site prefix (e.g. "site://example.com") followed by the path of the asset.

Next, specify which asset types you would like to include in your results:


            #set($query = $query.includePages(true))  
#set($query = $query.includeFiles(true))  
#set($query = $query.includeBlocks(false))  
#set($query = $query.includeFolders(true))  
#set($query = $query.includeSymlinks(false)) 
            

All of these properties will be true by default, but are all listed here for completeness.  Note that if you are matching by Content Type and not Metadata Set, only Pages will be returned.

To limit the results to only assets that have a particular value for one of their metadata fields, use either the hasMetadata() or hasAnyMetadataValues() method.


            ## having a specific value "Index"
#set($query = $query.hasMetadata("displayName", "Index"))
## having one or both of either "value1" or "value2"
#set($query = $query.hasAnyMetadataValues('category', ['value1', 'value2']))
            

hasMetadata(String fieldName, String fieldValue) - accepts a single value where it will try to match assets containing the supplied value.

hasAnyMetadataValues(String fieldName, Collection<String> fieldValues) - accepts an array containing multiple values where it will try to match assets containing at least one of the supplied values.

Note: hasMetadata(String fieldName, Collection<String> fieldValues) has been depracated in favor of the new hasAnyMetadataValues(fieldName, fieldValues) method.

To limit the results to only assets that have a particular value for one of their metadata fields, use either the hasTag() or hasAnyTags() method.


            ## having a specific tag "tag1"
#set($query = $query.hasTag("tag1"))
## having one or both of either "tag1" or "tag2"
#set($query = $query.hasAnyTags('category', ['tag1', 'tag2']))
            

hasTag(String tagName) - accepts a single value where it will try to match assets containing the supplied tag.

hasAnyTags(String tagName) - accepts an array containing multiple tags where it will try to match assets containing at least one of the supplied tags.

A number of additional filtering options are available for your query including which can be supplied using the following methods:

  • maxResults(number of results) - Limit the query to a specified number of results.  The default value is 100 while the maximum value for this filter is 2,000.  Anything greater will be trimmed down to 2,000.
  • sortBy(field name) - Results can be sorted by any one of the following properties:
    • Static Metadata Fields ("author", "description", "displayName", "endDate", "keywords", "reviewDate", "startDate", "summary", "teaser", "title")
    • Last modified date ("modified")
    • Creation date ("created")
    • Asset name ("name")
    • Asset path ("path")
  • sortDirection(direction) - Results can be sorted in ascending ("asc") or descending ("desc") order
  • siteName(siteName) - Results can be limited to a particular Site using the Site's name
  • searchAcrossAllSites() - Results can come from all Sites
  • publishableOnly(true/false) - Results can be filtered to only include those that are publishable
  • indexableOnly(true/false) - Results can be filtered to only include those that are indexable. Note that when set to true, matched results must also have an empty start date or a start date in the past and an empty end date or an end date in the future.

                #set($query = $query.maxResults(30))  
    #set($query = $query.sortBy("name"))  
    #set($query = $query.sortDirection("desc"))  
    #set($query = $query.siteName("example.com))  
    #set($query = $query.searchAcrossAllSites())  
    #set($query = $query.publishableOnly(true))  
    #set($query = $query.indexableOnly(false))  
            

Once all required properties have been set and all desired filtering options have been specified, use the execute() method to retrieve your results.


                #set($results = $query.execute())  
      
    #foreach($page in $results)  
    $page.name  
    #end  
            

Note that all query object methods can be chained together for more concise method calls.


            #set($results = $query.byMetadataSet("Default").includePages(true).maxResults(10).sortBy("name").sortDirection("asc").execute())
            

To see the current state of the query object itself, format writers can reference the query object variable. This will output a list of all the properties and their current values.

Query object reference:


            #set($query = $_.query())  
#set($query = $query.includeFiles(false))  
#set($query = $query.byMetadataSet("Default"))  
  
$query 
            

Output:


            [metadataFieldName = null [displayName|title|summary|teaser|keywords|description|author|startDate|endDate|reviewDate]
 metadataFieldValues = [null]
 * Assign metadataFieldName and metadataFieldValue by calling hasMetadata($name, $value)
 tags = [null]
 * Assign tags by calling hasAnyTags(['tag1', 'tag2']) or hasTag('tag')
 metadataSetLink = Default
 includePages = true
 includeBlocks = true
 includeFiles = false
 includeFolders = true
 includeSymlinks = true
 * Assign contentTypeLink by calling byContentType($link) or metadataSetLink by calling byMetadataSet($link)
 sortBy =  [summary|keywords|endDate|author|created|displayName|description|title|path|reviewDate|name|modified|startDate|teaser]
 sortDirection = asc [asc|desc]
 maxResults = 100 [anything above 2000 will be trimmed down to 2000]
 siteName = www.example.edu
 * Call searchAcrossAllSites() to null out
 indexableOnly = true
 publishableOnly = false]
  
Call execute() to get search results 
            
Locator Tool and Performance

Locator Tool can be considered an alternative to Index Blocks altogether. Most formats that use Index Blocks could be rewritten to use Locator Tool instead. Using the Locator Tool in general is much slower than retrieving assets with an Index Block, in that for example, an Index Block with 1,000 assets rendered will generally complete rendering much faster than if a Locator Tool was to perform locate() calls 1,000 times, especially if Index Block rendering cache is used. However, in most cases, the reason for rendering so many assets in an Index Block is only so that it encompasses just a few assets that are really needed for the rendering of a specific Page, such assets being usually spread out across the system. In these scenarios, using the Locator Tool just a few times versus rendering an Index Block with 1,000 assets in it is going to be much faster and a better solution.

To prevent the possibility of a Velocity Format from rendering too slowly or taking too many system resources, and therefore to prevent the Velocity Formats from potentially making the system unstable, the maximum Format transformation time has been set to 5 minutes. After that time, the rendering process will stop, also preventing the Page from getting published. To prevent this from happening, developers should be careful of the number of times the Locator Tool is being used as well as number of times referencing properties are being accessed (examples: asset’s parent Folder, Folder’s children, an asset selected through structured data asset chooser).

Math Tool

The Math Tool provides convenience methods for converting numeric text to real numbers are performing various mathematical operations.  Some examples are provided below and the full API documentation can be found here.

Converting numeric text to real numbers:  The Math Tool provides simple methods for converting numeric text -- such as the values returned from XML nodes -- into real numbers, suitable for performing math operations.  For example, previously, to convert the numeric text derived from a page metadata field to a real number in Velocity would require the following:

Note:  This example assumes an index block, with "Append Calling Page Data" selected and a page with the "Teaser" metadata field set to some numeric text, i.e. "25".


                #set ( $numText = "0" )  
    #set ( $numText = $_XPathTool.selectSingleNode($contentRoot,"//calling-page/system-page/teaser").value )  
    #set ( $realNumber = 0 )  
    #set ( $realNumber = $realNumber.parseInt($numText) )  
            

Line-by-line explanation:

1.  Initialize a placeholder $numText variable to a string containing valid numeric text.  This step is necessary to avoid a runtime error when calling parseInt() later, as parseInt() is not written to fail gracefully for a Velocity script -- i.e. it throws an exception rather than simply returning null on failure.
2.  Assign a new value to $numText, derived from the contents of the current page's "Teaser" field. 
3.  Create a dummy integer variable, $realNumber, and set its value to a real number.
4.  Use the dummy integer variable, $realNumber, to convert $numText to an integer value.

The above is obviously neither the most efficient nor intuitive way of converting numeric text to a real number.  With the Math Tool, the above can be accomplished with the following code:


                #set ( $numText = $_XPathTool.selectSingleNode($contentRoot,"//calling-page/system-page/teaser").value )  
    #set ( $realInt = $_MathTool.toInteger($numText) )  
    #set ( $realDouble = $_MathTool.toDouble($numText) ) 
            

Line-by-line explanation:

1.  Create a variable, $numText, and assign it a value derived from the contents of the current page's "Teaser" field.
2.  Create a variable, $realInt, using $_MathTool.toInteger() to convert the $numText into a real integer value (i.e. 25).
3.  Create a variable, $realDouble, using $_MathTool.toDouble() to convert $numText into a real double (floating-point decimal) value (i.e. 25.39).

Performing math operations:  The Math Tool also has numerous methods for performing various math operations.


                #set ( $numbers = [23,42,26.3,21,67,89] )  
    #set ( $average = $_MathTool.getAverage($numbers) )  
    #set ( $total = $_MathTool.getTotal($numbers) )  
    <p>Total = ${total}</p>  
    <p>Average = ${average}</p><br/>  
    <p>Ceiling of total = ${_MathTool.ceil($total)}</p>  
    <p>Floor of total = ${_MathTool.floor($total)}</p>  
    <p>Average, rounded = ${_MathTool.round($average)}</p>  
    <p>Average, rounded to 2 decimals = ${_MathTool.roundTo(2,$average)}</p>  
            

Line-by-line explanation:

1.  Creates an array of numeric values, called $numbers.
2.  Calculates the average of all items in the $numbers array, and stores the result in a variable, $average.
3.  Calculates the total of all items in the $numbers array, and stores the result in a variable, $total.
4.  Outputs the total (268.3).
5.  Outputs the average (44.71666666666667).
6.  Outputs the ceiling of $total (total = 268.3, so ceiling = 269).
7.  Outputs the floor of $total (total = 268.3, so floor = 268).
8.  Outputs the average, rounded to the nearest whole number (45).
9.  Outputs the average, rounded to 2 decimal places (44.72). 

Number Tool

The Number Tool contains several method for formatting various types of numeric data.  Some examples are shown below and the full API documentation may be found here.


                #set ( $myNumber = 13.55 )  
    <p><strong>My number as percentage =</strong> ${_NumberTool.percent($myNumber)}</p><br/>  
    <p><strong>My number as currency =</strong> ${_NumberTool.currency($myNumber)}</p><br/>  
    <p><strong>My number as integer =</strong> ${_NumberTool.integer($myNumber)}</p><br/>  
            

Line-by-line explanation:

1.  Creates a variable, $myNumber, and assigns it a numeric value (13.55).
2.  Outputs $myNumber as a percentage (1,355%).
3.  Outputs $myNumber as currency ($13.55)
4.  Outputs $myNumber as an integer (13).

Property Tool

The most important use of this tool is using the outputProperties() method to display all available properties and methods a given object exposes, which is very helpful for Velocity Format developers. For example the following code will output all the properties and methods the current Page provides:


            $_PropertyTool.outputProperties($currentPage) 
            

Please note that some of the properties can output null values. The second use of the PropertyTool is to be able to easily verify whether or not an object is null, for example:


            #set ( $hasStructuredData = !$_PropertyTool.isNull($currentPage.structuredData)) 
            
As of Cascade CMS 8.0.2 you can also verify whether or not given String is empty. This will return true if the String is null, it is an empty String or it contains only whitespace characters, for example:

            #set($isThisEmpty = $_PropertyTool.isEmpty('    ')) ## $isThisEmpty has true value assigned
            

            $_PropertyTool.outputFirstNotEmpty($property1, $property2, $property3, $property4)

## Example
$_PropertyTool.outputFirstNotEmpty(page.metadata.title, page.metadata.displayName, page.name, page.getStructuredData("label").textValue)
            
Outputs the first non-empty property found. The example checks title, display name, name or data definition label field in that order.

Serializer Tool

The Serializer Tool allows users to take any node in the XML hierarchy backed by JDOM and serialize it into its underlying XML.  This makes it possible to do things like retrieve the contents of a WYSIWYG node in a structured data Page and convert it straight to XML without having to output each node in the JDOM tree manually. 

The Serializer Tool's serialize() method takes two arguments.  The first argument can be any JDOM Element.  The second is a boolean which determines whether or not the XML for the Element passed as the first argument is removed from the output or not.


            #set($sd = $_XPathTool.selectSingleNode($contentRoot, '//system-page[@current]//system-data-structure'))  
Structured Data Serialized: $_SerializerTool.serialize($sd, false) 
            

Note: The block used with this example must include page XML inline; the page used must employ a structured Data Definition.  If these criteria are not met, the output of this example will not be relevant.

Line-by-line explanation:

  1. Retrieves the structured data portion of the system-page node corresponding to the current Page by using the XPath Tool and stores it in the variable $sd.
  2. Serializes the JDOM object representing the root structured data element into raw XML.  Notice that the second argument to the serialize() method is false meaning the root element of the XML chosen to be serialized will NOT be removed from the output.

As of Cascade CMS 8.0.2 the Serializer Tool has a new method available: toJson(xml, removeRoot). This method will convert given XML String or Element into a String in JSON format and optionally remove the root element. For example, this code:


            $_SerializerTool.toJson('<xml><page id="id1">Page1</page><page id="id2">Page2</page></xml>', true)
            
... will result with this JSON String:

            {"page":[{"id":"id1","content":"Page1"},{"id":"id2","content":"Page2"}]}
            

Sort Tool

The Sort Tool is modeled after the <xsl:sort/> directive and contains two methods: sort() and addSortCriterion().  The sort() method takes a list of JDOM Elements, which can be acquired using the XPath Tool, and sorts them based on the criteria specified using the addSortCriterion() method.  The addSortCriterion() method takes 5 arguments: a selection string, language, data type, sort order, and case order.  Below is a description of each argument.

Method addSortCriterion():

  • selection string - An XPath expression specifying the node/node-set on which to sort.
  • language - Specifies the two-letter ISO-639 language code to be used when sorting text data, defauls to "en".
  • data type - Either "text", "number", or "qname", defaults to "text".
  • sort order - Either "ascending" or "descending", defaults to "ascending".
  • case order - Either "lower-first" or "upper-first", specifies whether upper-case or lower-case letters come first when sorting, defaults to "lower-first".
Multiple criteria can be added to the Sort Tool by calling addSortCriterion() as many times as desired with different parameters.  When sorting, if the first criterion added to the sort tool results in two Elements being treated as equal; the next criterion that was added will be used and so on until "uniqueness" is achieved between the two.  Each call to the sort() method will reset the current list of criteria being used to sort.

            #set($sys_pages = $_XPathTool.selectNodes($contentRoot, '//system-page'))  
$_SortTool.addSortCriterion("name", "", "text", "ascending", "upper-first")  
$_SortTool.sort($sys_pages)  
  
<h2>Pages listed in order by name</h2>  
#foreach($page in $sys_pages)      
    <p>Page Name: $page.getChild('name').value</p>  
#end 
            

Note: The block used with this example must contain at least one 'system-page' element; otherwise the output will contain no results.

Line-by-line explanation:

  1. Uses the XPath Tool to retrieve all system-page nodes in the contentRoot.
  2. Adds a new sort criterion that specifies that items should be sorted by the value of the name element with the language defaulting to english, the data type being text, sort order ascending, and with upper case letters being placed first in order when comparing two pages with the same name.
  3. The Sort Tool is being used to sort the system-pages.  Notice that you do not have to issue a #set directive.  This is because the sorting is done "in place" and does not require that a new list be created.
  4. (blank)
  5. Outputs a heading for our list of pages.
  6. Begins iterating over our sorted list of system-pages.
  7. Outputs each system-page's name.
  8. Ends iteration.

As of Cascade Server 7.4, the SortTool also acquired the following functions:

  • sort(Collection collection), sort(Object[] array), sort(Map map) - sorts the collection, array or map using natural order. For example a collection of Strings will be sorted alphabetically.
  • sort(Collection collection, String property), sort(Object[] array, String property), sort(Map map, String property) - sorts the collection, array or map using natural order of a property with given name. For example, a collection of Pages can be sorted by name or by folderOrder.
  • sort(Collection collection, List properties), sort(Object[] array, List properties), sort(Map map, List properties) - sorts the collection, array or map using natural order of a list of properties with given names. For example, a collection of Pages in the system can be sorted by createdBy and within these, they can be sorted by createdOn.

Here is an example of Velocity Format that outputs all assets under root folder sorted by folder order:


            #set($folder = $_.locateFolder("/"))  
#outputFolder($folder)  
  
#macro(outputFolder $folder)  
   #set($children = $folder.children)  
   #set($sortedChildren = $_SortTool.sort($children, "folderOrder"))  
   <ul>  
    #foreach($child in $sortedChildren)  
        <li>$child.name</li>     
    #end  
   </ul>  
#end 
            

            #set($sorted = $_SortTool.sort($assets, "metadata.dynamicField(myDynamicField).value")) 
#set($sorted = $_SortTool.sort($pages, "structuredDataNode(myField).textValue"))
            

It's possible to use dot-notation and parantheses to access specific metadata fields and structured data fields by name by providing their name or path. If some of the sorted assets do not have given field, they should be removed from the list first using "$_ListTool.removeNull".

String Tool

The String Tool contains two methods, substringBefore() and substringAfter(), which may be familiar to users who have used XPath string functions at some point.  Both methods take two string arguments.  The first argument is searched to determine if it contains the second argument.  If the second argument is found in the first, then a portion of the first argument is returned.  Depending on which method is used, either the portion of the first argument that comes before the second argument  is returned (substringBefore()) or the portion of the first argument that comes after the second argument is returned (substringAfter()).  If the second argument cannot be found in the first, then an empty string is returned.

For example, if one were to call the substringAfter() method with the arguments "/path/to/asset" and "path", the result would be "/to/asset" because "/to/asset" is the prtion of "/path/to/asset" that comes after "path".  Likewise, if you were to call substringBefore() with the arguments "/path/to/asset" and "asset", the result would be "/path/to/".


                #set($sys_pages = $_XPathTool.selectNodes($contentRoot, '//system-page'))  
    $_SortTool.addSortCriterion("name", "", "text", "ascending", "upper-first")  
    $_SortTool.sort($sys_pages)  
      
    <h2>Pages listed in order by name</h2>  
    #foreach($page in $sys_pages)      
        <p>Page Name: $page.getChild('name').value - Path: $_StringTool.substringAfter($page.getChild('path').value, "test")</p>  
    #end
            

Note: The block used with this example must contain at least one 'system-page' element; otherwise the output will contain no results.

Line-by-line explanation:

1-6. Same as Sort Tool explanation.
7. Page name and path are output but only the part of each page's path that follows the string "test" is returned.  This could be used if pages in the index are contained in the "/test" folder and it was not desired for that section of the path to be included in the output.
8. Same as Sort Tool explanation.

XPath Tool

Support for XPath statements is now available as part of Cascade's Velocity resources. This allows users to query the JDOM XML structure using an XPath expression, similar to how this would be performed if you were using an XPath expression in the "select" attribute of an XSL template. For example, if you want to retrieve all system-page elements within an index block; you can now do so with an XPath query, rather than by manually drilling down in the JDOM structure.

Below is an example of how you can query for all the groups the current user is member of and output them as an unordered list.


                #set($fullname = $_XPathTool.selectSingleNode($contentRoot, '//user-information/full-name'))  
    #set($groups = $_XPathTool.selectNodes($contentRoot, '//user-information/groups/group'))  
    <p>Hello, $fullname.value. You are a member of the following groups:</p>  
    <ul>  
    #foreach($group in $groups)  
        <li>$group.value</li>  
    #end  
    </ul>  
            

Note: The Index Block used with this example must include user information.

Line-by-line explanation:

  1. Retrieves the full-name node from the index block by using the XPath Tool and stores it in the variable $fullname.
  2. Retrieves the list of group nodes from the index block by using the XPath Tool and stores it in the variable $groups.
  3. Outputs a welcome message including the current user's name.
  4. Opens an unordered list.
  5. Begins iterating over the group nodes.
  6. Outputs each group name as a list item.
  7. Terminates the iteration.
  8. Closes the unordered list.
A full list of available methods on the XPath tool can be found in the JDOM XPath API.