JIC Language

Author: Timo Laitinen
Date: 2006-05-07

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

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

Contents

4.4. Action
4.9. Summary
5.1. Primitives
7.4. Type array
7.6. Type list
7.7. Type map
7.10. Type factory

2.  What Is JIC Language?

JIC Language is an XML vocabulary for expressing a graph of Java objects. It provides a descriptive and specialized format for describing the state of a group of Java objects.

The XML code written in JIC Language is processed by the JIC Engine, a Java program that interprets the information and initializes the actual Java objects.

Before going into the details of the language, the term initialization is explained more thoroughly.

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

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

3.  XML Syntax of JIC Language

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"?>
<message xmlns="http://www.jicengine.org/jic/2.0">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"?>
<calendar xmlns="http://www.jicengine.org/jic/2.0"  class="java.util.GregorianCalendar"  args="year,month,day">
  <year  class="int">2004</year>
  <month  class="int">9</month>
  <day  class="int">9</day>
  <lenient  class="boolean">true</lenient>
  <timeZone  class="java.util.TimeZone"  instance="java.util.TimeZone.getTimeZone(id)">
    <id>GMT</id>
  </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
  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 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 also 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.

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 for defining the element instance. 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  class="int">123</number>
<locale  class="java.util.Locale"  args="language,country">
  <language>fi</language>
  <country>FI</country>
</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"?>
<map xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<calendar xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<map xmlns="http://www.jicengine.org/jic/2.0"  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-property xmlns="http://www.jicengine.org/jic/2.0"  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-message xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<calendar xmlns="http://www.jicengine.org/jic/2.0"  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 be converted to other kinds of Java objects.

Example: Converting CDATA manually

Few examples that access CDATA and convert it manually.

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

5.3. CDATA Conversions

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: automatic 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>

The same in Java:

String string1 = "This is a String";
Integer number = new Integer(12345);
double number2 = 123.45;
boolean boolean_ = true;

Because the CDATA is already a String and no conversion is needed, also the class attribute can be left out in elements that define a new String.

Example: creating a String

The class and instance attributes can be omitted when a String is created.

<string1  class="java.lang.String">This is a String</string1>
<string2>This is also a String</string2>

CDATA conversion is a convenient way to create data-objects that have an unambiguous String-form.

5.3.1. List of Available 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
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.String cdata any value
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. 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.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  class="int">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"?>
<calendar xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<formattedDate xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<out xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<position xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<array xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<birthdays xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<birthdays xmlns="http://www.jicengine.org/jic/2.0"  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 8 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.
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.

(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. List of All JIC Element Types

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

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"?>
<window xmlns="http://www.jicengine.org/jic/2.0"  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)"  class="boolean">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)"  class="boolean">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"?>
<window xmlns="http://www.jicengine.org/jic/2.0"  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"  instance="javax.swing.SwingConstants.CENTER"/>
      <font  class="java.awt.Font">Arial-bold-16</font>
    </label>
    <opaque  class="boolean">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"  instance="javax.swing.JFrame.DISPOSE_ON_CLOSE"/>
  <visible  class="boolean">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"?>
<array xmlns="http://www.jicengine.org/jic/2.0"  class="java.lang.String[]"  type="array">
  <e>Element 1</e>
  <e>Element 2</e>
  <e>Element 3</e>
  <e>Element 4</e>
</array>
Example: int array

Primitive arrays are created with the same procedure.

<?xml version="1.0" encoding="UTF-8"?>
<array xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<set xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<collection xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<list xmlns="http://www.jicengine.org/jic/2.0"  class="java.util.ArrayList"  type="list">
  <e  class="int">1</e>
  <e  class="int">2</e>
  <e  class="int">3</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"?>
<map xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<map xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<window xmlns="http://www.jicengine.org/jic/2.0"  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  class="boolean">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"?>
<windowContainer xmlns="http://www.jicengine.org/jic/2.0"  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  class="boolean">true</visible>
  </window>
</windowContainer>

7.9. Type switch

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

7.10. Type factory

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

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"?>
<container xmlns="http://www.jicengine.org/jic/2.0"  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-property xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<button xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<dateFormat xmlns="http://www.jicengine.org/jic/2.0"  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"?>
<test xmlns="http://www.jicengine.org/jic/2.0"  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>

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"?>
<window xmlns="http://www.jicengine.org/jic/2.0"  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  class="int">7</rows>
        <cols  class="int">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  class="boolean">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"?>
<window xmlns="http://www.jicengine.org/jic/2.0"  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  class="int">7</rows>
        <cols  class="int">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  class="boolean">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"?>
<container xmlns="http://www.jicengine.org/jic/2.0"  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.  Build Parameters and Overridings

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

11.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"?>
<numberFormat xmlns="http://www.jicengine.org/jic/2.0"  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.

11.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"?>
<message xmlns="http://www.jicengine.org/jic/2.0"  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>

11.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"/>

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

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

13.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"?>
<dateFormat xmlns="http://www.jicengine.org/jic/2.0"  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>

13.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"?>
<formattedDate xmlns="http://www.jicengine.org/jic/2.0"  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.0"
  xmlns="http://www.jicengine.org/jic/2.0"
  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"?>
<formattedDate xmlns="http://www.jicengine.org/jic/2.0"  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>

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

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

14.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)"

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

14.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 exception is an element whose element instance is the CDATA string. The class attribute can be omitted in that case and the default value java.lang.String will be used.

Values

A full class name.

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

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

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

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

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

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

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