Author: Timo Laitinen
Date: 2006-05-28
Contents
1. What Is JIC Language?
JIC Language is an XML vocabulary for defining graphs of Java objects. It provides a descriptive and specialized format for describing the state of a group of Java objects.
XML code written in JIC Language is processed by the JIC Engine, a Java program that interprets the information and creates and initializes the actual Java objects.
Before going into the details of the language, the term initialization is explained more thoroughly.
1.1. Initialization of Java Objects
The term initialization is a process where the state of a Java object is set so that it is ready to be used in an application. Although the object state may change also during its lifetime, every object has some kind of an initialization phase.
The simplest way to initialize an object is to make a constructor call. Necessary parameters are provided via constructor arguments and the object is ready for service after the instantiation. According to good object-oriented principles, an object should we in a valid state after the constructor call.
Single constuctor call is rarely enough, though. In practice the object often needs to be configured further by calling one or more of its methods. In addition, objects may also be retrieved from various factories, and the actual constructor call is hidden. And since objects have dependencies to other objects, the initialization of one Java object requires the initalization of also other objects.
The initialization of a Java object therefore consists of the following steps:
-
Collateral initialization - the initialization of additional objects:
- Argument objects - objects that will be used as arguments to a constructor or method call in the object acquisition phase.
- Helper objects - objects that are used in the initialization of the object and discarded afterwards.
-
Object acquisition - obtaining the instance to be initialized:
- Instantiating the object with a constructor call.
- Invoking a method that yields the object. (call to a factory method, for example)
- (Obtaining the value of a static field.)
-
State refinement - calling various initialization methods of the object.
- Initialization methods have always side-effects and they usually do not return anything.
- For example: setting bean properties.
Some notes:
- The initialization process is recursive - the initialization of one object may require the initialization of other objects.
- There is no single way for object acquisition - both constructor and method invocations are used.
- Full initialization requires also calling various initialization methods after the object has been acquired.
The purpose of the initialization process is to set the parameters of an object. Objects are parameterized because the values of some variables was not known when the code was written. Therefore the purpose of the initialization process is to define the detailed values for the parameters.
Details are usually information that needs to be changed relatively easily. Therefore various configuration files are used for storing the detailed values - configuration files are easier/faster to change than Java code. Example of this is the use of properties files in Java applications.
After the initialization, the object is ready to be used somehow. Usually a reference to the object is given to other objects in the application and the objects start to interact with each other via method calls. The state of the initialized object may change during its lifetime. Sooner or later the object is discarded or the whole application is stopped. The events that occur after the initialization are not in focus here. Regardless of what happens when the object is used, each object has some kind of an initialization phase.
1.2. Purpose of JIC Language
JICE is a tool specialized into the initialization and JIC Language is the XML-based language used for describing the details of the process. JIC Language code can be understood as procedural code. The JIC Engine processes the XML elements much in the order that they appear, so the elements can be thought to be executed. The XML code can be seen as a large patch process that constructs the graph of objects.
The language supports the initialization process presented in the previous chapter fully. JIC Language can be used for both defining a String and a complex graph of Swing components. No restrictions are placed on the kind of constructors or methods an object has or what interfaces it implements. JIC Language may initialize any kind of Java object.
However, JIC Language may be used only for describing the object state. It is not a general purpose programming language and can not be used for expressing complex logic. Application logic must be put into the Java classes.
Here are some of the advantages of JIC Language over plain-old Java code:
- Easier/faster to change: no compilation required.
- The XML code can be produced/manipulated dynamically with various XML technologies. (also during application lifetime.)
- The XML format is a more descriptive format for representing minor details such as numbers, texts, colors, fonts, etc.
- The XML tree visualizes the structure of the object graph better than Java code.
2. About This Document
This document specifies the syntax and semantics of JIC Language, the XML configuration format of JICE. The document serves both as a tutorial for learning JIC Language and as the specification of the language.
In contrast, the other parts of JICE (i.e. the JIC Engine) and the way JICE could be utilized in real-life applications are not discussed.
2.1. About the Examples
All the examples are manipulating the standard J2SE classes, because the standard Java API is familiar to all Java developers.
However, JIC Language is by no means limited to operating only with the standard Java API. In fact, if JIC Language would be used in a real-life application, the JIC files would manipulate most likely the application classes.
Because the purpose of the examples is to demonstrate the capabilities of the JIC Language, some of them may seem even absurd if viewed as actual configuration files.
3. Overview of JIC Language Syntax
Here is a list of the most significant characteristics of the JIC Language syntax:
-
JIC files are XML files containing JIC Language code. The use of file-suffix
.jicis encouraged. - JIC Language specifies a common element type called JIC Element. Every XML element in a JIC File is a JIC Element.
-
JIC Language does not have a fixed set of XML elements:
- (In most cases) the author of the file chooses the name of the elements in the same way as a programmer chooses variable names.
- In some situations the name depends on the Java API being manipulated.
- The result is that the element names in a JIC File are always related to the domain of the application being configured.
- Because the element names are not fixed, an exact DTD/schema of the JIC Language can not be defined.
- Every element in a JIC File must belong to the namespace
http://www.jicengine.org/jic/2.1. -
JIC Language specifies a fixed set of JIC attributes. The attributes define the behaviour and semantics of an element. The attributes are:
-
action -
args -
class -
if -
instance -
overridable-by -
type -
vars
-
- Actual values such as strings, numbers and booleans are always placed on the CDATA sections of the elements.
- Attributes are used for describing Java-specific things: constructor and method calls, classes, etc.
- Mixed content (elements inside a CDATA section) are not allowed.
- Elements may contain additional attributes, if the attributes belong to a namespace of their own. They can be used for example to store meta-data that makes it easier to manipulate the files with XML tools. The JIC Engine ignores these extra attributes when processing a JIC file.
The syntax adheres to good XML design principles. Elements define the structure of the data, CDATA is used for specifying the data and the attributes are used for meta-data. The format is very verbose - if descriptive element names are used, every string and number has a name that tells something about the meaning of the value. The names of the XML element are always related to the context of the objects being initialized.
The file contains a single JIC Element <message> that defines the String "Hello World!":
<message xmlns="http://www.jicengine.org/jic/2.1">Hello World!</message>
In Java code the same thing would be expressed as:
String message = "Hello World!"; return message;
Here is a more complex JIC File. The JIC Element <calendar> initializes an instance of java.util.GregorianCalendar and uses several other JIC Elements in the process.
<calendar xmlns="http://www.jicengine.org/jic/2.1" class="java.util.GregorianCalendar" args="year,month,day">
<year>2004</year>
<month>9</month>
<day>9</day>
<lenient>true</lenient>
<timeZone class="java.util.TimeZone">GMT</timeZone>
</calendar>
In Java the same initialization would be expressed as:
int year = 2004;
int month = 9;
int day = 9;
java.util.GregorianCalendar calendar = new java.util.GregorianCalendar(year,month,day);
calendar.setLenient(true);
calendar.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
return calendar;
4. JIC Elements
4.1. What Are JIC Elements?
JIC Elements are the basic building blocks in JIC Language. JIC Element is an executable unit that performs individual initialization tasks. A JIC Element is capable of:
- initializing a Java object (called element instance)
- calling an initialization method (called action)
- doing both of the above
In the XML file the JIC Elements appear as XML elements - every XML element in a JIC File is a JIC Element.
JIC Elements take advantage of other JIC Elements in performing complex tasks. For example, the initialization of a Java object may be a complex process - the constructor arguments must also be initialized and after construction there may be some initialization methods that must be called. In such cases the initialization is divided into simpler subprocesses that are delegated to other JIC Elements. Complex tasks are therefore executed with the help of many JIC Elements.
The cooperation/delegation relationships of JIC Elements appear as parent-child relationships of the XML elements. A JIC Element uses its child elements in achieving a complex task, and the task of an element is part of a larger task executed by the parent of the element. JIC Elements use their child elements and serve their parent elements.
4.2. Name of a JIC Element
Every JIC Element has a name that is defined by the name of the XML element:
- The name resembles a variable name
- The author of the file may choose the name in the same way a programmer may choose the name of a variable.
- Descriptive names should be used. The guidelines for choosing variable names can be applied.
- (In most cases) the name is used by the parent JIC Element for referring to the element instance of the element (more about this later).
- (In most cases) the name must be a valid Java variable name (
variableNameinstead ofvariable-nameorvariable.name)
Note that the name is used only for identifying the element, it does not define the behaviour of the element (attributes are used for this).
4.3. Element Instance
The object initialized by a JIC Element is referred to as element instance. The attribute instance is used for specifying the instance. The value of the attribute is a simple Java expression - for example a constructor or a method call - that, when executed, will return the object.
This Java expression is referred to as the constructor of a JIC Element. When a Java object is initialized, the object acquisition step is performed by executing the constructor.
The instance attribute provides a flexible way for defining how the element instance is obtained. The kind of Java expressions supported are listed on the table below.
| expression type | examples |
|---|---|
| constructor invocation |
new java.util.Date()
|
| method call |
out.println()
|
| value of a variable |
out
|
| value of a static field |
java.lang.System.out
|
(The expression may contain variables that are available in the current context. The contex and the variables are explained more thoroughly later. Most often the variables refer to element instances of the child elements, so there is a child element whose name matches the variable.)
The class of the element instance must always* be defined. This is done with the attribute class that holds a full class name. The class-information is useful in situations where the class of the instance can not be directly seen from the instance attribute. The element instance of the element may also be derived from the class attribute, if the instance attribute is not specified.
*) the class attribute may be omitted in simple elements that contain CDATA. In such cases the class is either String or a primitive such as int, double or boolean.
<calendar class="java.util.Calendar" instance="java.util.Calendar.getInstance()"/>
<string class="java.lang.String" instance="cdata">This is a String</string>
<number class="int" instance="java.lang.Integer.parseInt(cdata)">123</number>
<locale class="java.util.Locale" instance="new java.util.Locale(language,country)">
<language class="java.lang.String" instance="cdata">fi</language>
<country class="java.lang.String" instance="cdata">FI</country>
</locale>
The JIC fragment above resembles the following Java code:
java.util.Date date = new java.util.Date();
java.util.Calendar calendar = java.util.Calendar.getInstance();
String string_ = "This is a String";
int number = java.lang.Integer.parseInt("123");
String language = "fi";
String country = "FI";
java.util.Locale locale = new java.util.Locale(language,country);
JIC Language defines many shortcuts that make it easier to define common types of element instances. Therefore the attribute instance can be omitted in many cases. The examples above can also be written in the following form:
<calendar class="java.util.Calendar" instance="java.util.Calendar.getInstance()"/>
<string>This is a String</string>
<number>123</number>
<locale class="java.util.Locale">fi_FI</locale>
Element instances and the related attributes are described in more detail in chapter How To Define Element Instances?.
4.4. Action
A JIC Element may also have an action. Action is a Java operation similar to the constructorr that defines the element instance. The action is also executed when the element is processed. However, the return value of action is discarded.
Action is used for calling an initialization method which have side-effects and which do not usually return anything. Actions are therefore utilized in the state refinement. However, actions do not usually call a method of their own element instance. Instead, they often modify the state of the element instance of their parent elements. After the parent element has obtained its element instance, it delivers the instance to child elements, which may modify the state of the instance.
Action is set with the attribute action and it may hold similar simple Java expressions as the instance attribute (see JIC Expressions). The action attribute can be used together with the instance attribute.
Below is a JIC File where both <entry> elements execute an action that adds an entry to the java.util.HashMap instance.
The variable parent refers to the Map instance created by the parent element <map>.
<map xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap">
<entry action="parent.put(key,value)">
<key>key1</key>
<value>value1</value>
</entry>
<entry action="parent.put(key,value)">
<key>key2</key>
<value>value2</value>
</entry>
</map>
In Java the same Map would be constructed as:
java.util.HashMap map = new java.util.HashMap();
map.put("key1","value1");
map.put("key2","value2");
return map;
The element <lenient> sets the property lenient of the java.util.Calendar instance. The element instance of <lenient> becomes the value of the property.
<calendar xmlns="http://www.jicengine.org/jic/2.1" class="java.util.Calendar" instance="java.util.Calendar.getInstance()">
<lenient action="parent.setLenient(this)" class="boolean" instance="java.lang.Boolean.valueOf(cdata)">true</lenient>
</calendar>
In most cases the action is a Java expression that starts with "parent.". Therefore a shortcut is provided. The Map example above can also be written in the form:
put(key,value) means parent.put(key,value).
<map xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap">
<entry action="put(key,value)">
<key>key1</key>
<value>value1</value>
</entry>
<entry action="put(key,value)">
<key>key2</key>
<value>value2</value>
</entry>
</map>
NOTE: Be aware that the JIC Language and Java differ in the way they interpret a plain method call such as put(key,value):
- In Java it means:
this.put(key,value) - In JIC Language it means:
parent.put(key,value)
The action can also be used for calling static methods.
<system-property> sets a system property by calling java.lang.System.setProperty
<system-property xmlns="http://www.jicengine.org/jic/2.1" action="java.lang.System.setProperty(name,value)">
<name>example.property</name>
<value>This is just an example</value>
</system-property>
4.5. Variable Elements And Action Elements
Element instance and action are optional - a JIC Element must have either one, or both. The action has a crucial effect on the role of a JIC Element. The purpose of elements with action is to execute the action. Elements that only define an element instance however form a variable that is used by their parent elements.
Elements with action are called action elements and elements without action are called variable elements. The situation is summarized in the following table.
| Element role | Has action | Has element instance |
|---|---|---|
| -ILLEGAL- | - | - |
| variable element | - | + |
| action element | + | - |
| action element | + | + |
Variable elements and action elements differ in the way that they cooperate with their parent elements:
- A variable element:
- Forms a variable:
- the name is the name of the JIC Element
- the value is the element instance.
- The parent element must use the variable for something. For example:
- the variable is used in creating the element instance.
- the variable is used in the action.
- the variable is used to define an element variable inside the parent element.
- The element name must be a valid Java variable name so that it can be used in Java expressions.
- Forms a variable:
- An action element:
- Executes an operation.
- Typically used for:
- Calling of a method of the element instance of the parent, e.g. setting the value of a property.
- Calling a static method.
- The element name has no importance.
- The element instance of an action element can not be referenced outside the element.
4.6. Variables And Contexts
4.6.1. What Are Variables And Contexts?
Variables are objects that can be referenced by name. They are used in the Java operations of attributes instance and action.
Most variables are defined by the variable elements. In addition, the JIC Language defines a few built-in variables such as this, cdata and parent, for example.
A context is a namespace that holds a set of variables. The context defines a scope where the variable can be used. A variable must always be bound to a single context. However, because the contexts are nested, a variable may be available in many contexts regardless of this.
Every JIC Element has 3 different contexts:
-
element context: for variables that are available everywhere inside the element:
- [the element context of the parent element]
- + those child variable elements that are marked as element variables with the attribute
vars.
-
instance context: for variables that are available in the
instanceattribute:- [the element context of the element]
- + those child variable elements that are used in the
instanceattribute. - + built-in variable
cdata - + built-in variable
parent
-
action context: for variables that are used in the action:
- [the element context of the element]
- + those child variable elements that are used in the
actionattribute. - + built-in variable
this - + built-in variable
parent
There is also a special root context. The root element of the JIC File has no parent element, but the root context can be thought of as "the element context of the parent of the root element".
The use of variables in the instance and action attribute is pretty straight-forward. A variable in the Java expression refers most often to a child element, as already shown in many examples.
Element variables and the use of attribute vars is presented in chapter How to Use Element Variables?.
4.6.2. How to Resolve the Context of a Variable?
The context of the built-in variables is predetermined. The context of variables that are defined by variable elements is always chosen by the parent element. The method is simple: the parent simply checks whether the variable is used in the attribute instance, action or vars.
The element <print-message> contains 2 variable elements:
- The variable
datedefined by<date>is put to instance context - The variable
outdefined by<out>is put to actioncontext
<print-message xmlns="http://www.jicengine.org/jic/2.1" action="out.println(this)" class="java.lang.String" instance="date.toString()">
<date class="java.util.Date" instance="new java.util.Date()"/>
<out class="java.io.PrintStream" instance="java.lang.System.out"/>
</print-message>
4.6.3. Built-in Variables
JIC Language specifies the names of a few built-in variables:
| Name | Refers to | Context |
|---|---|---|
parent
|
the element instance of the parent element.
Available if:
|
instance context and action context |
this
|
the element instance of the element itself, if the element has one. | action context |
cdata
|
the String-value of the CDATA section of the element, if the element has one. | instance context |
buildContext
|
An instance of org.jicengine.BuildContext. Always available. |
root context |
*) the JIC Elements are processed in the order that they appear in the JIC File. The Java operation yielding the element instance is executed as soon as all the necessary variable elements have been processed, but not before. Therefore the variable parent is available only in child elements that appear after the variable elements used in the instance attribute.
4.6.4. Loose Variable Elements
If the parent can not determine a context for a variable, the variable element that defined it becomes a loose variable element. They are a kind of wildcards that are used for various purposes. By default, a loose variable element is used for setting a bean property: the name of the element defines the property name, and the element instance is the value of the property.
the <lenient> is a loose variable element. The parent <calendar> uses it for setting the property lenient of the java.util.Calendar instance.
<calendar xmlns="http://www.jicengine.org/jic/2.1" class="java.util.Calendar" instance="java.util.Calendar.getInstance()">
<lenient class="boolean" instance="java.lang.Boolean.valueOf(cdata)">true</lenient>
</calendar>
The same effect would be achieved if the <lenient> would have the attribute action="parent.setLenient(this)".
The way the parent element handles loose variable elements depends on the type of the element. Different JIC Element types have varying policies for loose variable elements. JIC Element types are presented in the section JIC Element Types.
4.7. How JIC Elements Are Executed?
After the JIC Engine has parsed a JIC File, it starts executing the JIC elements. There is only a single root element, which is executed first.
The execution propagates to child elements - the child elements are executed as part of the execution of the parent.
The elements are always executed in the same order that they appear in the JIC file. If one wants to follow the execution by looking at the XML code, each element can be thought to be fully executed after its end tag.
The execution has the following steps:
| Step | Description | Initialization phase |
|---|---|---|
| 1 |
Child elements are executed one by one, until all variable elements needed in obtaining the element instance have been encountered. After a variable element has been executed, the respective variable is made available in the appropriate context. |
collateral initialization |
| 2 |
The element instance is obtained by executing the Java operation set with |
object acquisition |
| 3 |
Rest of the child elements are executed, again one by one. |
state refinement |
| 4 |
The action of the element is executed. |
state refinement of the parent |
NOTE: the execution of a JIC Element may be altered if:
- the
ifattribute is set. (see How to Use the if Atribute for Controlling the Execution of a JIC Element) - the JIC Element type of an element is
switch. (see How to Use the switch Type for Choosing the Element Instance Dynamically. - the JIC Element type of an element is
factory. (see User-defined Factories. - the element is overridden. (see Build Parameters and Overridings.
4.8. Order of Child Elements
Because the order of the elements has significance, it is recommended that the child elements would always be put in a following order:
- variable elements that are declared as element variables
-
variable elements used in the
instanceattribute - action elements and loose variable elements
-
variable elements used in the
actionattribute
JIC Language does not force this order but the scheme would prohibit most stupid errors like calling an initialization method before the object has been created, etc.
4.9. Summary
A JIC Element is an executable unit capable of initializing a Java object or executing a Java operation. The initialized object is referred to as element instance and the Java operation action. These two capabilities make it possible to initialize all kinds of Java objects.
JIC Elements accomplish complex initialization tasks by working together. Contexts are used for passing necessary object references from element to another.
5. How To Define Element Instances?
This section shows in more detail how the element instance of an element can be defined.
5.1. Primitives
Internally JICE handles every primitive as a corresponding wrapper object - int is handled as an instance of java.lang.Integer, etc. The wrapper objects are converted to primitives when needed i.e. when they are used in method calls.
Therefore there is no real difference between primitives and the corresponding wrapper objects. You may use either the primitive type or the wrapper object class in the class attribute.
5.2. Using CDATA to Define Strings
Elements may access their CDATA via the variable cdata that contains the String-value of the CDATA section. The CDATA section makes it possible to define a new String, which may then be converted to other kinds of Java objects.
Few examples that access CDATA and convert it to other kind of Java objects.
<number class="java.lang.Integer" instance="java.lang.Integer.valueOf(cdata)">12345</number>
<number2 class="double" instance="java.lang.Double.valueOf(cdata)">123.45</number2>
<boolean class="boolean" instance="java.lang.Boolean.valueOf(cdata)">true</boolean>
<url class="java.net.URL" instance="new java.net.URL(cdata)">http://www.sourceforge.net</url>
5.3. CDATA Conversions
Although Strings are common in configuration files, also many other kind of value objets are needed, such as numbers (int, double, etc.), booleans, urls, locales, colors, fonts, etc.
There are two kinds of CDATA conversions:
- Class-based CDATA conversions
- The
classattribute defines what kind of object is created from the CDATA. - Syntax-based CDATA conversions*
- The value of the CDATA itself is used to resolve how the CDATA should be converted.
*) Syntax-based CDATA conversions are available only in JICE 2.1 and later.
In both cases, the instance attribute is omitted, which reduces the amount of XML code. With syntax-based CDATA conversions, also the class attribute is omitted.
CDATA Conversions make the use of CDATA more efficient. The String-value of the CDATA section is automatically converted to certain kinds of objects. The type of object to be instantiated is determined by the class attribute and the instance attribute may be omitted.
The previous example can be written without the instance attribute:
<number class="java.lang.Integer">12345</number>
<number2 class="double">123.45</number2>
<boolean class="boolean">true</boolean>
<url class="java.net.URL">http://www.sourceforge.net</url>
The same in Java:
String string1 = "This is a String"; Integer number = new Integer(12345); double number2 = 123.45; boolean boolean_ = true;
Certain types (String, int, double and boolean) may be created also without the class attribute. The example above could be written as:
<number>12345</number>
<number2>123.45</number2>
<boolean>true</boolean>
<url class="java.net.URL">http://www.sourceforge.net</url>
CDATA conversions provide a convenient way to create data-objects that have an unambiguous String-form.
5.3.1. List of Available Class-based CDATA Conversions
All currently available conversions are listed in the following table.
| Class | Corresponding instance attribute |
Accepted CDATA |
|---|---|---|
boolean
|
java.lang.Boolean.valueOf(cdata)
|
boolean values |
double
|
java.lang.Double.valueOf(cdata)
|
double values |
float
|
java.lang.Float.valueOf(cdata)
|
float values |
int
|
java.lang.Integer.valueOf(cdata)
|
integer values |
long
|
java.lang.Long.valueOf(cdata)
|
long values |
short
|
java.lang.Short.valueOf(cdata)
|
short values |
java.lang.Boolean
|
java.lang.Boolean.valueOf(cdata)
|
boolean values |
java.lang.Double
|
java.lang.Double.valueOf(cdata)
|
double values |
java.lang.Float
|
java.lang.Float.valueOf(cdata)
|
float values |
java.lang.Integer
|
java.lang.Integer.valueOf(cdata)
|
integer values |
java.lang.Long
|
java.lang.Long.valueOf(cdata)
|
long values |
java.lang.Short
|
java.lang.Short.valueOf(cdata)
|
short values |
java.lang.String
|
cdata
|
any value |
java.lang.Class
|
[internal to JICE] |
Full class name such as:
|
java.awt.Color
|
[internal to JICE] |
Color values in both hexadecimal and integer formats: for example 00FF99 or 0,255,127
The alpha channel can also be specified: 00FF9966 or 0,255,127,90.
|
java.awt.Dimension
|
[internal to JICE] |
Dimension in format width x height
for example 200x100, 50 x 100, etc.
|
java.awt.Font
|
java.awt.Font.decode
|
Font values, e.g. Arial-10
|
java.awt.Point
|
[internal to JICE] |
A point in format (x,y)
for example (0,0), (100,50), etc.
|
java.math.BigDecimal
|
new java.math.BigDecimal(cdata)
|
A decimal value. |
java.math.BigInteger
|
new java.math.BigInteger(cdata)
|
An integer value. |
java.net.URL
|
new java.net.URL(cdata)
|
An url. |
java.util.Locale
|
[internal to JICE] |
A locale code in format language_country
for example en_US, fi_FI, etc.
|
java.util.TimeZone
|
java.util.TimeZone.getTimeZone(cdata)
|
An id of a timezone. |
org.jicengine.io.Resource
|
[internal to JICE] |
Accepts a file path that is relative to the current JIC file. The format is specified by |
5.3.2. Class-based CDATA Conversion Examples
<color class="java.awt.Color">255,255,255</color>
java.awt.Color color = new java.awt.Color(255,255,255);
java.awt.Dimension dimension = new java.awt.Dimension(150,50);
java.awt.Font font = java.awt.Font.decode("Arial-10");
java.awt.Point point = new java.awt.Point(0,0);
java.net.URL url = new java.net.URL("http://www.google.com");
java.util.Locale locale = new java.util.Locale("en","US");
java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone("GMT");
5.3.3. Syntax-based CDATA Conversions
If the class attribute is omitted, the syntax of the CDATA is examined to find out how it should be processed:
| Syntax | Resulting object | Examples |
|---|---|---|
| an integer value (only digits, optionally starting with the minus sign) |
int, as parsed by the java.lang.Integer.valueOf
|
<value1>123</value1>
<value2>0</value2> <value3>-12356</value3> |
| a decimal value (only digits with the integer and decimal part, optionally starting with the minus sign) |
double, as parsed by the java.lang.Double.valueOf
|
<value1>12.3</value1>
<value2>0.0</value2> <value3>-123.56789</value3> |
boolean i.e. true or false
|
boolean, as parsed by the java.lang.Boolean.valueOf
|
<value1>true</value1>
<value2>false</value2> |
| any other kind of value |
java.lang.String
|
<string1>this is a String</string1>
<string2>12.4.2006</string2> <string3>properties.property</string3> |
If you want to create a String "-1234", "true", etc., specify the attribute class="String". This disables the syntax-based CDATA conversion.
(NOTE: JICE 2.0.x did not support syntax-based CDATA conversions. if the class was omitted, the result was always a String.)
5.4. How to Invoke Constructors?
An object is instantiated by using the new operator to invoke the constructor. The constructor invocation can be defined in the instance attribute.
However, because object instantiation is a very common way to define the element instace, a shortcut is provided. The value of the instance attribute can be derived from the class attribute and the instance attribute can be left out. This saves the author from e.g. writing the class name twice.
In case the invoked constructor requires parameters, the necessary constructor arguments are defined with the attribute args that holds a list of arguments.
The instance attribute can be omitted.
<map class="java.util.HashMap"/>
The JIC fragment above is equal to this:
<map class="java.util.HashMap" instance="new java.util.HashMap()"/>
The args attribute specifies the constructor arguments:
<initialSize>20</initialSize>
</map>
<dateFormat class="java.text.SimpleDateFormat" args="pattern,locale">
<pattern>yyyy-MM-dd</pattern>
<locale class="java.util.Locale">fi_FI</locale>
</dateFormat>
The JIC fragment above is equal to this:
<initialSize class="int">20</initialSize>
</map>
<dateFormat class="java.text.SimpleDateFormat" instance="new java.text.SimpleDateFormat(pattern,locale)">
<pattern>yyyy-MM-dd</pattern>
<locale class="java.util.Locale">fi_FI</locale>
</dateFormat>
5.5. How to Obtain the Return-value of a Method Call?
The element instance may also be obtained via method call. For example, the object is retrieved from a static factory, which means that the static factory must be called. There are also many situations when an instance method needs to be called in order to obtain the object.
The attribute instance is used for defining the method call. There are no shortcuts provided. Below are a few examples.
Note that the attribute args is used only for defining the arguments of a constructor call. Arguments to a method call are defined inside the instance attribute.
An instance of java.util.Calendar is obtained with the method java.util.Calendar.getInstance(TimeZone timeZone)
<calendar xmlns="http://www.jicengine.org/jic/2.1" class="java.util.Calendar" instance="java.util.Calendar.getInstance(timeZone)">
<timeZone class="java.util.TimeZone">Europe/Helsinki</timeZone>
</calendar>
The same in Java:
String id = "Europe/Helsinki"; java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone(id); java.util.Calendar calendar = java.util.Calendar.getInstance(timeZone); return calendar;
The element instance of the <formattedDate> is the result of formatting the java.util.Date instance with the java.text.DateFormat.
<formattedDate xmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String" instance="dateFormat.format(date)">
<dateFormat class="java.text.DateFormat" instance="java.text.DateFormat.getInstance()"/>
<date class="java.util.Date"/>
</formattedDate>
The same in Java:
java.text.DateFormat dateFormat = java.text.DateFormat.getInstance(); java.util.Date date = new java.util.Date(); String formattedDate = dateFormat.format(date); return formattedDate;
5.6. How to Obtain the Value of a Static Field?
The attribute instance may also be used for retrieving the value of a static field:
<out xmlns="http://www.jicengine.org/jic/2.1" class="java.io.PrintStream" instance="java.lang.System.out"/>
java.io.PrintStream out = java.lang.System.out;
<position xmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String" instance="java.awt.BorderLayout.NORTH"/>
String position = java.awt.BorderLayout.NORTH;
5.7. How to Obtain the Value of a Variable?
The element instance of an element may also simply be the value of a variable.
<innerMessage>This is the message</innerMessage>
</message>
String innerMessage = "This is the message"; String message = innerMessage;
5.8. How to Create Arrays?
The instance attribute can also be used for creating arrays. However, the JIC Element type 'array' provides a much more efficient way to both create and populate arrays. See Type array.
<array xmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String[]" instance="new java.lang.String[size]">
<size class="int">0</size>
</array>
6. How to Use Element Variables?
As mentioned earlier, every JIC Element has 3 contexts that each hold a set of variables:
- instance context
- action context
- element context
The instance context and action context are very restricted - they are accessed only from the instance and action attributes, respectively.
Variables in the element context however have a wider scope: they can be accessed everywhere inside the JIC Element. This includes:
- The
actionandinstanceattributes of the element. - The
actionandinstanceattribute of every element inside the element.
The variables in the element context are called element variables. They can be thought of as a sort of global variables inside the element which can be used by many child elements.
The attribute vars is used to declare the element variables of an element. The attribute holds a comma-separated list of variables that identifies which child variable elements define the element variables.
The <birthdays> initializes a java.util.Map that contains mappings from a persons name (as String) to their birthdays (as java.util.Date)
The <parseFormat> defines a java.text.DateFormat that is used for parsing String-values into java.util.Date-objects.
The <date> elements may use the variable parseFormat because it is defined as an element variable in <birthdays>.
<birthdays xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap" vars="parseFormat">
<parseFormat class="java.text.SimpleDateFormat" args="cdata">yyyy-MM-dd</parseFormat>
<birthday action="put(person,date)">
<person>Britney Spears</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1981-12-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Christina Aguilera</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1980-12-18</date>
</birthday>
<birthday action="put(person,date)">
<person>Shakira</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1977-02-02</date>
</birthday>
</birthdays>
In Java the same kind of Map would be constructed as:
java.text.SimpleDateFormat parseFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");
java.util.HashMap birthdays = new java.util.HashMap();
birthdays.put("Britney Spears", parseFormat.parse("1981-12-02"));
birthdays.put("Christina Aguilera", parseFormat.parse("1980-12-18"));
birthdays.put("Shakira", parseFormat.parse("1977-02-02"));
return birthdays;
Local variables always override element variables.
The birthday of Justin Timberlake is parsed with a different java.text.DateFormat object. The local variable parseFormat overrides the element variable with the same name.
<birthdays xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap" vars="parseFormat">
<parseFormat class="java.text.SimpleDateFormat" args="cdata">yyyy-MM-dd</parseFormat>
<birthday action="put(person,date)">
<person>Britney Spears</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1981-12-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Christina Aguilera</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1980-12-18</date>
</birthday>
<birthday action="put(person,date)">
<person>Shakira</person>
<date class="java.util.Date" instance="parseFormat.parse(cdata)">1977-02-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Justin Timberlake</person>
<date class="java.util.Date" instance="parseFormat.parse(dateString)">
<dateString>31.01.1981</dateString>
<parseFormat class="java.text.SimpleDateFormat" args="cdata">dd.MM.yyyy</parseFormat>
</date>
</birthday>
</birthdays>
In Java the same kind of Map would be constructed as:
java.text.SimpleDateFormat parseFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");
java.util.HashMap birthdays = new java.util.HashMap();
birthdays.put("Britney Spears", parseFormat.parse("1981-12-02"));
birthdays.put("Christina Aguilera", parseFormat.parse("1980-12-18"));
birthdays.put("Shakira", parseFormat.parse("1977-02-02"));
java.text.SimpleDateFormat parseFormat2 = new java.text.SimpleDateFormat("dd.MM.yyyy");
birthdays.put("Justin Timberlake", parseFormat2.parse("31.01.1981"));
return birthdays;
7. JIC Element Types
7.1. What Are JIC Element Types?
The type of a JIC Element is used to fine-tune the behaviour of the element. In most cases the type makes it easier to initialize a certain kind of object.
JIC Language defines 10 different JIC element types:
| Type | Purpose |
|---|---|
bean
|
The default type. Makes it easier to set bean properties. |
array
|
Makes it easier to create and populate an array. |
collection
|
Makes it easier to create and populate a java.util.Collection instance. |
list
|
Makes it easier to create and populate a java.util.List instance. |
map
|
Makes it easier to create and populate a java.util.Map instance. |
container
|
Makes it easier to define element variables. Used often as the type of the root element. |
constant-of
|
Alternative way to access constants (i.e. static fields) |
switch/1
|
A switch structure that makes it possible to select the element instance of an element dynamically from a set of alternatives. |
factory/x
|
Used for defining a factory, kind of a function that is defined and used in JIC Files. |
cdata-converter/1
|
Used for defining a custom CDATA conversion in a JIC File. |
(Note: JIC Element types are not to be confused with the categories action elements and variable elements. A JIC Element is either an action element or a variable element depending on whether it has an action or not. The JIC Element type is defined by the attribute type.)
The advantage of JIC Element types comes from the way they treat loose variable elements: each type has a different policy that gives the loose variable elements a meaningful purpose.
In most cases the loose variable elements are used for modifying the element instance of the element. The same would be achieved by defining the action attribute of the child elements, but the JIC Element types make it possible to leave the action attribute out. Therefore they reduce the amount of code needed to specify certain things.
The types switch/1 and factory/x are special because they provide functionality that can not be implemented with basic language features.
7.2. JIC Element Types and Loose Variable Elements
The following table lists the policies that different JIC Element types use for loose variable elements.
| Type | Policy | Advantage |
|---|---|---|
bean
|
Uses a loose variable element for setting a bean property with the same name. | The attribute action="parent.setXXX(this)" can be omitted from the child elements that set properties. |
array
|
Creates an array and puts every loose variable element into the array. | Populating an array becomes very easy. |
collection
|
Adds the element instance of every loose variable element into the collection. | The attribute action="parent.add(this)" can be omitted from the child elements that define list elements. |
list
|
Adds the element instance of every loose variable element into the list. | The attribute action="parent.add(this)" can be omitted from the child elements that define list elements. |
map
|
Puts the element instance of every loose variable element into the Map. The name of the element is used as the key. |
The attribute action="parent.put(name,value)" can be omitted from the child elements that define map entries. |
container
|
Creates an element variable from each loose variable element. | No need to list every element variable in the vars attribute if there are many variables. |
constant-of
|
Child elements not allowed, only CDATA. | Alternative way to access constants (i.e. static fields) |
switch/1
|
Uses loose variable elements as cases. One case is selected by a criteria when the element is executed. | Makes it possible to define the element instance of an element dynamically. |
factory/x
|
May contain a single loose variable element that defines what the factory returns. | Makes it possible to define a factory (a kind of a function) in a JIC File. |
cdata-converter/1
|
May contain one loose variable element that defines the result of the CDATA conversion. | Makes it possible to define a custom CDATA conversion in a JIC File. |
The type of a JIC Element is set with the attribute type, which holds the name of the type. Default value of the attribute is bean.
The following sections show how the JIC Element types are used.
7.3. Type bean (the default)
The bean type makes it easier to set bean-like properties i.e. call setXXX()-methods. This is all it does - it does not by any means require that the initialized object is a pure bean or prohibit the invocation of other kinds of methods.
<window> defines an instance of javax.swing.JFrame that contains a single JLabel.
Various elements have an action attribute that sets a property.
<window xmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" args="title">
<title>This is a JFrame</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>This is a JLabel</text>
<horizontalAlignment action="setHorizontalAlignment(this)" class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font action="setFont(this)" class="java.awt.Font">Arial-bold-16</font>
</label>
<opaque action="setOpaque(this)">true</opaque>
<background action="setBackground(this)" class="java.awt.Color">200,90,90</background>
</contentPane>
<size action="setSize(this)" class="java.awt.Dimension">200x200</size>
<location action="setLocation(this)" class="java.awt.Point">(300,100)</location>
<defaultCloseOperation action="setDefaultCloseOperation(this)" class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<visible action="setVisible(this)">true</visible>
</window>
(Note: <contentPane> has an empty action attribute because no action needs to be executed, but we don't want the parent <window> to handle the <contentPane> as a variable element either.)
The same <window> can be constructed also without many action attributes that were present in the previous example.
All the same properties are still set because of the way the bean type handles loose variable elements.
Because bean is the default type, we don't have to use the type attribute.
<window xmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" args="title">
<title>This is a JFrame</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>This is a JLabel</text>
<horizontalAlignment class="int" type="constant-of(javax.swing.SwingConstants)">CENTER</horizontalAlignment>
<font class="java.awt.Font">Arial-bold-16</font>
</label>
<opaque>true</opaque>
<background class="java.awt.Color">99ccff</background>
</contentPane>
<size class="java.awt.Dimension">200x200</size>
<location class="java.awt.Point">(300,100)</location>
<defaultCloseOperation class="int" type="constant-of(javax.swing.JFrame)">DISPOSE_ON_CLOSE</defaultCloseOperation>
<visible>true</visible>
</window>
7.4. Type array
Arrays would be very tedious to initialize without the type array. Every array element would have to be added with the method java.lang.reflect.Array.set(Object array, int index, Object value).
Fortunately, the type array makes it quite straightforward to define an array.
<array> initializes an array of String-objects. Every child element of <array> is a loose variable element that are made into array elements. The names of the elements have no significance.
The array type creates automatically an array of correct size. The instance attribute needs not to be defined.
<array xmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String[]" type="array">
<e>Element 1</e>
<e>Element 2</e>
<e>Element 3</e>
<e class="String">4.45</e>
</array>
Primitive arrays are created with the same procedure.
<array xmlns="http://www.jicengine.org/jic/2.1" class="int[]" type="array">
<one class="int">1</one>
<two class="int">2</two>
<three class="int">3</three>
<four class="int">4</four>
</array>
7.5. Type collection
collection type makes it easier to populate a collection.
Every collection - list, set, etc. - may be defined also without the collection type, but it requires that every element must have an action that adds the element to the collection.
With collection type, the action attributs of the child elements may be omitted. Every loose child variable is added to the collection. The examples below demonstrates this.
Every child element has the same kind of action attribute.
(int-values can be added to the set because they are automatically converted to java.lang.Integers)
<set xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashSet">
<e action="add(this)" class="int">1</e>
<e action="add(this)" class="int">2</e>
<e action="add(this)" class="int">3</e>
<e action="add(this)" class="int">4</e>
</set>
<collection xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashSet" type="collection">
<e class="int">1</e>
<e class="int">2</e>
<e class="int">3</e>
<e class="int">4</e>
</collection>
(type collection is available in JICE 2.0.2 and later releases.)
7.6. Type list
The list type behaves like the more general collection, except that the element instance must implement the java.util.List interface.
<list xmlns="http://www.jicengine.org/jic/2.1" class="java.util.ArrayList" type="list">
<e>1</e>
<e class="int">2</e>
<e>-3344</e>
<e class="int">-4</e>
</list>
7.7. Type map
The map type makes it easy to populate a java.util.Map in situations where the keys are Strings and valid XML element names.
map type handles every loose variable element as an entry in the map. The name of the element becomes the key (as a String) and the element instance becomes the value.
The map type is useful in only cases where the keys are appropriate. If other kinds of keys need to be used, the Map can always be created and populated manually.
<map xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap" type="map">
<entry action="put(key,value)">
<key>background.color</key>
<value class="java.awt.Color">0099CC</value>
</entry>
<entry action="put(key,value)">
<key>foreground.color</key>
<value class="java.awt.Color">000000</value>
</entry>
</map>
<map xmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap" type="map">
<background.color class="java.awt.Color">0099CC</background.color>
<foreground.color class="java.awt.Color">000000</foreground.color>
</map>
7.8. Type container
The container type is useful as the type of the root element in large JIC Files. An element variable is created from every loose variable element, and the scope of the variables is the whole document. Therefore every loose variable element directly under the root element becomes sort of a "global object", which can then be referred to by other elements.
The same could be achieved without the container type, but then every element variable would have to be listed in the vars attribute.
The type container is also useful in making the XML tree in a JIC File flatter. A very deep tree is hard to read, but the file may be easier to understand if it is chopped to smaller units. The same phenomena occurs in Java code: it is considered bad if a single Java method contains lots of code. Therefore the code is devided into multiple smaller methods.
T