JIC Language User Guide

Author: Timo Laitinen
Date: 2006-05-28

Contents

4.4.Action
4.9.Summary

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:

  1. Collateral initialization - the initialization of additional objects:
    1. Argument objects - objects that will be used as arguments to a constructor or method call in the object acquisition phase.
    2. Helper objects - objects that are used in the initialization of the object and discarded afterwards.
  2. Object acquisition - obtaining the instance to be initialized:
    1. Instantiating the object with a constructor call.
    2. Invoking a method that yields the object. (call to a factory method, for example)
    3. (Obtaining the value of a static field.)
  3. 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 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:

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:

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.

Example: simple JIC File

The file contains a single JIC Element <message> that defines the String "Hello World!":

<?xml version="1.0" encoding="UTF-8"?>
<messagexmlns="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;
Example: initializing a Calendar

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.

<?xml version="1.0" encoding="UTF-8"?>
<calendarxmlns="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:

  1. initializing a Java object (called element instance)
  2. calling an initialization method (called action)
  3. 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:

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()
new java.util.Locale(language,country)
method call out.println()
dateFormat.format(date)
java.util.TimeZone.getTimeZone(id)
value of a variable out
dateFormat
value of a static field java.lang.System.out
java.awt.BorderLayout.CENTER

(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.

Example: using class and instance attributes
<date class="java.util.Date" instance="new java.util.Date()"/>
<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);
Example: shortcuts

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:

<date class="java.util.Date"/>
<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.

Example: executing actions

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>.

<?xml version="1.0" encoding="UTF-8"?>
<mapxmlns="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;
Example: element with both action and element instance

The element <lenient> sets the property lenient of the java.util.Calendar instance. The element instance of <lenient> becomes the value of the property.

<?xml version="1.0" encoding="UTF-8"?>
<calendarxmlns="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:

Example: shortcut in action

put(key,value) means parent.put(key,value).

<?xml version="1.0" encoding="UTF-8"?>
<mapxmlns="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.

Example: calling a static method

<system-property> sets a system property by calling java.lang.System.setProperty

<?xml version="1.0" encoding="UTF-8"?>
<system-propertyxmlns="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:

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

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.

Example: choosing contexts for variables

The element <print-message> contains 2 variable elements:

  • The variable date defined by <date> is put to instance context
  • The variable out defined by <out> is put to actioncontext
<?xml version="1.0" encoding="UTF-8"?>
<print-messagexmlns="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:
  • The parent element has an element instance.
  • The element instance of the parent has already been obtained when the element is encountered*
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.

Example: loose variable element

the <lenient> is a loose variable element. The parent <calendar> uses it for setting the property lenient of the java.util.Calendar instance.

<?xml version="1.0" encoding="UTF-8"?>
<calendarxmlns="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 instance.

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:

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:

  1. variable elements that are declared as element variables
  2. variable elements used in the instance attribute
  3. action elements and loose variable elements
  4. variable elements used in the action attribute

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.

Example: Converting CDATA manually

Few examples that access CDATA and convert it to other kind of Java objects.

<string1 class="java.lang.String" instance="cdata">This is a String</string1>
<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. JIC Language offers CDATA conversions to make the creation of these value objects easier.

There are two kinds of CDATA conversions:

Class-based CDATA conversions
The class attribute 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.

Example: Class-based CDATA Conversions

The previous example can be written without the instance attribute:

<string1 class="java.lang.String">This is a String</string1>
<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;
Example: Syntax-based CDATA Conversions

Certain types (String, int, double and boolean) may be created also without the class attribute. The example above could be written as:

<string1>This is a String</string1>
<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.net.URL
  • java.lang.String[]
  • java.lang.Double
  • org.jicengine.ExampleClass$InnerClass
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 org.jicengine.io.Resource.getResource(String)

5.3.2.Class-based CDATA Conversion Examples

Example: few CDATA conversions
<color class="java.awt.Color">FFFFFF</color>
<color class="java.awt.Color">255,255,255</color>
java.awt.Color color = new java.awt.Color(255,255,255);

<dimension class="java.awt.Dimension">150x50</dimension>
java.awt.Dimension dimension = new java.awt.Dimension(150,50);

<font class="java.awt.Font">Arial-10</font>
java.awt.Font font = java.awt.Font.decode("Arial-10");

<point class="java.awt.Point">(0,0)</point>
java.awt.Point point = new java.awt.Point(0,0);

<url class="java.net.URL">http://www.google.com</url>
java.net.URL url = new java.net.URL("http://www.google.com");

<locale class="java.util.Locale">en_US</locale>
java.util.Locale locale = new java.util.Locale("en","US");

<timeZone class="java.util.TimeZone">GMT</timeZone>
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.

Example: empty constructor invocations

The instance attribute can be omitted.

<date class="java.util.Date"/>
<map class="java.util.HashMap"/>

The JIC fragment above is equal to this:

<date class="java.util.Date" instance="new java.util.Date()"/>
<map class="java.util.HashMap" instance="new java.util.HashMap()"/>
Example: constructor invocations with arguments

The args attribute specifies the constructor arguments:

<map class="java.util.HashMap" args="initialSize">
<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:

<map class="java.util.HashMap" instance="new java.util.HashMap(initialSize)">
<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.

Example: invoking a static method

An instance of java.util.Calendar is obtained with the method java.util.Calendar.getInstance(TimeZone timeZone)

<?xml version="1.0" encoding="UTF-8"?>
<calendarxmlns="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;
Example: invoking an instance method

The element instance of the <formattedDate> is the result of formatting the java.util.Date instance with the java.text.DateFormat.

<?xml version="1.0" encoding="UTF-8"?>
<formattedDatexmlns="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:

Example: obtaining System.out
<?xml version="1.0" encoding="UTF-8"?>
<outxmlns="http://www.jicengine.org/jic/2.1" class="java.io.PrintStream" instance="java.lang.System.out"/>
java.io.PrintStream out = java.lang.System.out;
Example: obtaining BorderLayout.NORTH
<?xml version="1.0" encoding="UTF-8"?>
<positionxmlns="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.

Example: value of a variable
<message class="java.lang.String" instance="innerMessage">
<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.

Example: Instantiating an empty array
<?xml version="1.0" encoding="UTF-8"?>
<arrayxmlns="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:

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 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.

Example: declaring 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>.

<?xml version="1.0" encoding="UTF-8"?>
<birthdaysxmlns="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.

Example: overriding an element variable

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.

<?xml version="1.0" encoding="UTF-8"?>
<birthdaysxmlns="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.

Example: setting bean properties manually

<window> defines an instance of javax.swing.JFrame that contains a single JLabel.

Various elements have an action attribute that sets a property.

<?xml version="1.0" encoding="UTF-8"?>
<windowxmlns="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.)

Example: taking advantage of the bean type

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.

<?xml version="1.0" encoding="UTF-8"?>
<windowxmlns="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.

Example: String 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.

<?xml version="1.0" encoding="UTF-8"?>
<arrayxmlns="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>
Example: int array

Primitive arrays are created with the same procedure.

<?xml version="1.0" encoding="UTF-8"?>
<arrayxmlns="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.

Example: Initializing a HashSet manually

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)

<?xml version="1.0" encoding="UTF-8"?>
<setxmlns="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>
Example: Initializing a HashSet with collection type
<?xml version="1.0" encoding="UTF-8"?>
<collectionxmlns="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.

Example: Initializing a List with list type
<?xml version="1.0" encoding="UTF-8"?>
<listxmlns="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.

Example: initializing map manually
<?xml version="1.0" encoding="UTF-8"?>
<mapxmlns="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>
Example: using map type
<?xml version="1.0" encoding="UTF-8"?>
<mapxmlns="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.

Example: a deeply nested JIC File

The following file defines a JFrame that dispalys the current time.

<?xml version="1.0" encoding="UTF-8"?>
<windowxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" args="title">
<title>Clock</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">

<north action="add(this,location)" class="javax.swing.JPanel">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>The Current Date Is:</text>
<font class="java.awt.Font">Arial-bold-16</font>
</label>
<location class="java.lang.String" instance="java.awt.BorderLayout.NORTH"/>
</north>

<center action="add(this,location)" class="javax.swing.JPanel">
<layout class="java.awt.FlowLayout" args="align">
<align class="int" instance="java.awt.FlowLayout.CENTER"/>
</layout>

<label action="add(this)" class="javax.swing.JLabel" args="text">
<text class="java.lang.String" instance="dateFormat.format(currentDate)">
<dateFormat class="java.text.SimpleDateFormat" args="pattern">
<pattern>dd.MM.yyyy HH:mm:ss</pattern>
</dateFormat>
<currentDate class="java.util.Date"/>
</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>

<label action="add(this)" class="javax.swing.JLabel" args="text">
<text class="java.lang.String" instance="timeZone.getID()">
<timeZone class="java.util.TimeZone" instance="java.util.TimeZone.getDefault()"/>
</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>

<location class="java.lang.String" instance="java.awt.BorderLayout.CENTER"/>
</center>
</contentPane>
<size class="java.awt.Dimension">200x150</size>
<location class="java.awt.Point">(300,100)</location>
<defaultCloseOperation class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<visible>true</visible>
</window>

The result looks something like this:

The resulting JFrame

Example: using container type and flatterning the file

The file below initializes a similar JFrame than the previous example, but the file is flattened to smaller object definitions.

The <window> automatically declares the element variables dateFormat, currentDate, currentDateLabel, currentTimeZoneLabel, northPanel and centerPanel from the respective loose variable elements.

The same would be achieved if the <window> would contain the attribute vars="dateFormat, currentDate, currentDateLabel, currentTimeZoneLabel, northPanel, centerPanel".

<?xml version="1.0" encoding="UTF-8"?>
<windowContainerxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" type="container" instance="window">

<dateFormat class="java.text.SimpleDateFormat" args="pattern">
<pattern>dd.MM.yyyy HH:mm:ss</pattern>
</dateFormat>

<currentDate class="java.util.Date"/>

<currentDateLabel class="javax.swing.JLabel" args="text">
<text class="java.lang.String" instance="dateFormat.format(currentDate)"/>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</currentDateLabel>

<currentTimeZoneLabel class="javax.swing.JLabel" args="text">
<text class="java.lang.String" instance="timeZone.getID()">
<timeZone class="java.util.TimeZone" instance="java.util.TimeZone.getDefault()"/>
</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</currentTimeZoneLabel>

<northPanel class="javax.swing.JPanel">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>The Current Date Is:</text>
<font class="java.awt.Font">Arial-bold-16</font>
</label>
</northPanel>

<centerPanel class="javax.swing.JPanel">
<layout class="java.awt.FlowLayout" args="align">
<align class="int" instance="java.awt.FlowLayout.CENTER"/>
</layout>
<label action="add(currentDateLabel)"/>
<label action="add(currentTimeZoneLabel)"/>
</centerPanel>

<window class="javax.swing.JFrame" args="title">
<title>Clock</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">
<north action="add(northPanel,location)">
<location class="java.lang.String" instance="java.awt.BorderLayout.NORTH"/>
</north>
<center action="add(centerPanel,location)">
<location class="java.lang.String" instance="java.awt.BorderLayout.CENTER"/>
</center>
</contentPane>
<size class="java.awt.Dimension">200x150</size>
<location class="java.awt.Point">(300,100)</location>
<defaultCloseOperation class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<visible>true</visible>
</window>
</windowContainer>

7.9.Type constant-of

The type constant-of/1 provides an alternative method for accessing constants i.e. static fields.

Example: Using constant-of

The following example demonstrates the two ways for accessing constants.

<?xml version="1.0" encoding="UTF-8"?>
<constantsxmlns="http://www.jicengine.org/jic/2.1" type="container" class="java.lang.String" instance="message">
<message>This demonstrates how to use the 'constant-of' type.</message>
<position1 class="String" instance="java.awt.BorderLayout.CENTER"/>
<position2 class="String" type="constant-of(java.awt.BorderLayout)">CENTER</position2>
<align1 class="int" instance="java.awt.FlowLayout.LEFT"/>
<align2 class="int" type="constant-of(java.awt.FlowLayout)">LEFT</align2>
<action1 class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<action2 class="int" type="constant-of(javax.swing.JFrame)">DISPOSE_ON_CLOSE</action2>
</constants>

The differences are cosmetic. constant-of allows the value - the name of the constant - to be put into the CDATA section. If the value needs to be changed, only the CDATA section needs to be modified. This way the modification of a constant value is done the same way as String, int, boolean, etc. values are modified.

7.10.Type switch

The type switch/1 is defined in section How to Use the switch Type for Choosing the Element Instance Dynamically

7.11.Type factory

The type factory/x is defined in section User-defined Factories

7.12.Type cdata-converter

The type cdata-converter/1 is defined in section User-defined CDATA Conversions

8. How to Use the if Atribute for Controlling the Execution of a JIC Element

8.1.Attribute if

The attribute if is used to control whether a JIC Element is executed or not.

The attribute holds a JIC expression that is evaluated before the element. In case the expression evaluates to false, the element is not executed. The result is the same as removing the element from the JIC File. If the expression evaluates to true or the if attribute is not set, the element is executed normally.

The if attribute is associated only with a single JIC Element. It resembles therefore a single if block in Java. It can not be used for constructing if-else or if-elseif-else like structures. See XXX (switch)

Example: simple if attribute

<container> has an element variable doDebug that is used for determining whether the <print-message> is executed.

The value of doDebug is true, so the message will appear in System.out when the file is processed.

<?xml version="1.0" encoding="UTF-8"?>
<containerxmlns="http://www.jicengine.org/jic/2.1" action="" vars="doDebug">
<doDebug class="boolean">true</doDebug>
<print-message if="doDebug" action="this.println(message)" class="java.io.PrintStream" instance="java.lang.System.out">
<message>JIC File executed</message>
</print-message>
</container>

The example corresponds to Java code:

boolean doDebug = true;
if( doDebug ){
  String message = "JIC File executed";
  System.out.println(message);
}

return;

8.2.Uses for if

The effect of not executing a JIC Element is the same as removing the corresponding XML element (and its contents) from the JIC File.

Therefore the attribute if should only be used in elements that are not required in the execution of other elements. For example, removing an action elements does not usually cause the execution of the parent element to fail. However, removing a variable element may break the parent as one variable is missing.

The table below lists cases where if can be used.

Element Purpose of if
action elements if controls whether the action is executed or not.
loose variable elements

Many loose variable elements are used for executing an operation. E.g. bean type uses every loose variable element for setting a bean property.

In such a case the if is used for the same purpose as in an action element - for controlling whether an operation is executed or not.

other variable elements

A local variable element may override an outer element variable. Using if in such an element controls whether the element variable is overridden or not.

The use of if in other kind of variable elements causes most likely errors.

Note that the expressions inside an unexecuted element are not evaluated. Hence the validity of the expressions is not verified completely. For example the use of non-existing methods or variables is not checked.

Expressions are always parsed, however, so the most trivial syntax errors and illegal class names will be encountered even if an element is not executed.

8.3.Expressions in the if attribute

The if attribute is evaluated before the execution of the element is started. The expression is executed in a context of its own, which consists of:

Note that none of the element instances that are inside the element can be referenced from the if attribute. Even the variable this can not be used.

Otherwise any valid JIC expression may be used in the if attribute. The return value of the expression is interpreted as follows:

Return value Result
a boolean (or a java.lang.Boolean) true or false
null false
other Java objects true

Java APIs contain various methods where the return value null implies some kind of an error. This information may be utilized in the if attribute, because null is interpreted as false.

The ! operator may be used for negating the result. It works also with the "null or non-null" type of tests.

Operators such as =, <, >, && and || are currently NOT supported.

Example: testing for a null value

The following JIC File sets the system property example.property only if it hasn't been previously set.

<?xml version="1.0" encoding="UTF-8"?>
<system-propertyxmlns="http://www.jicengine.org/jic/2.1" action="" type="container">
<propertyName>example.property</propertyName>
<propertyValue>Example value</propertyValue>
<set if="!java.lang.System.getProperty(propertyName)" action="java.lang.System.setProperty(propertyName,propertyValue)"/>
</system-property>

The corresponding Java code is:

String propertyName = "example.property";
String propertyValue = "Example value";

if( System.getProperty(propertyName) != null ){
  System.setProperty(propertyName,propertyValue);
}

return;

9. How to Use the switch Type for Choosing the Element Instance Dynamically

9.1.Type switch/1

The JIC Element type switch makes it possible to select the element instance of an element from a set by some criteria. It resembles the switch structure in Java language.

The switch type handles every loose variable element as a case. When an element of type switch is executed, one of the cases is selected and the element instance of the selected element becomes the element instance of the switch element.

The correct case is selected by comparing the names of the case elements with the switch variable. The element whose name equals with the String value of the variable is selected.

The switch type operates therefore on Strings, whereas in Java the switch structure is based on int values.

Example: localizing button text

The <text> is a switch that has three cases: <fi>, <en> and <sv>. The variable language is the switch variable.

The <language> defines the value of the switch variable. The default value is "en", but the default can be overridden with a build parameter named lang. (For more info on build parameters, see Build Parameters and Overridings)

When <text> is executed, it compares the names of elements <fi>, <en> and <sv> with the value of the variable language. The first match is chosen, and the element instance of the chosen element becomes the element instance of <text>.

<?xml version="1.0" encoding="UTF-8"?>
<buttonxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JButton" args="text" vars="text">
<text class="java.lang.String" type="switch(language)">
<language overridable-by="lang">en</language>
<fi>Paina minua!</fi>
<en>Click me!</en>
<sv>Tryck mig!</sv>
</text>
</button>

If the build parameter lang is not provided, the String "Click me!" becomes the button text. If the parameter is defined but the value does not match with any of the cases, the execution of the <text> will fail.

The example corresponds to Java code:

String text;

String language = "en";
if ( << param "lang" is defined >> ){
  language = << value of param "lang" >>;
}

if (language.equals("fi")){
  text = "Paina minua!";
}
else if (language.equals("en")){
  text = "Click me!";
}
else if (language.equals("sv")){
  text = "Tryck mig!";
}
else {
  throw new Exception("no match");
}

javax.swing.JButton button = new javax.swing.JButton(text);

return button;

The switch type is a genuine switch in the sense that it executes only a single case element - the ones that are not chosen are ignored.

The instance or args attributes can not be used with switch, because the switch already defines how the element instance of the element will obtained.

9.2.How to Define the Default Case?

A case named default specifies a default case that will be chosen if none of the other cases match.

Example: specifying a default case

This example initializes a localized DateFormat object. If the language does not match, the DateFormat defined by <default> will be chosen.

<?xml version="1.0" encoding="UTF-8"?>
<dateFormatxmlns="http://www.jicengine.org/jic/2.1" class="java.text.DateFormat" type="switch(language)">
<language overridable-by="lang">en</language>
<fi class="java.text.SimpleDateFormat" args="pattern">
<pattern>dd.MM.yyyy</pattern>
<timeZone class="java.util.TimeZone">Europe/Helsinki</timeZone>
</fi>
<en class="java.text.SimpleDateFormat" args="pattern">
<pattern>MM/dd/yy</pattern>
<timeZone class="java.util.TimeZone">America/New_York</timeZone>
</en>
<default class="java.text.SimpleDateFormat" args="pattern">
<pattern>yyyy-MM-dd</pattern>
<timeZone class="java.util.TimeZone">GMT</timeZone>
</default>
</dateFormat>

The example corresponds to Java code:

java.text.DateFormat dateFormat;

String language = "en";
if ( << param "lang" is defined >> ){
  language = << value of param "lang" >>;
}

if (language.equals("fi")){
  dateFormat = new java.text.SimpleDateFormat("dd.MM.yyyy");
  dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("Europe/Helsinki"));
}
else if (language.equals("en")){
  dateFormat = new java.text.SimpleDateFormat("MM/dd/yy");
  dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("America/New_York"));
}
else {
  dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");
  dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
}

return dateFormat;

9.3.Limitations

The type switch is very limited in its capabilities as is also the switch structure in Java. The criteria for choosing a case is based on Strings. In addition, the String must be a valid XML element name.

If more complex logic is needed for choosing the element instance of an element, the logic must be put into a Java class or method which is then used from the JIC File.

10. User-defined Factories

10.1.What Are User-defined Factories?

Factories are kind of functions that are defined and used in JIC Files. On JIC Element creates the factory, which may then be called by other JIC Elements.

Factories have parameters and they can return a Java object. Various JIC Elements may call a factory much like they would call a Java method.

The JIC Element type factory is used for defining a new factory. The element that defines a factory is referred to as a factory element. The element has a child element defines what the factory returns.

A factory may be called from the instance attribute with the syntax jic::factory-name(parameters).

Example: defining and calling a simple factory

The factory toUrl receives a String and transforms it into a java.net.URL.

<?xml version="1.0" encoding="UTF-8"?>
<testxmlns="http://www.jicengine.org/jic/2.1" class="java.net.URL" instance="url">

<toUrl type="factory(java.lang.String location)">
<url class="java.net.URL" args="location"/>
</toUrl>

<url class="java.net.URL" instance="jic::toUrl(cdata)">http://www.google.com</url>
</test>

(note: JIC Language already has a cdata conversion for java.net.URLs so the above factory is not really needed.)

10.2.When to Use Factories?

Factories are useful in situations where multiple similar objects need to be initialized with slightly varying properties. If the configuration of a single object requires 10 lines of JIC Language code, defining many such objects increases the size of the JIC File rapidly. A factory can define the common properties in the objects, and the code needed to configure a single object is reduced.

Note that the same could be achieved by creating a new Java method or class. But there are situations when the nature of the common properties does not belong to Java classes.

Example: configuring multiple JLabels

The JIC File below initializes a JFrame that looks something like this:

The resulting JFrame

The configuration of the 7 JLabels makes the file quite long as each label requires 5 lines:

<?xml version="1.0" encoding="UTF-8"?>
<windowxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" args="title">
<title>Tip of the Day</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">

<northPanel action="add(this,location)" class="javax.swing.JPanel">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>JIC Element types:</text>
<font class="java.awt.Font">Arial-bold-16</font>
</label>
<location class="java.lang.String" instance="java.awt.BorderLayout.NORTH"/>
</northPanel>

<centerPanel action="add(this,location)" class="javax.swing.JPanel">
<layout class="java.awt.GridLayout" args="rows,cols">
<rows>7</rows>
<cols>1</cols>
</layout>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>bean</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>array</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>list</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>map</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>container</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>switch</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>factory</text>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</label>
<location class="java.lang.String" instance="java.awt.BorderLayout.CENTER"/>
</centerPanel>

</contentPane>
<size class="java.awt.Dimension">200x250</size>
<location class="java.awt.Point">(300,100)</location>
<defaultCloseOperation class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<visible>true</visible>
</window>

The only thing different in the JLabel objects is the label text. With the help of the factory createLabel(java.lang.String text), the configuration of the labels is greatly simplified.

<?xml version="1.0" encoding="UTF-8"?>
<windowxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JFrame" args="title">
<title>Tip of the Day</title>
<contentPane action="" class="javax.swing.JComponent" instance="parent.getContentPane()">

<northPanel action="add(this,location)" class="javax.swing.JPanel">
<label action="add(this)" class="javax.swing.JLabel" args="text">
<text>JIC Element types:</text>
<font class="java.awt.Font">Arial-bold-16</font>
</label>
<location class="java.lang.String" instance="java.awt.BorderLayout.NORTH"/>
</northPanel>

<centerPanel action="add(this,location)" class="javax.swing.JPanel">
<layout class="java.awt.GridLayout" args="rows,cols">
<rows>7</rows>
<cols>1</cols>
</layout>

<createLabel type="factory(java.lang.String text)">
<result class="javax.swing.JLabel" args="text">
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</result>
</createLabel>

<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">bean</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">array</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">list</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">map</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">container</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">switch</label>
<label action="add(this)" class="javax.swing.JLabel" instance="jic::createLabel(cdata)">factory</label>
<location class="java.lang.String" instance="java.awt.BorderLayout.CENTER"/>
</centerPanel>

</contentPane>
<size class="java.awt.Dimension">200x250</size>
<location class="java.awt.Point">(300,100)</location>
<defaultCloseOperation class="int" instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
<visible>true</visible>
</window>

The factory defines the horizontal alignment and the font of the labels. These properties are typical details that are closer to configuration than application logic. It is therefore feasible to use a factory and define them in a JIC File instead of creating e.g. a subclass of JLabel which is center aligned and has the proper font by default.

10.3.Type factory/x

Here are the characteristics of the factory type:

10.4.How to Use Element Variables within Factories?

In addition to the factory parameters and the element instances defined inside the factory, also outer element variables may used in the factory.

The following example demonstrates this.

Example: creating localized labels

This example defines labels for every weekday. The labels are returned in an array of JLabel instances. The label texts (weekdays) are fetched from a ResourceBundle.

The properties in the ResourceBundle are defined in two files based on the locale:

Locale en_US Locale fi_FI
label.day1 = Monday
label.day2 = Tuesday
label.day3 = Wednesday
label.day4 = Thursday
label.day5 = Friday
label.day6 = Saturday
label.day7 = Sunday
	
label.day1 = Maanantai
label.day2 = Tiistai
label.day3 = Keskiviikko
label.day4 = Torstai
label.day5 = Perjantai
label.day6 = Lauantai
label.day7 = Sunnuntai
	

In the JIC File the element <bundle> obtains a ResourceBundle by locale. The bundle is available as the element variable bundle.

<createLabel> defines a factory that creates JLabel objects. The factory takes a resource bundle key as a parameter. The parameter is used for fetching a localized text for the created JLabel from the ResourceBundle.

<labels> initializes the array that contains the labels.

<?xml version="1.0" encoding="UTF-8"?>
<containerxmlns="http://www.jicengine.org/jic/2.1" class="javax.swing.JLabel[]" instance="labels" vars="bundle">

<bundle class="java.util.ResourceBundle" instance="java.util.ResourceBundle.getBundle(name,locale)">
<name>factory_localized-weekdays</name>
<locale class="java.util.Locale" overridable-by="locale">en_US</locale>
</bundle>

<createLabel type="factory(java.lang.String key)">
<result class="javax.swing.JLabel" args="text">
<text class="java.lang.String" instance="bundle.getString(key)"/>
<horizontalAlignment class="int" instance="javax.swing.SwingConstants.CENTER"/>
<font class="java.awt.Font">Arial-italic-14</font>
</result>
</createLabel>

<labels class="javax.swing.JLabel[]" type="array">
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day1</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day2</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day3</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day4</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day5</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day6</label>
<label class="javax.swing.JLabel" instance="jic::createLabel(cdata)">label.day7</label>
</labels>

</container>

Note that only a single ResourceBundle instance is created. The same instance is used every time the factory is called.

11. User-defined CDATA Conversions

11.1.What Are User-defined CDATA Conversions

New class-based CDATA conversions may be defined in the JIC File. User-defined CDATA conversions are special factories that are identified by the target class instead of name and that always receive one parameter - the CDATA value of the element.

User-defined CDATA conversions are defined with the element type cdata-converter/1, which is similar to factory/x. The target class is given as a parameter for the type.

Example: User-defined CDATA conversion for java.util.Date

JIC Language does not have a CDATA conversion for java.util.Dates, because the date formats for defining dates vary so much. If dates need to be created in a JIC file, the java.text.DateFormat used for parsing the dates could be defined first and then used for parsing the dates:

<?xml version="1.0" encoding="UTF-8"?>
<birthdaysxmlns="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>

The same could be achieved by using a factory, although the factory does not provide much advantages in this case:

<?xml version="1.0" encoding="UTF-8"?>
<birthdaysxmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap">

<parseDate type="factory(java.lang.String dateString)">
<date class="java.util.Date" instance="parseFormat.parse(dateString)">
<parseFormat class="java.text.SimpleDateFormat" args="cdata">yyyy-MM-dd</parseFormat>
</date>
</parseDate>

<birthday action="put(person,date)">
<person>Britney Spears</person>
<date class="java.util.Date" instance="jic::parseDate(cdata)">1981-12-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Christina Aguilera</person>
<date class="java.util.Date" instance="jic::parseDate(cdata)">1980-12-18</date>
</birthday>
<birthday action="put(person,date)">
<person>Shakira</person>
<date class="java.util.Date" instance="jic::parseDate(cdata)">1977-02-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Justin Timberlake</person>
<date class="java.util.Date" instance="jic::parseDate(cdata)">1981-01-31</date>
</birthday>
</birthdays>

With a user-defined CDATA conversion, though, the code for creating a java.util.Date is reduced:

<?xml version="1.0" encoding="UTF-8"?>
<birthdaysxmlns="http://www.jicengine.org/jic/2.1" class="java.util.HashMap">

<toDate type="cdata-converter(java.util.Date)">
<date class="java.util.Date" instance="parseFormat.parse(cdata)">
<parseFormat class="java.text.SimpleDateFormat" args="cdata">yyyy-MM-dd</parseFormat>
</date>
</toDate>

<birthday action="put(person,date)">
<person>Britney Spears</person>
<date class="java.util.Date">1981-12-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Christina Aguilera</person>
<date class="java.util.Date">1980-12-18</date>
</birthday>
<birthday action="put(person,date)">
<person>Shakira</person>
<date class="java.util.Date">1977-02-02</date>
</birthday>
<birthday action="put(person,date)">
<person>Justin Timberlake</person>
<date class="java.util.Date">1981-01-31</date>
</birthday>
</birthdays>

11.2.When to Use User-defined CDATA Conversions?

user-defined CDATA conversions are useful in situations where have some application-specific objects that have a clear string-form. In these cases the user-defined CDATA conversions make it easier to define instances of these classes.

11.3.The type cdata-converter/1

The type cdata-converter/1 behaves much like the type factory/x. Characteristics:

(Type cdata-converter is available in JICE 2.1.2 and later.)

12. Build Parameters and Overridings

12.1.What Are Build Parameters?

A JIC File may receive build parameters. They are named Java objects that are given to the JIC engine at "runtime" i.e. when the JIC engine processes the JIC file. Build parameters can be used in the JIC File together with the Java objects initialized by the JIC elements.

A build parameter can be used in two ways:

  1. The parameter can override the element instance of a JIC Element. This kind of a parameter is an optional one and the JIC Element being overridden provides the default value.
  2. The parameter value can be retrieved explicitly. This kind of parameter is an obligatory parameter: the processing of the JIC File will fail if the parameter isn't present.

The details on how to provide build parameters to a JIC File are defined by the JIC Engine. See JIC Engine.

12.2.Overriding Element Instances: Attribute overridable-by

The element instance of any JIC Element can be declared to be overridable by a certain build parameter. This means that the element instance of the element serves as a default value. It is used if the parameter is not available. If the parameter exists, the parameter value will become the element instance of the element.

The attribute overridable-by declares that the element instance may be overridden. The value of the attribute is the name of the build parameter that is capable of overriding the instance.

Example: declaring an element to be overridable

The element <locale> is overridable by a build parameter locale.

<?xml version="1.0" encoding="UTF-8"?>
<numberFormatxmlns="http://www.jicengine.org/jic/2.1" class="java.text.NumberFormat" instance="java.text.NumberFormat.getIntegerInstance(locale)">
<locale class="java.util.Locale" overridable-by="locale">en_US</locale>
</numberFormat>

Note that only elements marked overridable can be overridden with build parameters. There is no support for overriding any element in a JIC File.

12.3.Effects of Overriding

If an element is overridden, the element is will not be executed normally:

Example: execution of inner action elements

If the build parameter message is present, the element <inner-action-element> will never be executed.

If the parameter is not available, the message "inner-action-element executed" will appear in System.out.

<?xml version="1.0" encoding="UTF-8"?>
<messagexmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String" instance="defaultValue" overridable-by="message">
<defaultValue>Hello World</defaultValue>
<inner-action-element action="out.println(debug)">
<debug>inner-action-element executed</debug>
<out class="java.io.PrintStream" instance="java.lang.System.out"/>
</inner-action-element>
</message>

12.4.How to Access Build Parameters Directly?

The value of a build parameter can be retrieved also directly. The instance attribute is used for this with a little peculiar syntax.

Example: retrieving the value of a build parameter

The element instance of <element> will be an int defined by the build parameter meaningOfLife.

<element class="int" instance="param::meaningOfLife"/>

The prefix param:: is followed by the name of the parameter. The parameter name does not have to adhere to the restrictions of Java variable names.

Example: different parameter names

The parameter name may contain also characters that are not allowed within Java variables.

<element class="int" instance="param::meaning.of.life"/>
<element2 class="int" instance="param::meaning-of-life"/>

13. How to Access File Resources from JIC Files?

One way to access file resources from JIC Files is to use the Java IO API in the same way as any API is used in JIC Language. For example, a java.io.File object may be created and read easily.

However, JIC Language provides also tools for locating various file resources with paths relative to the current JIC File. The resource model in the package org.jicengine.io is used for this.

By a resource we mean any kind of data that is read through the java.io.InputStream or java.io.Reader classes. The resource could be a file resource that is read with java.io.FileInputStream or it could be web resource that is read through a java.net.URL. See the package org.jicengine.io for more details.

The org.jicengine.io package does not need to be used if the resources are located through absolute paths or urls. But if relative paths needs to be used, the package provides nice tools for this.

Example: accessing file resources

The element type resource is used for locating resources relative to the current JIC File. For an example, lets say that we have the following file structure:

 dir/
  |_ subdir/
  |   |_ file2.properties
  |
  |_ example.jic
  |_ file1.properties

In the example.jic, the Java properties file file1.properties can be read with the following JIC script:

<properties class="java.util.Properties">
<inputStream action="load(inputStream)" class="java.io.InputStream" instance="resource.getInputStream()">
<resource class="org.jicengine.io.Resource">file1.properties</resource>
</inputStream>
</properties>

The example script does approximately the following:

  1. Element <properties> creates an empty java.util.Properties instance.
  2. The element <resource> creates an instance of org.jicengine.io.Resource that points to the properties file.
  3. The element <inputStream> obtains a java.io.InputStream instance from the <resource> element and loads the properties by calling the load method.

Of course, the other properties file may be read with the same fashion.

<properties class="java.util.Properties">
<inputStream action="load(this)" class="java.io.InputStream" instance="resource.getInputStream()">
<resource class="org.jicengine.io.Resource">subdir/file2.properties</resource>
</inputStream>
</properties>

The org.jicengine.io package is a good tool for reading resources. If you want to only resolve the url to the resource instead of reading it, most, but not all, of the implementations of the org.jicengine.io.Resource interface support also this.

14. How to Use Multiple JIC Files Together?

In a larger application there often rises a need to manipulate multipe JIC Files and use them modularily together. Here are a few examples of possible scenarios:

JICE provides currently only the basic tools for processing single JIC Files.

14.1.How to Use the Output of a JIC File as Input to Another JIC file?

JIC Files can be chained together: the output of one JIC File can be used as input to another. This can be done in two ways:

Both ways are explained in more detail below.

Example: Chaining in Application Code

Suppose that we have a file DateFormat.jic that yields a java.text.DateFormat instance:

<?xml version="1.0" encoding="UTF-8"?>
<dateFormatxmlns="http://www.jicengine.org/jic/2.1" class="java.text.SimpleDateFormat" args="pattern,locale">
<pattern>dd.MM.yyyy HH:mm:ss z</pattern>
<locale class="java.util.Locale" args="language,country">
<language>fi</language>
<country>FI</country>
</locale>
</dateFormat>

We want to use the DateFormat in the file formatDate.jic:

<formattedDate class="java.lang.String" instance="dateFormat.format(date)">
<dateFormat class="java.text.DateFormat" instance="param::dateFormat"/>
<date class="java.util.Date"/>
</formattedDate>

We would chain the two files in the application code:


import org.jicengine.io.*;
import org.jicengine.*;
import java.io.*;

// ....

try {

	// locate the two files
	Resource file1 = new FileResource(new File("DateFormat.jic"));
	Resource file2 = new FileResource(new File("formatDate.jic"));

	// process the first file
	DateFormat dateFormat = (DateFormat) JICEngine.build(file1);

	// construct parameters for the second file
	Map buildParams = new HashMap();
	buildParams.put("dateFormat", dateFormat);

	// process the second file

	String formattedDate = (String) JICEngine.build(file2, buildParams);

} catch (Exception e){
	// handle exception
}

	
Example: Chaining in the JIC File

We may also implement the chaining in the second JIC file. So we would modify the file formatDate.jic in the above example into this:

<formattedDate class="java.lang.String" instance="dateFormat.format(date)">
<dateFormat class="java.text.DateFormat" instance="org.jicengine.JICEngine.build(file)">
<file class="org.jicengine.io.Resource">DateFormat.jic</file>
</dateFormat>
<date class="java.util.Date"/>
</formattedDate>

14.2.Extending a JIC File

This refers to a situation where a JIC File needs to be modified slightly in order to derive a new configuration from it. There are many similar configurations, and there is a need to specify the common features in a single place, which is then extended.

Currently, two approaches can be used:

Technique Pros & Cons
The other files provide overridings to the general file. Simple. However, only elements marked overridable can be overridden.
Modify the JIC File with XSLT Any element can be modified. Requires however that the programmer knows XSLT. It may also be confusing that some of the configuration is written in JIC Language and the other in XSLT.

An example of the XSLT transformation is given below.

Example: modifying a JIC file with XSLT

The following kind of file is extended:

<?xml version="1.0" encoding="UTF-8"?>
<formattedDatexmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String" instance="dateFormat.format(date)">
<dateFormat class="java.text.SimpleDateFormat" args="pattern,locale">
<pattern>dd.MM.yyyy HH:mm:ss z</pattern>
<locale class="java.util.Locale" args="language,country">
<language>fi</language>
<country>FI</country>
</locale>
</dateFormat>
<date class="java.util.Date"/>
</formattedDate>

The following XSLT modifies the dateformat pattern.

The default template in the the XSLT copies every node to the result tree as is.

However, the one template matches the element j:formattedDate/j:dateFormat/j:pattern and replaces it with a new element.


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:j="http://www.jicengine.org/jic/2.1"
  xmlns="http://www.jicengine.org/jic/2.1"
  version="1.0"
  exclude-result-prefixes="j"
  >

<xsl:output method="xml" version="1.0" encoding="ISO-8859-1" omit-xml-declaration="no" indent="yes" />

<!--
===========================
override a single element
===========================
-->
<xsl:template match="j:formattedDate/j:dateFormat/j:pattern">
	<pattern>yyyy-MM-dd HH:mm:ss z</pattern>
</xsl:template> 

<!--
also other overridings could be specified here with similar templates.
-->


<!-- 
	this copies every other node to the result tree.
-->
<xsl:template match="@*|node()" priority="-100">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>


The XSL transformation results in the following JIC File where the <pattern> element has a different value.

<?xml version="1.0" encoding="UTF-8"?>
<formattedDatexmlns="http://www.jicengine.org/jic/2.1" class="java.lang.String" instance="dateFormat.format(date)">
<dateFormat class="java.text.SimpleDateFormat" args="pattern,locale">
<pattern>yyyy-MM-dd HH:mm:ss z</pattern>
<locale class="java.util.Locale" args="language,country">
<language>fi</language>
<country>FI</country>
</locale>
</dateFormat>
<date class="java.util.Date"/>
</formattedDate>

14.3.Generating JIC Files from other XML formats

JIC Language can be used in creating a mapping from any XML format to Java.

An application could for example specify a custom XML format, which is then converted to JIC Language code with XSLT and processed.

15. JIC Attribute Definitions

Attribute Purpose
action="JIC expression" Sets the action of the element.
args="variable list" Specifies constructor arguments.
class="full.class.name" Defines the class of the element instance of the element.
if="JIC expression" Defines an operation that determines whether the element is executed or not.
instance="JIC expression" Defines the operation that yields the element instance of the element.
overridable-by="parameterName" Makes the element instance overridable by an external parameter.
type="typeIdentifier" Sets the JIC element type of the element.
vars="variable list" Defines the element variables of the element.

15.1.action="JIC expression"

Effect Sets the action of the element.
Use Optional. Any element could be equipped with an action. The use of action does not depend on any other attribute.
Values

action may contain any JIC expression (see JIC Expressions). The action expression is executed in the action context of the element.

In addition, the use of the actor parent in method calls is optional. A plain method call is interpreted as a call to the parent. So instead of:

action="parent.setProperty(this)"

this is enough:

action="setProperty(this)"

Also, an empty value gives the element an action that, when executed, doesn't really do anything:

action=""

Other examples:

action="parent.setProperty(propertyValue)"
action="java.lang.System.setProperty(name, value)"

15.2.args="variable list"

Effect

Specifies constructor arguments given to the constructor in situations where the instance attribute is missing and the constructor invocation is derived from the class attribute.

Use Optional. Can not be used with the instance attribute.
Values

A comma-separated list of variables.

Any value that could be written inside the braces in a constructor invocation is valid. For example:

args="variable1"
args="variable1, variable2"

Example
<locale class="java.util.Locale" args="language,country">
<language>fi</language>
<country>FI</country>
</locale>

is the same as:

<locale class="java.util.Locale" instance="new java.util.Locale(language,country)">
<language>fi</language>
<country>FI</country>
</locale>

15.3.class="full.class.name"

Effect

States that the element has an element instance and signals the type of the instance. The attribute has two roles:

  1. class is a type constraint - Guarantees that the element instance of the element is an instance of this class (OR an instance of some subclass of this class).
  2. class provides a shortcut for defining the element instance of the element: If the element does not have the instance attribute, the Java operation that yields the element instance is defined from the class attribute:
    • A constructor invocation is derived from the class and args attributes.
    • If the element contains CDATA, the element instance created through CDATA Conversions.
Use

Required in elements that have an element instance.

Only exceptions are simple elements that have CDATA. The class attribute can be omitted in that case and the value of the class attribute will be either int, double, boolean or java.lang.String, depending on the value of the CDATA.

Values
  • A full class name
  • Primitive: int, double, boolean, long, float, char
  • Shortcut String may be used instead of java.lang.String

Note: Array types are defined with the same syntax as in Java source:
class="java.lang.Object[]", class="java.util.Date[]", etc.

Note: Inner classes are defined in a format that includes the $ sign. Use class="java.text.DateFormat$Field" instead of class="java.text.DateFormat.Field".

15.4.if="JIC expression"

Effect Controls whether the element is executed or not. Defines an expression that, if evaluates to false, hinders the element from being executed.
Use Optional. Any element may have a if attribute. Does not depend on other attributes.
Values

Any JIC Expression (see JIC Expressions)

The none of the element instances inside the element can be referenced from the if.

15.5.instance="JIC expression"

Effect Defines how the element instance of the element is obtained. The value is a Java operation that, when executed, yields the object.
Use Used in elements that have an element instance.
The instance can be omitted if the element instance is obtained through a constructor invocation.
Values

Any JIC expression may be used (see JIC Expressions). The expression is executed in the instance context of the element.

The expression should return an object, since null values are currently not supported.

Examples:

instance="new java util.Date()"
instance="new java.net.URL(address)"
instance="new java.util.Locale(language,country)"
instance="java.util.TimeZone.getTimeZone(id)"
instance="dateFormat.format(date)"
instance="variable"
instance="param::param.name"

15.6.overridable-by="parameterName"

Effect Declares that the element instance is overridable by a build parameter. See the section on build parameters and overridings for more details.
Optionality Optional. Can be used only if the element has an element instance.
Values

The name of the overriding build parameter.

NOTE: currently, a JIC file could contain two overridable elements with the same identifier i.e. the same build parameter would override multiple elements, if the Java classes of the elements are the same. Don't yet know whether this would be a good thing or not so try to avoid that.

15.7.type="typeIdentifier"

Effect Sets the JIC element type of the element.
Optionality Optional
Value
  • <typeName>(<parameters>), where:
    • <typeName is one of the following type names: bean, array, list, map, container, switch, factory
    • <parameters> are parameters given to the type.
  • If the type has no type parameters, simple expression <typeName> is enough.

15.8.vars="variable list"

Effect Defines which of the inner variable elements become element variables.
Use Optional.
Values

A comma-separated list of variable names that must match to the child variable elements of the element.

16. JIC Expressions

A JIC expression may consists of the following expressions:

The class names of inner classes contain the $ character. Instead of full.class.Name.InnerClass, the format full.class.Name$InnerClass must be used.