Language basics
Content Script is a Domain-Specific Programming Language (DSL) for OpenText Content Server.
The language is based on Oscript and exposes a Groovy interface to developers. Groovy ( http://www.groovy-lang.org/ ) is a widespread dynamic language for the Java Virtual Machine, particularly indicated for the creation of DSLs.
Content Script language syntax is fully compatible with Groovy.
Under the hood, a mix of Oscript and Java features allow for a deep integration with Content Server functionalities, as well as for an extreme ease of integration with external systems.
The following sections are meant to be an introduction to the language.
Statements¶
The definition of variables can be either generic or restricted to a specific type. Assigning a value to a variable that does not match its type will force the engine to attempt to cast its value to the given type. In case no conversions can be done, it will result in an error.
// Defining a local variable can be done either by
// 1) declaring explicitly its type
// 2) using the "def"
int anInt = 1
String aString = "text"
def anObject = "anything"
anObject = 123
With String variables, a few useful tricks are available:
// Strings can be defined both with quotes ('') or double quotes ("")
String aString = "text"
String anotherString = 'text'
// Selecting the alternative "" or '' can be useful if quotes are present in the string content
String aQuote = "this is a quote: 'My words...' "
String anotherQuote = 'this is a quote: "My words..." '
// using triple """ allows to span across multiple lines for string
// definition. Useful for readable SQL queries, for example..
String multilineString = """SELECT *
FROM DTREE
WHERE DATAID = 2000"""
Lists and Maps can be defined very easily
def aList = ["firstElement", "secondElement"]
def aMap = [firstKey:"firstValue", secondKey:"secondValue"]
// statements can span across multiple lines
def multilineDefinition = ["firstElement",
"secondElement"]
// collections can contain different kinds of elements
def aMapWithStringsAndInts = [first:"one", second:2
Basic Control Structures¶
Below are the basic structures for flow control and iteration
-
if – else statement
-
if – else if – else statement
-
inline if statement
-
switch statement
-
while loop
-
for loop
Flow control: if – else¶
if(a == b){
//do something
} else {
//do something else
}
Flow control: if - else if - else¶
if(a == b){
// do the first thing
} else if(c == d){
// do a second thing
} else {
// do something else
}
Flow control: inline if - else¶
a = (b == c) ? "c is equal to b" : "c is different from b"
Flow control: switch¶
switch ( a ) {
case "a":
result = "string value"
break
case [1, 2, 3, 'b', 'c']:
result = "a mixed list of elements"
break
case 1..10:
result = "a range"
break
case Integer:
result = "is an Integer"
break
case Number:
result = "is a Number"
break
default:
result = "default"
}
Looping: while¶
def a = 0
while (a++ < 10){
// do something ten times
}
def b = 10
while ( b-- > 0 ) {
// do something ten times
}
Looping: for¶
// Standard Java loop
for (int i = 0; i < 5; i++) {
}
// range loop
for ( index in 0..100 ) {
// do something
}
// list or array loop
for ( index in [0, 10, 20, 40, 100] ) {
// do something 5 times
}
// map looping
def aMap = ['first':1, 'second':2, 'third':3]
for ( entry in aMap ) {
// do something for each entry (the values can be accessed and used)
entry.value
}
Operators¶
All Groovy operators can be used in Content Scripts:
Operator Name | Symbol | Description |
---|---|---|
Spaceship | <=> | Useful in comparisons, returns -1 if left is smaller 0 if == to right or 1 if greater than the right |
Regex find | =~ | Find with a regular expression |
Regex match | ==~ | Get a match via a regex |
Java Field Override | .@ | Can be used to override generated properties to provide access to a field |
Spread | *. | Used to invoke an action on all items of an aggregate object |
Spread Java Field | *.@ | Combination of the above two |
Method Reference | .& | Get a reference to a method, can be useful for creating closures from methods |
asType Operator | as | Used for groovy casting, coercing one type to another. |
Membership Operator | in | Can be used as replacement for collection.contains() |
Identity Operator | is | Identity check. Since == is overridden in Groovy with the meaning of equality we need some fallback to check for object identity. |
Safe Navigation | ?. | returns nulls instead of throwing NullPointerExceptions |
Elvis Operator | ?: | Shorter ternary operator |
Methods and Service Parameters¶
Methods on objects can be called using the dot "." followed by the method signature and parameter clause.
out << template.evaluateTemplate("""
#@csform(false, "Submit")
<label for="myFile">File to be uploaded</label>
<input type="file" name="myFile" />
#end
""")
if(params.myFile && params.myFile.filelength){
def parentNode = docman.createFolder("MyFolder")
def file = new File(params.myFile)
if(file && file.canRead()){
docman.createDocument( parentNode, params.myFile_filename, file, "", false, parentNode)
//Redirect after submit
redirect "${url}/open/${self.ID}"
}
}
Methods can be called omitting the parenthesis in the parameter clause, given that (a) there is no ambiguity and (b) the method signature has at least one parameter.
// In certain cases, parenthesis can be omitted
docman.createFolder "MyFolder"
Properties and Fields¶
Properties and public fields of objects can be accessed using the dot "." followed by the property or field name.
def folder = docman.createFolder("myFolder")
// Accessing an object property
def me = folder.createdBy
A safe syntax to navigate through fields is available in Groovy by adding a "?" before the dot. In this case, the chain will be interrupted if one of the intermediate values is undefined, avoiding an exception to be raised.
// Safe field access (no exception raised if folder is NULL)
def me = folder?.createdBy
Comments¶
// Comments are available as single line // and multiline /* */
def a = 1 // A comment can close a line
/* Or span
over multiple
lines */
Closures¶
Content Script inherits from Groovy the concept of Closures. A closure is an open, anonymous, block of code that can take arguments, return a value and that can be assigned to a variable.
// Define a closure and assign it to a variable
def addNumbers = { def num1 , def num2 -> //Arguments
return (num1 as int)+(num2 as int)
}
out << "Calling the addNumbers closure:${addNumbers(4, "5")} <br/>"
addNumbers = { String... arguments -> // Variable number of arguments (MUST be the last parameter)
def total =0
arguments.each{total+=(it as int)}
return total
}
out << "Calling the addNumbers closure:${addNumbers("1", "2","3")} <br/>"
def createNewFolder = { String name, def parentNode = docman.getEnterpriseWS() ->
docman.createFolder(parentNode, "name" )
}
def node = createNewFolder( new Date().format("yyyyMMddHHss"))
out << "Calling the createNewFolder with One arguments:${node.ID} <br/>"
def newNode = createNewFolder( new Date().format("yyyyMMddHHss"), node)
out << "Calling the createNewFolder with Two arguments:${newNode.ID} <br/>"
Content Script programming valuable resources¶
A number of resources can be extremely useful to the Content Script developer at different times. A few of the most important ones are:
Online help
The Content Script Module features an online guide that covers the basic language syntax and functionalities. It also contains quick references to context variables and methods.
Code Snippet Library
When using the Content Script Editor, a library of ready-to-use code snippets is available to bootstrap new scripts without having to start from scratch. The library includes usage examples and code templates for many common use cases, and can be easily extended by the developer.
Groovy reference guide
The Apache Groovy language is supported by a wide community of adopters worldwide. Groovy is supported by the Apache Software Foundation: a significant amount of documentation and examples are available online.
Velocity reference guide
The Apache Velocity engine powers the templating features in Content Script. Velocity is supported by the Apache Software Foundation: lots of documentation and examples can be found throughout the web and on the project’s website.