CGG   Scripting in JaGrLib

There is simple XML scripting capability built in the JaGrLib: JGL script is a XML file with set of tags corresponding to basic Java commands. You can create Java objects (including JaGrLib objects and modules), link them together and return arbitrary set of such instances back to the caller..

JGL scripts were introduced originally for CSG-scene definition purposes, so there are no structured commands such as if, for or switch.

JGL script syntax

Syntactic diagrams (details will be given below):

INSTANCE      <- $object$ |
                 $ref$    |
                 $member$ |
                 $function$

OBJECT        <- INSTANCE |
                 $array$  |
                 $def$    |
                 $val$    |
                 "<null />"

METHOD        <- $method$ |
                 $set$

SEQUENCE      <- OBJECT*

$script$      <- "<script>"
                   { $object$   |
                     $array$    |
                     $def$      |
                     $function$ |
                     $return$ }*
                 "</script>"

$object$      <- "<object" [ " id=" ID ] ">"
                   { $class$ [ $constructor$ ] |
                     $function$ }
                   METHOD*
                 "</object>"

$array$       <- "<array" [ " id=" ID ] ">"
                   { [ $class$ ] SEQUENCE |
                     $data$ }
                 "</array>"

$return$      <- "<return>"
                   ( $key$ OBJECT )*
                 "</return>"

$constructor$ <- "<constructor>"
                   SEQUENCE
                 "</constructor>"

$method$      <- "<method>"
                   $name$
                   SEQUENCE
                 "</method>"

$set$         <- "<set" [ " key=" KEY ] ">"
                   [ $key$ | OBJECT ]
                   OBJECT
                 "</set>"

$function$    <- "<function>"
                   INSTANCE
                   $name$
                   SEQUENCE
                 "</function>"

$member$      <- "<member>"
                   { $class$ | INSTANCE }
                   $name$
                 "</member>"

$val$         <- "<val" [ " type=" TYPE ] ">"
                   LITERAL ( "," LITERAL )*
                 "</val>"

$data$        <- "<data" [ " type=" TYPE ] ">"
                   LITERAL ( "," LITERAL )*
                 "</data>"

$def$         <- "<def key=" KEY [ " type=" TYPE ] ">"
                   LITERAL ( "," LITERAL )*
                 "</def>"

$class$       <- "<class>" 'fully-qualified Java class' "</class>"

$name$        <- "<name>" 'Java identifier' "</name>"

$key$         <- "<key>" 'arbitrary string' "</key>"

ID            <- 'unique identifier'

TYPE          <- "Z" |
                 "B" |
                 "C" |
                 "S" |
                 "I" |
                 "J" |
                 "F" |
                 "D" |
                 "T" |
                 "L" 'fully-qualified Java class' ";" |
                 "[" TYPE

KEY           <- 'arbitrary quoted string'

LITERAL       <- 'long Java literal' |
                 'double Java literal' |
                 QUOTE 'arbitrary string' QUOTE

QUOTE         <- 'arbitrary non-comma character legal in XML elements'

How to call JGL script from JaGrLib

All scripting code is included in the cz.cuni.jagrlib.xml.JGLScript class. You can simply create an instance of this class and let it interpret your scripts from XML files. Optional input hash-map can be passed as the 2nd parameter. Example:

import java.util.Map;
import cz.cuni.jagrlib.iface.*;
import cz.cuni.jagrlib.xml.JGLScript;

...

  LightSource  light  = null;
  RayGenerator camera = null;

  Map< String, Object > input = new HashMap< String, Object > ();
  input.put( "position", new double[] { 0.0, 8.0, 0.0 } );

  JGLScript script = new JGLScript();
  Map< String, Object > map = script.interpret( "environment.jgl", input );
  if ( map != null )
  {
    Object o;

    if ( (o = map.get( "camera" ) ) != null &&
         o instanceof RayGenerator )
      camera = (RayGenerator)o;

    if ( (o = map.get( "light" ) ) != null &&
         o instanceof LightSource )
      light = (LightSource)o;
  }
As you can see, interpreter object returns a Map<String,Object> on success (if fatal error has occured, null is returned and error description is written into the log-file).
Unlimited number of Java objects can be returned from a JGL script. All objects are tagged by unique string identifiers. Script author must define returned objects in one of <return> sections.

Once created, JGLScript instance can be used repetitively, even from different threads (but the interpret() function is declared synchronized, so effectively only one thread can use it at the same time).

JGL details

<object>

<object> section defines a new class instance. If named ("id=" attribute) it can be referenced afterwards using the "<ref>" command.

There are three ways to construct a new class instance:

  1. "<constructor>" section defines constructor arguments (thus selects one from multiple available constructors)
  2. "<function>" section declares that a new class instance will be returned from a function call
  3. if neither of two listed sections has occured, default (non-argument) constructor will be used
In cases 1. and 3. "<class>" element has to define object's class.

After constructing class instance, you can write arbitrary number of method calls ("<method>" or "<set>" sections) in the <object> section.

<class>

<class> element defines class name (either fully-qualified or short name prefixed by one of: "cz.cuni.jagrlib.", "cz.cuni.jagrlib.piece.", "cz.cuni.jagrlib.testing.", "cz.cuni.jagrlib.iface.", "cz.cuni.jagrlib.obscure.", "cz.cuni.jagrlib.worker.", "java.lang."). Any standard or JaGrLib class can be used.

<constructor>

<constructor> element could either be empty (for default constructor) or contains sequence of actual constructor arguments.

<method>

<method> section defines method identifier first, followed by optional list of arguments.

<set>

<set> section is shortcut for invokation of the set(key,value) method. Only two arguments has to be defined: "key" (key string) and "value" (arbitrary value). Key string can be specified in the "key=" attribute of the <set> element.

<function>

<function> section defines class instance first, followed by mandatory method identifier and optional list of arguments.

Arguments

Function/method/constructor arguments or array elements are defined as arbitrary-sized sequence of following elements:

<array>

"<array>" section defines instance of an array. Multi-dimensional arrays can be constructed naturally by providing arrays as array elements.
If named ("id=" attribute) array object can be referenced using the "<ref>" command.

Array elements: can be defined either using the data section (literal array) or as a sequence of arbitrary objects. In the latter case there must be "<class>" element defining array element type.

<ref>

"<ref>" element defines reference to a previously declared instance/array (or object passed as script-input). Object identifiers are arbitrary strings (w/o leading and trailing whitespaces) and are unique in the scope of JGL script.

<member>

<member> section defines class instance first, followed by member identifier to be fetched.

<val>

<val> element defines data literal - either scalar or vector value. "type=" attribute defines literal type, Java internal type abbreviations are used:

"[" prefix defines 1D array of the following type.

There are definitions of actual data items inside of the <val> element. Natural textual representations are used (read by Java library functions), strings are quoted by arbitrary quotes (single quotes "'" are recommended), array elements are separated by commas ",". The whole array can be surrounded by braces "{}". Some examples:

  <val type="I">4</val>
  <val type="D">3.14</val>
  <val type="T">This is string (with one trailing space) </val>
  <val type="[D">{1.0,-1.0,0.0}</val>
  <val type="[T"> '1st', '2nd', '3rd', '4th' </val>

The "type=" parameter can be ommited: in that case, script interpreter tries the listed variants successively:

  1. integer number (type: integer)
  2. floating-point number (type: double)
  3. boolean literal (type: boolean)
  4. null value (alternative: <null /> element)
  5. otherwise the value is interpreted as string literal, but without any leading or trailing whitespaces (type: Java.lang.String)
Examples:
  <val>4</val>
  <val>3.14</val>
  <val>false</val>
  <val>null</val>
  <val>String literal WITHOUT trailing spaces!  </val>

<def>

<def> element interior is syntactically equal to the "<val>" interior. <def> element names the given data literal so it can be referenced later.

<data>

<data> element interior is syntactically equal to the "<val>" interior. <data> element defines the array "en bloc".

<return>

<return> sections define values returned from a JGL script. There can be arbitrary number of [ key, value ] tuples stored sequentially in one array. "key" is nonempty string (unique within the JGL script), "value" can be any value.

JGL script examples

The following script returns two initialized TrMatrix instances:

<script>
 <object id="mi">
  <class>TrMatrix</class>
  <constructor> <val>4</val> <val>3</val> </constructor>
 </object>
 <object id="m">
  <class>TrMatrix</class>
  <constructor> <val>4</val> <val>3</val> </constructor>
  <method>
   <name>scaleAxes3D</name>
   <null />
   <val>2.0</val>
   <val>0.08</val>
   <val>0.08</val>
   <ref>mi</ref>
  </method>
  <method>
   <name>translate3D</name>
   <val>0.0</val>
   <val>0.25</val>
   <val>1.46</val>
   <ref>mi</ref>
  </method>
 </object>
 <return>
  <key>matrix</key>
  <ref>m</ref>
  <key>inverse</key>
  <ref>mi</ref>
 </return>
</script>
.. and is equivalent to Java code:
 TrMatrix m  = new TrMatrix( 4, 3 );
 TrMatrix mi = new TrMatrix( 4, 3 );
 m.scaleAxes3D( null, 2.0, 0.08, 0.08, mi );
 m.translate3D( 0.0, 0.25, 1.46, mi );
 Map< String, Object > result = new HashMap< String, Object >();
 result.put( "matrix",  m );
 result.put( "inverse", mi );
 return result;


[JaGrLib HOWTO (in Czech)]  [Ray-tracing in JaGrLib (in Czech)]  [JaGrLib home-page]  [CGG at MFF UK]

Valid XHTML 1.1 Copyright (C) 2007-2009 J.Pelikán, last change: $Date: 2013-11-22 23:47:16 +0100 (Fri, 22 Nov 2013) $
Send comments/requests to pepca.at.cgg.mff.cuni.cz