ExecutionEngine DataTypes
Overview
The two main execution pillars of the ExecutionEngine are invocations and data. This section covers the later. The ExecutionEngine supports a number of commonly used data types inherently and provides abstractions to cover all non primitive ones. These supported data types are covered in the following sections.
The direction followed by the ExecutionEngine aims to solve the following problem. In the context of a distributed environment that cannot afford to create a canonical data model perfectly defining the full range of transfered messages, there must be a way to describe the data moved without binding them to specific classes, packages or even schema. But still the way of capturing the data must contain enough information to be able to reconstruct the needed structures populating them with the stored values.
One way to go around this problem is to identify common workflow patterns, in an offline fashion, so that data exchange directions and pairs can be identified. Then, transformation utilities could be defined to support the identified pairings. These of course could explode to an unmanageable size of such transformations while it might only be applicable (keeping a curtain level of generality) to Web Service invocations, while POJO based transformations might become much more intrusive to client code.
This approach was not the one pursued by the ExecutionEngine and the underlying data types approach detailed in this section. The approach taken was that of non intrusive description of types and collection of types based on a wide list of primitives that are inherently manageable by the engine. These primitives are listed in following sections. This way, a component that needs to be invoked with some parameters or returns some parameter that needs to be later used, needs only to have a way of describing the structure and type of its type with respect to the engine constructs. After this mapping is performed, the engine can then provide a number of generic manipulation utilities that can process and transform the stored types to any type that is needed by the rest of its clients. For many of the listed constructs, even that specific mapping is not needed as the engine does its best to proactively sketch all the needed information at runtime. Of course there may be cases where a needed type may not be easily mapped to the supported constructs. In that case there are still utilities offered to cover all needs even if that would require a more tight client binding.
Supported data types
- BooleanClass
- A boolean object type (java.lang.Boolean)
- BooleanPrimitive
- A boolean primitive type (boolean)
- DoubleClass
- A double object type (java.lang.Double)
- DoublePrimitive
- A double primitive type (double)
- FloatClass
- A float object type (java.lang.Float)
- FloatPrimitive
- A float primitive type (float)
- IntegerClass
- An integer object type (java.lang.Integer)
- IntegerPrimitive
- An integer primitive type (int)
- String
- A String object type (java.lang.String)
- ResultSet
- An IProxyLocator type capable of identifying a result set
- RecordStore
- An IStoreLocator type capable of identifying a result set that is stored in some record store
- Convertable
- A type capable of storing information on a type that is not directly supported but can be transformed into a string serialization from an object and then back into the object using some converter object
- Reflectable
- A type capable of storing information on named data types that can be used to populate or be populated from an object that follows the generic get/set pattern on member variables of the respective names
- Array
- A multidimensional array of one of the above types
Highlights
- Wrapped and unwrapped types
- The reason of having for primitive types also the wrapped version of them (Integer primitive and integer Class), is mainly due to Java's reflection API and the way these Java types are distinguished from one another. So should for example part of the execution plan needs to make a call to some Java object's method through reflection, then the exact type as defined in the signature of that method must be available. If the method's signature requires an int and it is provided with an Integer, an error will occur.
- Convertables
- This Data Type category provides the biggest flexibility concerning the value that can be passed to an element invoked by the ExecutionEngine or returned to it by an invocation when the involved invokable is a POJO. But this also comes with the toll of having to produce the respective Converter utility for each object that will be passed back to the ExecutionEngine or be delivered by it. And this Converter utility will have to implement an interface that is defined by the ExecutionEngine library meaning that the portability of the package is hurt. Even so, the capability is offered in cases where portability is not of great importance.
- Refelctables
- This Data Type category provides the largest generality without binding the client implementation to any execution engine libraries. As most of the types passed as arguments or are returned as results mainly act as containers of other primitive types, this utility offers the possibility of abstracting over these objects through the means of the regularly used get/set methods. An object returned by a client class invocation is scanned through reflection and the getters and setters found dictate the member values it offers. These values are then extracted through the respective getter method and are stored under the name that joins the get and set method (e.g. for int getX() and setX(int x), the common name is X). Respectively when populating an argument, the getters and setters are retrieved and wherever the common name matches one of the names available through the reflectable data type as well as the type, the setter is used to set the payload needed. This scanning can work recursively to sketch a very deep level of encapsulation. This Data Type in conjunction with the Array data type can cover most of the foreseen common usage scenarios.
Usage
The following snippets demonstrate the definition of some of the above listed data types and the corresponding xml representations to give an insight on the internal structure.
Primitive boolean data type:
IDataType dt1=new DataTypeBooleanPrimitive(); dt1.SetValue(true);
The corresponding XML representation of the data type:
<dt type="BooleanPrimitive"> <value>true</value> </dt>
A plain string data type:
IDataType dt2=new DataTypeString(); dt2.SetValue("Hello World of D4Science");
The corresponding XML representation of the data type:
<dt type="String"> <value> <![CDATA[ Hello World of D4Science ]]> </value> </dt>
A data type that can host the serialization created by the specified converter and also be used to reconstruct the original object:
IDataType dt3=new DataTypeConvertable(); ((DataTypeConvertable)dt3).SetConverter(ObjectImplementingIObjectConverter.class.getName());
The corresponding XML representation of the data type:
<dt type="Convertable"> <value> <converted/> <converter>some.package.name.ObjectImplementingIObjectConverter</converter> </value> </dt>
A simple one dimensional integer array:
IDataType dt4=new DataTypeArray(); ((DataTypeArray)dt4.Value).SetArrayClassCode("["+IDataType.DataTypes.IntegerPrimitive); ((DataTypeArray)dt4.Value).SetValue(new int[] {1,2,3,4,5});
The corresponding XML representation of the data type:
<dt type="Array"> <value> <array code="[IntegerPrimitive"> <item> <dt type="IntegerPrimitive"> <value>1</value> </dt> </item> <item> <dt type="IntegerPrimitive"> <value>2</value> </dt> </item> <item> <dt type="IntegerPrimitive"> <value>3</value> </dt> </item> <item> <dt type="IntegerPrimitive"> <value>4</value> </dt> </item> <item> <dt type="IntegerPrimitive"> <value>5</value> </dt> </item> </array> </value> </dt>
A more complex data type follows. The following snippets fiorst define the types involved, and then as before present the code neede3d to make the data type definition as well as the the produced XML representation:
public class Person { private String Name=null; private int Age=0; private Course[] Courses=null; public Person(String Name,int Age,Course[] Courses) { this.Name=Name; this.Age=Age; this.Courses=Courses; } public void setName(String Name){this.Name=Name;} public String getName(){return this.Name;} public void setAge(int Age){this.Age=Age;} public int getAge(){return this.Age;} public void setCourses(Course[] Courses){this.Courses=Courses;} public Course[] getCourses(){return this.Courses;} } public class Course{ private String Name=null; private float Grade=0; public Course(String Name,float Grade){ this.Name=Name; this.Grade=Grade; } public void setName(String Name){this.Name=Name;} public String getName(){return this.Name;} public void setGrade(float Grade){this.Grade=Grade;} public float getGrade(){return this.Grade;} }
The data type definition snippet is the following:
Person p1=new Person("Insert Name Here", 40, new Course[]{new Course("Driving", 4.5f), new Course("Cooking",5.2f)}); Person p2=new Person("Rena Tsantouli", 25, new Course[]{new Course("Artistic Design", 4.5f), new Course("Sex education",9.2f), new Course("Web Design",-0.2f)}); Person p3=new Person("Insert Name Here", 27, new Course[]{new Course("Body Building", 9.4f), new Course("Comedy 101",5.2f)}); IDataType dt5=new DataTypeArray(); ((DataTypeArray)dt5).SetDefaultComponentType(Person.class.getName()); ((DataTypeArray)dt5).SetArrayClassCode("["+IDataType.DataTypes.Reflectable); ((DataTypeArray)dt5).SetValue(new Person[] {p1,p2,p3});
The corresponding XML representation is the following:
<dt type="Array"> <defComponent>some.package.name.Person</defComponent> <value> <array code="[Reflectable"> <item> <dt type="Reflectable"> <value> <items> <item name="Name""> <dt type="String"> <value><![CDATA[Insert Name Here]]></value> </dt> </item> <item name="Courses"> <dt type="Array"> <defComponent>some.package.name.Course</defComponent> <value> <array code="[Reflectable"> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Driving]]></value> </dt> </item> <item name="Grade"> <dt type="FloatPrimitive"> <value>4.5</value> </dt> </item> </items> </value> </dt> </item> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Cooking]]></value> </dt> </item> <item name="Grade"> <dt type="FloatPrimitive"> <value>5.2</value> </dt> </item> </items> </value> </dt> </item> </array> </value> </dt> </item> <item name="Age"> <dt type="IntegerPrimitive"> <value>40</value> </dt> </item> </items> </value> </dt> </item> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Insert Name Here]]></value> </dt> </item> <item name="Age"> <dt type="IntegerPrimitive"> <value>25</value> </dt> </item> <item name="Courses"> <dt type="Array"> <defComponent>some.package.name.Course</defComponent> <value> <array code="[Reflectable"> <item> <dt type="Reflectable"> <value> <items> <item name="Grade"> <dt type="FloatPrimitive"> <value>4.5</value> </dt> </item> <item name="Name"> <dt type="String"> <value><![CDATA[Artistic Design]]></value> </dt> </item> </items> </value> </dt> </item> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Sex education]]></value> </dt> </item> <item name="Grade"> <dt type="FloatPrimitive"> <value>9.2</value> </dt> </item> </items> </value> </dt> </item> </array> </value> </dt> </item> </items> </value> </dt> </item> <item> <dt type="Reflectable"> <value> <items> <item name="Age"> <dt type="IntegerPrimitive"> <value>27</value> </dt> </item> <item name="Courses"> <dt type="Array"> <defComponent>some.package.name.Course</defComponent> <value> <array code="[Reflectable"> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Body Building]]></value> </dt> </item> <item name="Grade"> <dt type="FloatPrimitive"> <value>9.4</value> </dt> </item> </items> </value> </dt> </item> <item> <dt type="Reflectable"> <value> <items> <item name="Name"> <dt type="String"> <value><![CDATA[Comedy 101]]></value> </dt> </item> <item name="Grade"> <dt type="FloatPrimitive"> <value>5.2</value> </dt> </item> </items> </value> </dt> </item> </array> </value> </dt> </item> <item name="Name"> <dt type="String"> <value><![CDATA[Insert Name Here]]></value> </dt> </item> </items> </value> </dt> </item> </array> </value> </dt>