jadex.rules.state.io.xml.OAVObjectReaderHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-rules Show documentation
Show all versions of jadex-rules Show documentation
Jadex Rules is a small lightweight rule engine, which currently
employs the well-known Rete algorithm for highly efficient rule
matching. Jadex rules is therefore similar to other rule engines
like JESS and Drools. Despite the similarities there are also
important differences between these systems:
* Jadex Rules is very small and
intended to be used as component
of other software. Even though rules can be specified in a Java
dialect as well as (a small variation of) the CLIPS language
its primary usage is on the API level. Jadex Rules is currently
the core component of the Jadex BDI reasoning engine.
* Jadex Rules cleanly separates between state and rule representation.
This allows the state implementation as well as the matcher to be
flexibly exchanged. Some experiments have e.g. been conducted with
a Jena representation. Regarding the matcher, it is planned to
support also the Treat algorithm, which has a lower memory footprint
than Rete.
* Jadex Rules pays close attention to rule debugging. The state as
well as the rete engine can be observed at runtime. The rule debugger
provides functionalities to execute a rule program stepwise and also
use rule breakpoints to stop the execution at those points.
package jadex.rules.state.io.xml;
import jadex.commons.SReflect;
import jadex.rules.state.IOAVState;
import jadex.rules.state.OAVAttributeType;
import jadex.rules.state.OAVJavaType;
import jadex.rules.state.OAVObjectType;
import jadex.xml.AttributeInfo;
import jadex.xml.BasicTypeConverter;
import jadex.xml.IPostProcessor;
import jadex.xml.IStringObjectConverter;
import jadex.xml.SXML;
import jadex.xml.StackElement;
import jadex.xml.SubobjectInfo;
import jadex.xml.TypeInfo;
import jadex.xml.bean.IBeanObjectCreator;
import jadex.xml.reader.IObjectReaderHandler;
import jadex.xml.reader.LinkData;
import jadex.xml.reader.ReadContext;
import java.util.List;
import java.util.Map;
/* $if !android $ */
import javax.xml.namespace.QName;
/* $else $
import javaxx.xml.namespace.QName;
$endif $ */
/**
* Handler for reading XML into OAV objects.
*/
public class OAVObjectReaderHandler implements IObjectReaderHandler
{
//-------- constants --------
/** Key of the state in the user context map. */
public static final String CONTEXT_STATE = "state";
//-------- constructors --------
/**
* Create a new handler.
*/
public OAVObjectReaderHandler()
{
}
//-------- methods --------
/**
* Get the most specific mapping info.
* @param tag The tag.
* @param fullpath The full path.
* @return The most specific mapping info.
*/
public TypeInfo getTypeInfo(Object object, QName[] fullpath, ReadContext context)
{
return null;
}
/**
* Create an object for the current tag.
* @param type The object type to create.
* @param root Flag, if object should be root object.
* @param context The context.
* @return The created object (or null for none).
*/
public Object createObject(Object type, boolean root, ReadContext context, Map rawattributes) throws Exception
{
Object ret = null;
IOAVState state = (IOAVState)((Map)context.getUserContext()).get(CONTEXT_STATE);
if(type instanceof TypeInfo)
type = ((TypeInfo)type).getTypeInfo();
if(type instanceof OAVObjectType)
{
ret = root? state.createRootObject((OAVObjectType)type): state.createObject((OAVObjectType)type);
}
else if(type instanceof Class)
{
Class clazz = (Class)type;
if(!BasicTypeConverter.isBuiltInType(clazz))
{
// Must have empty constructor.
ret = clazz.newInstance();
}
}
else if(type instanceof IBeanObjectCreator)
{
ret = ((IBeanObjectCreator)type).createObject(context, rawattributes);
}
else if(type instanceof QName)
{
// System.out.println("here: "+typeinfo);
QName tag = (QName)type;
OAVObjectType oavtype = state.getTypeModel().getObjectType(tag.getLocalPart());
if(oavtype!=null)
{
ret = root? state.createRootObject(oavtype): state.createObject(oavtype);
}
}
return ret;
}
/**
* Get the object type
* @param object The object.
* @return The object type.
*/
public Object getObjectType(Object object, ReadContext context)
{
return ((IOAVState)context).getType(object);
}
/**
* Convert an object to another type of object.
*/
public Object convertContentObject(String object, QName tag, ReadContext context) throws Exception
{
Object ret = object;
if(tag.getNamespaceURI().startsWith(SXML.PROTOCOL_TYPEINFO))
{
String clazzname = tag.getNamespaceURI().substring(8)+"."+tag.getLocalPart();
Class clazz = SReflect.classForName0(clazzname, context.getClassLoader());
if(clazz!=null)
{
if(!BasicTypeConverter.isBuiltInType(clazz))
throw new RuntimeException("No converter known for: "+clazz);
ret = BasicTypeConverter.getBasicStringConverter(clazz).convertString(object, context);
}
}
// todo: also support OAVObjectTypes as tagname for conversion?
// else
// {
// IOAVState state = (IOAVState)context;
//
// OAVObjectType type = state.getTypeModel().getObjectType(tag.getLocalPart());
// if(type!=null)
// {
// ret = state.createObject(type);
// Collection attrs = type.getDeclaredAttributeTypes();
// }
// }
return ret;
}
/**
* Handle the attribute of an object.
* @param object The object.
* @param attrname The attribute name.
* @param attrval The attribute value.
* @param attrinfo The attribute info.
* @param context The context.
*/
public void handleAttributeValue(Object object, QName xmlattrname, List attrpath, String attrval,
Object attrinfo, ReadContext context) throws Exception
{
// todo: implement idref!
// if(xmlattrname!=null && xmlattrname.getLocalPart().equals("ref"))
// System.out.println("ref: "+xmlattrname);
// If attrval==null only set if default value available.
if(attrval==null && !(attrinfo instanceof AttributeInfo && ((AttributeInfo)attrinfo).getAccessInfo().getDefaultValue()!=null))
return;
IOAVState state = (IOAVState)((Map)context.getUserContext()).get(CONTEXT_STATE);
OAVAttributeType attrtype = null;
Object val = attrval;
if(attrinfo instanceof AttributeInfo)
{
AttributeInfo info = (AttributeInfo)attrinfo;
attrtype = (OAVAttributeType)info.getAttributeIdentifier();
if(val==null && ((AttributeInfo)attrinfo).getAccessInfo().getDefaultValue()!=null)
val = ((AttributeInfo)attrinfo).getAccessInfo().getDefaultValue();
if(info instanceof AttributeInfo)
{
IStringObjectConverter conv = ((AttributeInfo)info).getConverter();
if(conv!=null)
val = conv.convertString(attrval, null);
}
}
else if(attrinfo instanceof OAVAttributeType)
{
attrtype = (OAVAttributeType)attrinfo;
}
else if(attrinfo!=null)
{
StackElement se = context.getTopStackElement();
context.getReporter().report("Unknown attribute info: "+attrinfo, "attribute error", context, se.getLocation());
}
// Search attribute in type and supertypes.
if(attrtype==null)
{
int pathidx = 0;
String tmpname = xmlattrname.getLocalPart();
do
{
// System.out.println("tmpname: "+tmpname);
String attrnameplu = tmpname.endsWith("y")? tmpname.substring(0, tmpname.length()-1)+"ies": tmpname+"s";
// Search in object type and all super types
OAVObjectType tmptype = state.getType(object);
while(attrtype==null && tmptype!=null)
{
String tmpnamesin = tmptype.getName()+"_has_"+tmpname;
String tmpnameplu = tmptype.getName()+"_has_"+attrnameplu;
attrtype = tmptype.getDeclaredAttributeType0(tmpnamesin);
if(attrtype==null)
attrtype = tmptype.getDeclaredAttributeType0(tmpnameplu);
if(attrtype==null)
tmptype = tmptype.getSupertype();
}
// Search for outer tags
if(attrpath!=null && attrpath.size()>pathidx)
tmpname = ((QName)attrpath.get(pathidx)).getLocalPart();
pathidx++;
}
while(attrtype==null && attrpath!=null && attrpath.size()>=pathidx);
}
if(attrtype!=null)
{
try
{
Object arg = val instanceof String && attrtype.getType() instanceof OAVJavaType
&& BasicTypeConverter.isBuiltInType(((OAVJavaType)attrtype.getType()).getClazz())?
BasicTypeConverter.getBasicStringConverter((((OAVJavaType)attrtype.getType()).getClazz()))
.convertString(attrval, null): val;
setAttributeValue(state, object, attrtype, arg);
}
catch(Exception e)
{
StackElement se = context.getTopStackElement();
context.getReporter().report(e.toString(), "attribute error", context, se.getLocation());
}
}
else
{
StackElement se = context.getTopStackElement();
context.getReporter().report("Unhandled attribute: "+object+", "+xmlattrname+", "+attrpath, "unhandled attribute", context, se.getLocation());
}
}
/**
* Link an object to its parent.
* @param object The object.
* @param parent The parent object.
* @param linkinfo The link info.
* @param tagname The current tagname (for name guessing).
* @param context The context.
*/
public void linkObject(Object elem, Object parent, Object linkinfo, QName[] pathname, ReadContext context) throws Exception
{
IOAVState state = (IOAVState)((Map)context.getUserContext()).get(CONTEXT_STATE);
// int idx = pathname.lastIndexOf("/");
// String tagname = idx!=-1? pathname.substring(idx+1): pathname;
String tagname = pathname[pathname.length-1].getLocalPart();
// System.out.println("link: "+elem+" "+parent);
// Find attribute where to set/add the child element.
boolean linked = false;
OAVAttributeType attrtype = null;
if(linkinfo instanceof SubobjectInfo)
{
SubobjectInfo info = (SubobjectInfo)linkinfo;
// if(!(info.getAccessInfo().getObjectIdentifier() instanceof OAVAttributeType))
// {
// System.out.println("kldg");
// }
attrtype = (OAVAttributeType)info.getAccessInfo().getObjectIdentifier();
// todo:?
// IStringObjectConverter conv = info.getConverter();
// if(conv!=null)
// elem = conv.convertString(elem, null);
}
else if(linkinfo instanceof OAVAttributeType)
{
attrtype = (OAVAttributeType)linkinfo;
}
if(attrtype!=null)
{
setAttributeValue(state, parent, attrtype, elem);
linked= true;
}
if(!linked)
{
linked = internalLinkObjects(tagname, elem, parent, state);
}
if(!linked && !(state.getType(elem) instanceof OAVJavaType
&& BasicTypeConverter.isBuiltInType(((OAVJavaType)state.getType(elem)).getClazz())))
{
linked = internalLinkObjects(state.getType(elem).getName(), elem, parent, state);
}
if(!linked)
{
context.getReporter().report("Could not link: "+elem+" "+parent, "Could not link", context, context.getParser().getLocation());
// throw new RuntimeException("Could not link: "+elem+" "+parent);
}
}
/**
* Bulk link an object to its parent.
* @param parent The parent object.
* @param children The children objects (link datas).
* @param context The context.
* @param classloader The classloader.
* @param rootobject The root object.
*/
public void bulkLinkObjects(Object parent, List children, ReadContext context) throws Exception
{
// System.out.println("bulk link for: "+parent+" "+children);
for(int i=0; i