ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Scripting Java Applications with XML and Simkin

by Simon Whiteside
02/01/2001

Storing behavior in XML files

XML is increasingly used to store data in Java applications. This article describes how XML can be extended to incorporate behavior, using the author's open source scripting language Simkin.

But why would you want to have behavior stored within XML? I'll illustrate by describing what led me to develop Simkin in the first place.

Imagine you're working on an adventure game: the game is divided into scenes, and each scene contains a number of characters. A natural representation would be to have Java Scene and SceneObject classes, storing each scene in an XML file.

<scene name="OwlWood">
<object name="Owl"/>
</scene>

This is a scene in the Owl Wood, The wood contains an owl.

The game requires that characters be visible at different times during the action, so we might add a visibility property.

<object name="Owl" visible="false"/>

Expressions

It would be good to make visibility dependent on something else; perhaps the result of a method call.

<object name="Owl" visible="isOwlVisible()"/>

We need some glue to evaluate "isOwlVisible()". The Java code could find the matching method, which it would assume to return a boolean, by introspection. It would be even nicer to be able to write expressions like

<object name="Owl" visible="not have_visited_owl_wood and not owl_spoken"/>

Now we have variables "have_visited_owl_wood" and "owl_spoken", and a simple expression syntax using and and not. We also need more Java code: an expression evaluator and a way of storing or retrieving values.

Statements

It turns out that the game requires that the owl has to say one thing if it's the first time the player has seen it, and something else the second time. This requirement takes us beyond the need for a simple expression evaluator into the realms of program logic.

In pseudo code, we want something like the following to be called when the player enters the scene:

if  num_visits=0 then play("FirstVisit.au") else play("NextVisit.au") num_visits=num_visits+1

There is no standard way of embedding this kind of script within XML, although there are two basic approaches: first, use XML tags for keywords; second, embed a script within the text between tags.

There aren't any standards for using XML tags for behavior, although common ways are emerging. Here's how we might represent the pseudo code:

<object name="Owl">
<function name="initialise">
<if condition="num_visits=0">
 <play file="FirstVisit.au"/>
<else>
 <play file="NextVisit.au"/>
</if>
<assign variable="num_visits"
value="num_visits+1"/>
</function>
</object>

In Simkin I chose to use the second approach. Here's the same code in Simkin:

<object name="Owl">
<function name="initialise">
if (num_visits=0){
  play("FirstVisit.au");
}else{
  play("NextVisit.au");
}
num_visits=num_visits+1;
</function>

I find this style more readable, and it has the advantage that the rules for character encoding within PCDATA sections are more relaxed than for attribute values.

The Simkin Interpreter

In either case you now need Java code to parse and interpret the statements, as well as evaluate expressions and access variables. In the case of Simkin I decided to develop an Interpreter class, using JavaCC to develop a parser.

Once the interpreter has parsed the script, it executes the statements one by one. The interpreter uses Java introspection to find methods and fields within Java objects.

I wanted the script to be able to call other Simkin functions and Java methods using the same syntax. This makes it easy to move subroutines into or out of Java as required. In the example above, play might have started life as Java method, but become a Simkin wrapper method.

To achieve this, the interpreter uses introspection to find a method, unless an object implements a special interface called Executable, in which case it delegates the responsibility of finding the method to the object itself. This means an object could first look for a Simkin method with the matching name.

The example above shows the utility of script access to variables. Simkin supports 4 kinds of variables:

  • locally defined variables within a function,
  • other elements within the same XML document,
  • fields within Java objects, and
  • "global" objects which are accessible from any script.

I found Simkin very useful when developing my adventure game, "The Animals of Farthing Wood". I developed a small amount of generic game code, which was then used by a team of 3 scripters to create the logic of the whole adventure.

You can obtain the Simkin interpreter free from the Simkin web site.

Simon Whiteside is an experienced software architect and developer, using Java and other languages such as C++.


Return to ONJava.com.