Menu

Home

Sly Technologies

EasyLibs Spunk API

An object based namespace and flexible scripting language library. Spunk is most useful in libraries which utilize annotations and wish to provide scripting functionality or and maintain complex/conditional relationships between objects.

Spunk framework provides two important features:

  • Object based namespace
  • Flexible scripting language executable from java against the namespace

Object based namespace

Namespace allows a complex collection of objects and beans to be easily searchable and placed into hierarchies which mimic the file system. In stead of building singletons or maps to reference different part of your business logic systems, create a single namespace and uniquely store any type of objects and reference them by name, path or through search results.

For example:

MutablePath namespace = new PathNode("Q&A"); // Empty root with just a name
namespace.add("questions", new ArrayList<String>());
namespace.add("answers", new ArrayList<String>());
MutablePath users = namespace.add("users");

IPath chris = users.add("ChristopherRobins", new ArrayList<String>());

/* From some input method */
List<String> christophersQuestions = chris.getData();
christophersQuestions.add("Who came up with the name Pooh?");

Spunk Scripts

A script is compiled into binary form and linked against namespace. A script is a regular java string which is compiled. The script can contain expressions or an assignment statements. Expressions always evaluate to a value such as an integer or a boolean. But can evaluate to any type of object, including user objects from namespace.
The compiler provides compilation methods for two types of scripts.

  • statement - an assignment statement (i.e. "root.a = 10")
  • expression - a pure expression that will be evaluated and will produce a result to be returned (i.e. "root.a + 10 < 100 && root.b == true")

Spunk Statements

A statement allows both references to be assigned values with '=' character and expressions to be evaluated. Further more, multiple statements and expressions can be specified in the script when separated using a ';' character.

For example:

root.field1 = 10; root.field1 + 1 == 11

Will result in assigning integer value of 10 to reference field1, then the expression following the ';' character will be evaluated which will result in a boolean true being returned by the IScript.execute method.

Spunk Expressions

Spunk expressions look very similar to java expressions.

For example:

root.field1 + 1 == 11 && root.group2.field13 < (10 - 5 * 2)

Arrays, Lists and Maps

Spunk compiler also allows array and collections references. The syntax for accessing arrays and arrays, lists and maps is using associative array syntax using [] characters. For arrays and lists, the value between [] characters must be an integer. For maps the value between [] can be any object but must match the key used in the underlying map object.

For example:

class MyClass {
    public final List<String> list = new ArrayList<>();
    public final Map<String, Integer> map = new HashMap<>();
    public final int[] array = new int[10];
 }

MyClass obj = new MyClass();

obj.list.add("string1");
obj.map.put("key1", 10);
obj.array[0] = 100;

MutablePath namespace = new PathNode("root");
namespace.addBean("list", obj.list);
namespace.addBean("map", obj.map);
namespace.addBean("array", obj.array);

namespace.evalStatement("list[0] =  'string2'");
namespace.evalStatement("map['key1'] = 20");
namespace.evalStatement("array[0] = 200");

System.out.printf("list[0]=%s, map[key1]=%d, array[0]=%d%n", obj.list.get(0),
            obj.map.get("key1"), obj.array[0]);

This will result in the following output to console:

list[0]=string2, map[key1]=20, array[0]=200

Note that multi-dimensional arrays and accessors are supported in the form 'list[0][1][2][3]' and so forth as long as the underlying object hierachy is made up of lists. You may also mix arrays, lists and maps in multi-dimensional arrays and the appropriate type will be resolved dynamically at runtime to an appropriate setter and getter accessor.

Exporting beans

Any object that follows the bean pattern can be exported into the namespace and referenced from within the spunk script. All bean properties automatically become available as references. The data types and typecasting is automatically determined and handled, although when mismatched occur, a cast exception may be raised. Also for methods that do not follow the bean naming patter for setters and getters, the properties can be exported manually by listing them during namespace creation.

For example:

String myBean = "hello world";
IPath path = new PathNode("root", myBean, "length");

boolean isLongerThen5 = path.evalExpression("root.length > 5");

The above spunk expression is equivalent to java expression:

boolean isLongerThen5 = myBean.length() > 5;

Also note that we could have shorted the expression to just "length > 5" since spunk will do a search in the namespace for the symbol 'length' and use it when resolved.

The example creates a bean object, which is simply a string. Then it create a namespace in the form of a single IPath node which is bound to myBean. Then it manually exports the property "length" since it does not follow the standard bean pattern for setLength/getLength and would not be recognized otherwise. Lastly a script is executed and the expression result is a boolean value which is returned. Since the length of our string is greater then 5 characters, the returned value will be true.


MongoDB Logo MongoDB