You can use the XOM API to create your own class driver.
When rules use a dynamic class, the rule engine must know the runtime policy for the class. The runtime policy is provided by a class driver and includes field getters and setters, and method and constructor bodies.
The runtime policy is defined through the following interfaces:
IlrClassDriver.ClassTester is used to test whether a particular Java™ object is an instance of a particular class.
IlrClassDriver.Reader represents a field getter, that is, a Java object used to read an object field.
IlrClassDriver.Writer represents a field setter, that is, a Java object used to write a value to a field.
IlrClassDriver.UnknownChecker is used to test whether a class has any unknown fields, that is, fields that have not been assigned a value.
IlrClassDriver.Invoker represents an invoker, that is, a Java object capable of executing a method.
IlrClassDriver.Constructor represents a constructor, that is, a Java object capable of creating an instance of the class.
IlrClassDriver contains methods for returning instances of the previous interfaces.
To create a class driver:
With a class driver, you can implement a dynamic class using any type of class, such as implementing all the dynamic classes of an application using hash tables.
It is not necessary to create and set the fields in a way that depends on the implementation. Once the class drivers are defined, the dynamic classes provide the means for creating and manipulating objects without knowing the implementation details of a particular driver.
A class driver that supports a constructor with no arguments:
Here is a simple example of a class driver that does not support method invocations but does support a zero-argument constructor. The following IlrHashObject class defines the root Java class to which all the dynamic classes are mapped.
package ilog.rules.factory;
import ilog.rules.bom.*;
import java.util.*;
public class IlrHashObject extends HashMap
{
private IlrClass clazz;
public IlrHashObject(IlrClass arg)
{
super(10);
clazz = arg;
}
//------------------------------------------------------------
// Identification methods
//------------------------------------------------------------
public boolean equals(Object arg)
{
return this == arg;
}
public int hashCode()
{
return System.identityHashCode(this);
}
public String toString()
{
StringBuffer buffer = new StringBuffer(100);
buffer.append(getXOMClassName());
buffer.append('@');
buffer.append(Integer.toHexString(hashCode()));
return buffer.toString();
}
//------------------------------------------------------------
// Utilities
//------------------------------------------------------------
public IlrClass getXOMClass()
{
return this.clazz;
}
public String getXOMClassName()
{
return clazz.getFullyQualifiedName();
}
};
A hash driver class:
The following IlrHashDriver class defines the runtime policy for such a virtual class hierarchy.
The class IlrHashObject is not required to implement any interfaces imposed by Decision Server.
package ilog.rules.factory;
import ilog.rules.bom.*;
import java.util.*;
public class IlrHashDriver implements IlrClassDriver
{
//------------------------------------------------------------
// Static classes
//------------------------------------------------------------
static class DynamicTester implements IlrClassDriver.ClassTester
{
IlrClass clazz;
DynamicTester(IlrClass clazz)
{
this.clazz = clazz;
}
public boolean isInstance(Object object)
{
return ((object instanceof IlrHashObject) &&
clazz.isAssignableFrom(((IlrHashObject)object).getXOMClass()));
}
};
static class Reader implements IlrClassDriver.Reader
{
String fieldname;
Reader(String fieldname)
{
this.fieldname = fieldname;
}
public Object get(Object object)
{
return ((IlrHashObject)object).get(fieldname);
}
};
static class Writer implements IlrClassDriver.Writer
{
String fieldname;
Writer(String fieldname)
{
this.fieldname = fieldname;
}
public void set(Object object,Object value)
{
((IlrHashObject)object).put(fieldname,value);
}
};
static class Constructor implements IlrClassDriver.Constructor
{
IlrClass clazz;
Constructor(IlrClass clazz)
{
this.clazz = clazz;
}
public Object newInstance(Object[] arguments)
{
return new IlrHashObject(clazz);
}
};
static class UnknownChecker implements IlrClassDriver.UnknownChecker
{
String fieldname;
UnknownChecker(String fieldname)
{
this.fieldname = fieldname;
}
public boolean isUnknown(Object object)
{
return !((IlrHashObject)object).containsKey(fieldname);
}
};
//------------------------------------------------------------
// Implementation of the driver
//------------------------------------------------------------
public IlrHashDriver()
{
}
public static IlrClassDriver create(IlrReflect reflect) throws Exception
{
return new IlrHashDriver();
}
public Class getRootClass()
{
return IlrHashObject.class;
}
public IlrClass getXOMClass(Object object)
{
return (object instanceof IlrHashObject) ?
((IlrHashObject)object).getXOMClass() : null;
}
public IlrClassDriver.ClassTester getTester(IlrClass aclass)
{
return new DynamicTester(aclass);
}
public IlrClassDriver.Reader getReader(IlrAttribute attribute)
{
return new Reader(attribute.getName());
}
public IlrClassDriver.Writer getWriter(IlrAttribute attribute)
{
return new Writer(attribute.getName());
}
public IlrClassDriver.UnknownChecker getUnknownChecker(IlrAttribute att)
{
return new UnknownChecker(att.getName());
}
public IlrClassDriver.Invoker getInvoker(IlrMethod method)
{
return null;
}
public IlrClassDriver.Constructor getConstructor(IlrConstructor constructor)
{
return new Constructor(constructor.getDeclaringClass());
}
};
Adding a Java object belonging to the class Person:
Suppose that a dynamic class Person with fields name and age are defined and that the class has the property set indicating that it uses IlrHashDriver as a class driver. The IlrReflect object contains an instance of IlrClass, named myclass, which represents the dynamic class. The following code creates and adds a Java object that is seen by the rule engine as belonging to the class Person.
IlrClass myclass = myModel.getClass("mypackage.Person")
IlrHashObject obj = new IlrHashObject(myclass); // Creates the object.
obj.put("name","Michael"); // Initializes the field name.
obj.put("age",new Integer(36)); // Initializes the field age.
context.insert(obj); // Inserts the object.