Data Type Table

Description

A data type table defines an OpenL Tablets data carrier. Using data types inside the OpenL Tablets rules is recommended, since using data types created in OpenL Tablets table from Java code is limited in the current implementation. For Java code, the preferable method is to use Java or Vocabulary type. For information on how this is done, see Data Table.

The following is an example of a data type table defining a data type called Person:

Figure 20: Data type table

The first row is the header containing the keyword 'Datatype' followed by the name of the data type. Every row, beginning with the second one, represents one property of the data type. The first column contains property types; the second column contains corresponding property names.

How OpenL handles Datatypes inside

Datatypes tables are being processed second after Properties Table it is done to build a domain model that is used in rules.

Datatype header format:

[Datatype <typename>] or [Datatype <typename> extends <parentTypeName>] or [Datatype <typename> <aliastype>]

Inheritance in Datatypes

There is possibility to inherit one datatype from another in OpenL Tablets. New datatype that inherits another will have access to all fields defined in parent datatype. If child datatype contains fields that defined in parent you will get warnings or errors (if field declared with different types in child and parent).

Also constructor with all fields of child datatype will contains all fields from parent fields and toString, equals and hashCode methods will use all fields form parent datatype.

Byte code generation at runtime

At runtime, when Openl engine instance is being built, for each datatype component java byte code is being generated, it represents simple java bean for this datatype. This byte code is being loaded to classloader so the object of type Class<?> can be accessible. Using this object through reflections new instances are being created and fields of datatypes are being initialized (see DatatypeOpenClass and DatatypeOpenField classes).

Java files generation

As generation of datatypes is performed on runtime and users can`t access this classes in their code, so to the JavaWrapperAntTask was added a goal "generate datatypes". It adds the possibility of generation java files and putting it to the file system. So users can use this types in their code. But there is a limitation: users shouldn`t create instances of datatype classes before creating an instance of OpenL engine. This is because the static class that was on the file system will be loaded first to the classloader. That is not good as the engine consider to work with datatypes generated at runtime.

Examples of right and wrong usage of datatypes

Look at the next 2 examples, represented right and wrong usage of datatype classes in your code. Examples will be shown with usage of dynamic OpenL wrapper.

At first call the ant task "make wrapper generate datatypes" and you will get java files of datatypes at your file system.

public interface RulesInterface {

// define the interface of the rules engine. it will be succesfully

// compiled as we have all appropriate classes at file system

DoubleValue clientDiscount(Policy policy);

}

This example demonstrates the right usage of datatype beans. To the classloader will be loaded class generated at runtime.

EngineFactory<RulesInterface> engineFactory = new EngineFactory<RulesInterface>(RuleEngineFactory.RULE_OPENL_NAME,

"rules/main/Tutorial_4.xls", RulesInterface.class);

// create new instance of OpenL engine

RulesInterface test = engineFactory.makeInstance();

Policy policy = null;

// create new instance of datatype class after building OpenL instance

try {

policy = (Policy) Class.forName("org.openl.generated.beans.Policy").newInstance();

policy.setClientTier("Preferred");

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(test.clientDiscount(policy));

And this one demonstrates the wrong usage of datatype beans. To the classloader will be loaded class that was compiled from the file system.

// create new instance of datatype class before building OpenL instance

Policy policy = null;

try {

policy = (Policy) Class.forName("org.openl.generated.beans.Policy").newInstance();

policy.setClientTier("Preferred");

} catch (Exception e) {

e.printStackTrace();

}

EngineFactory<RulesInterface> engineFactory = new EngineFactory<RulesInterface>(RuleEngineFactory.RULE_OPENL_NAME, "rules/main/Tutorial_4.xls", RulesInterface.class);

// create new instance of OpenL engine

RulesInterface test = engineFactory.makeInstance();

System.out.println(test.clientDiscount(policy));

Access datatype at runtime and after building OpenL wrapper

After parsing, each datatype is put to compilation context, so it will be accessible for rules during binding. Also all datatypes are placed to IOpenClass of whole module and will be accessible from CompiledOpenClass#getTypes when Openl wrapper wiill be generated.

Each TableSyntaxNode that is of type xls.datatype contains an object of datatype as its member.

Working with Datatype arrays from rules

There are 2 possibilities to work with Datatype arrays from rules: