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.

1
2
3
4
5
6
7
8
9
// 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 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

1
2
3
4
5
if(a == b){
    //do something
} else {
    //do something else
}

Flow control: if - else if - else

1
2
3
4
5
6
7
if(a == b){
    // do the first thing
} else if(c == d){
    // do a second thing
} else {
    // do something else
}

Flow control: inline if - else

1
a = (b == c) ? "c is equal to b" : "c is different from b"

Flow control: switch

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def a = 0

while (a++ > 10){
    // do something ten times
}

def b = 10

while ( b-- > 0 ) {
   // do something ten times
}

Looping: for

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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.

1
2
// 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.

1
2
3
4
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.

1
2
// Safe field access (no exception raised if folder is NULL)
def me = folder?.createdBy

Comments

1
2
3
4
5
6
7
// 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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 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 No 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.

http://www.groovy-lang.org/

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.

http://velocity.apache.org/