jadex.xml.reader.AReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-serialization-xml Show documentation
Show all versions of jadex-serialization-xml Show documentation
Jadex XML is an XML data binding framework for Java and also for other representations. The main idea of Jadex XML is that neither the XML-Schema on the one side nor the Java classes on the other side should define other binding. Instead, a separate mapping between both is used as a mediation. This allows designing the XML representation independent of the Java side but still being able to connect both as desired.
This idea was first put forward by the JiBX data binding framework. Jadex XML pushes it further by combining it with the configuration by exception principle. The framework can detect obvious correspondences between both sides automatically and only needs configuration information when translations are necessary. The configuration information is currently specified directly in form of Java configuration classes.
package jadex.xml.reader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.XMLConstants;
import jadex.commons.SUtil;
import jadex.commons.Tuple;
import jadex.commons.transformation.IStringObjectConverter;
import jadex.xml.AttributeInfo;
import jadex.xml.IPostProcessor;
import jadex.xml.SXML;
import jadex.xml.StackElement;
import jadex.xml.SubobjectInfo;
import jadex.xml.TypeInfo;
import jadex.xml.TypeInfoPathManager;
import jadex.xml.stax.ILocation;
import jadex.xml.stax.QName;
import jadex.xml.stax.XMLReporter;
import jadex.xml.stax.XmlUtil;
/**
* XML Reader abstract class.
*/
public abstract class AReader
{
//-------- constants --------
/** The debug flag. */
public static final boolean DEBUG = false;
/** The string marker object. */
public static final Object STRING_MARKER = new Object();
/** This thread local variable provides access to the read context,
* e.g. from the XML reporter, if required. */
public static final ThreadLocal READ_CONTEXT = new ThreadLocal();
/** The null object. */
public static final Object NULL = new Object();
/** The link mode. */
protected boolean bulklink;
protected XMLReporter reporter;
public AReader(boolean bulklink, XMLReporter reporter) {
this.bulklink = bulklink;
this.reporter = reporter!=null ? reporter : new XMLReporter()
{
public void report(String message, String errorType, Object relatedInformation, ILocation location) throws Exception
{
throw new RuntimeException(message);
}
};
}
/**
* Read properties from xml.
* @param input The input stream.
* @param classloader The classloader.
* @param context The context.
*/
// public abstract Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, java.io.Reader input, final ClassLoader classloader,
// final Object callcontext) throws Exception;
/**
* Read properties from xml.
* @param input The input stream.
* @param classloader The classloader.
* @param context The context.
*/
// public abstract Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, InputStream input, final ClassLoader classloader,
// final Object callcontext) throws Exception;
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromXML(AReader reader, String val, ClassLoader classloader, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
return objectFromXML(reader, val, classloader, null, manager, handler);
}
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromXML(AReader reader, String val, ClassLoader classloader,
Object context, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
// return objectFromByteArray(reader, val.getBytes(), classloader, context);
java.io.Reader rd = null;
try
{
rd = new StringReader(val);
Object ret = reader.read(manager, (IObjectReaderHandler)handler, rd, classloader, context);
return ret;
}
catch(Exception e)
{
// t.printStackTrace();
// System.out.println("problem: "+new String(val));
throw new RuntimeException(e);
}
finally
{
if(rd!=null)
{
try
{
rd.close();
}
catch(Exception e)
{
}
}
}
}
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromByteArray(AReader reader, byte[] val, ClassLoader classloader, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
return objectFromInputStream(reader, new ByteArrayInputStream(val), classloader, null, manager, handler);
}
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromByteArray(AReader reader, byte[] val, ClassLoader classloader, Object context, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
return objectFromInputStream(reader, new ByteArrayInputStream(val), classloader, context, manager, handler);
}
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromInputStream(AReader reader, InputStream val, ClassLoader classloader, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
return objectFromInputStream(reader, val, classloader, null, manager, handler);
}
/**
* @param val The string value.
* @return The encoded object.
*/
public static Object objectFromInputStream(AReader reader, InputStream bis, ClassLoader classloader, Object context, TypeInfoPathManager manager, IObjectReaderHandler handler)
{
try
{
Object ret = reader.read(manager, (IObjectReaderHandler)handler, bis, classloader, context);
return ret;
}
catch(Exception e)
{
// t.printStackTrace();
// System.out.println("problem: "+new String(val));
throw SUtil.throwUnchecked(e);
}
finally
{
if(bis!=null)
{
try
{
bis.close();
}
catch(Exception e)
{
}
}
}
}
/**
*
* /
public static Object[] getLastStackElementWithObject(List stack, QName localname)
{
StackElement pse = (StackElement)stack.get(stack.size()-2);
List pathname = new ArrayList();
pathname.add(localname);
for(int i=stack.size()-3; i>=0 && pse.getObject()==null; i--)
{
pse = (StackElement)stack.get(i);
pathname.add(0, ((StackElement)stack.get(i+1)).getTag());
}
return new Object[]{pse, pathname};
}*/
/**
* Get a subobject info for reading.
*/
public static SubobjectInfo getSubobjectInfoRead(QName localname, QName[] fullpath, TypeInfo patypeinfo, Map attrs)
{
SubobjectInfo ret = null;
if(patypeinfo!=null)
{
QName tag = localname;
QName[] fpath = fullpath;
// Hack! If localname is classname remove it
if(localname.getNamespaceURI().startsWith(SXML.PROTOCOL_TYPEINFO))
{
tag = fullpath[fullpath.length-2];
fpath = new QName[fullpath.length-1];
System.arraycopy(fullpath, 0, fpath, 0, fpath.length);
}
ret = patypeinfo.getSubobjectInfoRead(tag, fpath, attrs);
}
return ret;
}
/**
* Read properties from xml.
* @param input The input stream.
* @param classloader The classloader.
* @param context The context.
*/
public Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, java.io.Reader input, final ClassLoader classloader, final Object callcontext) throws Exception
{
IXMLReader parser = createXMLReader(input);
return read(tipmanager, handler, parser, classloader, callcontext);
}
/**
* Read properties from xml.
* @param input The input stream.
* @param classloader The classloader.
* @param context The context.
*/
public Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, InputStream input, final ClassLoader classloader, final Object callcontext) throws Exception
{
IXMLReader parser = createXMLReader(input);
return read(tipmanager, handler, parser, classloader, callcontext);
}
/**
* Read properties from xml.
* @param input The input stream.
* @param classloader The classloader.
* @param context The context.
*/
public Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, IXMLReader parser, final ClassLoader classloader, final Object callcontext) throws Exception
{
AReadContext readcontext = createReadContext(tipmanager, handler, parser, reporter, callcontext, classloader);
AReadContext oldcontext = READ_CONTEXT.get();
READ_CONTEXT.set(readcontext);
try
{
while(parser.hasNext())
{
int next = parser.next();
if(next== XmlUtil.COMMENT)
{
handleComment(readcontext);
}
else if(next==XmlUtil.CHARACTERS || next==XmlUtil.CDATA)
{
handleContent(readcontext);
}
else if(next==XmlUtil.START_ELEMENT)
{
handleStartElement(readcontext);
}
else if(next==XmlUtil.END_ELEMENT)
{
handleEndElement(readcontext);
}
}
// Handle post-processors.
for(int i=1; readcontext.getPostProcessors().size()>0; i++)
{
List ps = (List)readcontext.getPostProcessors().remove(Integer.valueOf(i));
if(ps!=null)
{
for(int j=0; j0 ? readcontext.getTopStackElement().getLocation() : parser.getLocation();
readcontext.getReporter().report(e.toString(), "XML error", readcontext, loc);
}
finally
{
READ_CONTEXT.set(oldcontext);
parser.close();
}
return readcontext.getRootObject()==NULL ? null : readcontext.getRootObject();
}
/**
* Handle the comment.
* @param readcontext The context for reading with all necessary information.
*/
protected void handleComment(AReadContext readcontext) throws Exception
{
if(readcontext.getReadIgnore()==0)
readcontext.setComment(readcontext.getParser().getText());
else if(DEBUG)
System.out.println("Ignoring: "+readcontext.getParser().getText());
// System.out.println("Found comment: "+comment);
}
/**
* Handle the content.
* @param readcontext The context for reading with all necessary information.
*/
protected void handleContent(AReadContext readcontext) throws Exception
{
if(readcontext.getReadIgnore()==0)
readcontext.getTopStackElement().addContent(readcontext.getParser().getText());
else if(DEBUG)
System.out.println("Ignoring: "+readcontext.getParser().getText());
// System.out.println("content: "+parser.getLocalName()+" "+content);
}
// For debugging: ReadContext -> Integer.
// private static Map stackdepth = Collections.synchronizedMap(new HashMap());
/**
* Handle the start element.
* @param readcontext The context for reading with all necessary information.
*/
protected void handleStartElement(AReadContext readcontext) throws Exception
{
IXMLReader parser = readcontext.getParser();
if(readcontext.getReadIgnore()>0)
{
readcontext.setReadIgnore(readcontext.getReadIgnore()+1);
if(DEBUG)
System.out.println("Ignoring: "+parser.getLocalName());
}
else if(readcontext.getReadIgnore()==0)
{
// List stack = readcontext.getStack();
// Fetch for info when creating attributes.
Map rawattrs = null;
int attrcnt = parser.getAttributeCount();
if(attrcnt>0)
{
rawattrs = new HashMap();
for(int i=0; i0)
{
StackElement pse = (StackElement)readcontext.getTopStackElement();
List pathname = new ArrayList();
pathname.add(localname);
for(int i=readcontext.getStackSize()-2; i>=0 && pse.getObject()==null; i--)
{
pse = (StackElement)readcontext.getStackElement(i);
pathname.add(0, readcontext.getStackElement(i+1).getTag());
}
if(pse!=null)
{
TypeInfo patypeinfo = ((StackElement)pse).getTypeInfo();
SubobjectInfo linkinfo = getSubobjectInfoRead(localname, fullpath, patypeinfo,
readcontext.getTopStackElement()!=null? readcontext.getTopStackElement().getRawAttributes(): null);
if(linkinfo!=null && linkinfo.getAccessInfo().isIgnoreRead())
{
readcontext.setReadIgnore(readcontext.getReadIgnore()+1);
if(DEBUG)
System.out.println("Ignoring: "+parser.getLocalName());
}
}
}
if(readcontext.getReadIgnore()==0)
{
// Test if it is an object reference
String idref = rawattrs!=null? (String)rawattrs.get(SXML.IDREF): null;
if(idref!=null)
{
if(readcontext.getReadObjects().containsKey(idref))
{
object = readcontext.getReadObjects().get(idref);
StackElement se = new StackElement(handler, localname, object, rawattrs, typeinfo, parser.getLocation());
readcontext.addStackElement(se);
}
else
{
StackElement se = new StackElement(handler, localname, null, rawattrs, typeinfo, parser.getLocation());
readcontext.addStackElement(se);
readcontext.getReporter().report("idref not contained: "+idref, "idref error", se, se.getLocation());
}
}
else
{
// Create object.
// todo: do not call createObject on every tag?!
Object ti = typeinfo;
if(localname.getNamespaceURI().startsWith(SXML.PROTOCOL_TYPEINFO)
&& (typeinfo==null || typeinfo.isCreateFromTag()))
{
ti = localname;
}
try
{
object = handler.createObject(ti, readcontext.getStackSize()==0, readcontext, rawattrs);
}
catch(Exception e)
{
// e.printStackTrace();
readcontext.getReporter().report(e.toString(), "creation error", readcontext, parser.getLocation());
readcontext.removeStackElement(); // remove ignored element info from stack. otherwise parser would be confused.
readcontext.setReadIgnore(1);
}
if(DEBUG && object==null)
System.out.println("No mapping found: "+localname);
// Try to search type info via type (when tag contained type information)
if(typeinfo==null && object!=null)
{
typeinfo = handler.getTypeInfo(object, fullpath, readcontext);
}
// If object has internal id save it in the readobjects map.
String id = rawattrs!=null? (String)rawattrs.get(SXML.ID): null;
if(id!=null && object!=null)
{
// System.out.println("ID: "+id+", "+object.getClass());
readcontext.getReadObjects().put(id, object);
}
readcontext.addStackElement(new StackElement(handler, localname, object, rawattrs, typeinfo, parser.getLocation()));
// Handle attributes.
int atcnt = attrcnt;
if(rawattrs!=null)
{
if(rawattrs.containsKey(SXML.ID))
atcnt--;
if(rawattrs.containsKey(SXML.ARRAYLEN))
atcnt--;
Collection attrinfos = typeinfo==null? null: typeinfo.getAttributeInfos();
if(attrinfos!=null)
{
for(AttributeInfo attrinfo: attrinfos)
{
boolean contains = rawattrs.containsKey(attrinfo.getAccessInfo().getXmlObjectName().getLocalPart());
boolean ignore = attrinfo.isIgnoreRead();
if(contains && ignore)
{
atcnt--;
}
}
}
}
if(atcnt>0)
{
List attrpath = null;
// If no type use last element from stack to map attributes.
if(object==null)
{
attrpath = new ArrayList();
attrpath.add(readcontext.getTopStackElement().getTag());
for(int i=readcontext.getStackSize()-2; i>=0 && object==null; i--)
{
StackElement pse = readcontext.getStackElement(i);
attrpath.add(pse.getTag());
typeinfo = pse.getTypeInfo();
object = pse.getObject();
}
}
// Handle attributes
if(object!=null)
{
Set attrs = typeinfo==null? Collections.EMPTY_SET: typeinfo.getXMLAttributeNames();
for(int i=0; i key = new LinkedList();
key.add(attrname);
for(int j=0; attrinfo==null && j it=attrs.iterator(); it.hasNext(); )
{
Object key = it.next();
if(key instanceof QName) // ignore path entries of same attributes.
{
Object attrinfo = typeinfo.getAttributeInfo(key);
// Hack. want to read attribute info here
handler.handleAttributeValue(object, (QName)key , attrpath, null, attrinfo, readcontext);
}
}
}
else
{
StackElement se = readcontext.getTopStackElement();
readcontext.getReporter().report("No element on stack for attributes", "stack error", se, se.getLocation());
}
}
// Handle comment.
if(readcontext.getComment()!=null && typeinfo!=null)
{
Object commentinfo = typeinfo.getCommentInfo();
if(commentinfo!=null)
{
handler.handleAttributeValue(object, null, null, readcontext.getComment(), commentinfo,
readcontext);
}
}
}
}
readcontext.setComment(null);
// System.out.println("start: "+parser.getLocalName());
}
}
/**
* Handle the end element.
* @param readcontext The context for reading with all necessary information.
*/
protected void handleEndElement(final AReadContext readcontext) throws Exception
{
if(readcontext.getReadIgnore()==0)
{
IXMLReader parser = readcontext.getParser();
// List stack = readcontext.getStack();
StackElement topse = readcontext.getTopStackElement();
// System.out.println("end: "+parser.getLocalName());
// QName localname = parser.getPrefix()==null || parser.getPrefix()==XMLConstants.DEFAULT_NS_PREFIX? new QName(parser.getLocalName())
// : new QName(parser.getNamespaceURI(), parser.getLocalName(), parser.getPrefix());
jadex.xml.stax.QName localname = parser.getName();
jadex.xml.stax.QName[] fullpath = readcontext.getXMLPath();
final TypeInfo typeinfo = readcontext.getPathManager().getTypeInfo(localname, fullpath, topse.getRawAttributes());
// Hack. Change object to content when it is element of its own.
if((topse.getObject()==null && topse.getContent()!=null && topse.getContent().trim().length()>0) || topse.getObject()==STRING_MARKER)
{
// Handle possible content type conversion.
Object val = topse.getContent()!=null? topse.getContent(): topse.getObject();
if(val instanceof String)
{
if(typeinfo!=null && typeinfo.getContentInfo()!=null)
{
Object coninfo = typeinfo.getContentInfo();
if(coninfo!=null && coninfo instanceof AttributeInfo)
{
IStringObjectConverter conv = ((AttributeInfo)coninfo).getConverter();
if(conv!=null)
{
val = conv.convertString((String)val, readcontext);
}
}
}
else
{
val = topse.getReaderHandler().convertContentObject((String)val, localname, readcontext);
}
}
topse = new StackElement(topse.getReaderHandler(), topse.getTag(), val, topse.getRawAttributes(), null, topse.getLocation());
readcontext.setStackElement(topse, readcontext.getStackSize()-1);
// stack.set(stack.size()-1, topse);
// readcontext.setTopse(topse);
}
// Handle content.
if(topse.getObject()!=null && topse.getContent()!=null && topse.getContent().trim().length()>0)
{
if(typeinfo!=null && typeinfo.getContentInfo()!=null)
{
topse.getReaderHandler().handleAttributeValue(topse.getObject(), null, null, topse.getContent(), typeinfo.getContentInfo(), readcontext);
}
else
{
StackElement se = readcontext.getTopStackElement();
readcontext.getReporter().report("No content mapping for: "+topse.getContent()+" tag="+topse.getTag(), "link error", se, se.getLocation());
}
}
// Handle post-processing
final IPostProcessor[] postprocs = topse.getReaderHandler().getPostProcessors(topse.getObject(), typeinfo);
if(postprocs!=null && postprocs.length>0)
{
for(int i=0; i0 && bulklink)
{
// Invoke bulk link for the finished object (as parent).
List childs = readcontext.removeChildren(topse.getObject());
if(childs!=null)
{
IBulkObjectLinker linker = (IBulkObjectLinker)(typeinfo!=null && typeinfo.getLinker()!=null? typeinfo.getLinker(): topse.getReaderHandler());
linker.bulkLinkObjects(topse.getObject(), childs, readcontext);
}
}
if(readcontext.getStackSize()>1)
{
StackElement pse = readcontext.getStackElement(readcontext.getStackSize()-2);
ArrayList pathname = new ArrayList();
pathname.add(localname);
for(int i=readcontext.getStackSize()-3; i>=0 && pse.getObject()==null; i--)
{
pse = readcontext.getStackElement(i);
pathname.add(0, readcontext.getStackElement(i+1).getTag());
}
if(pse.getObject()!=null)
{
// System.out.println("here: "+parser.getLocalName()+" "+getXMLPath(stack)+" "+topse.getRawAttributes());
TypeInfo patypeinfo = pse.getTypeInfo();
SubobjectInfo linkinfo = getSubobjectInfoRead(localname, fullpath, patypeinfo, topse.getRawAttributes());
bulklink = patypeinfo!=null? patypeinfo.isBulkLink(): this.bulklink;
if(!bulklink)
{
IObjectLinker linker = (IObjectLinker)(patypeinfo!=null && patypeinfo.getLinker()!=null? patypeinfo.getLinker(): pse.getReaderHandler());
linker.linkObject(topse.getObject(), pse.getObject(), linkinfo==null? null: linkinfo,
pathname.toArray(new jadex.xml.stax.QName[pathname.size()]), readcontext);
// IObjectLinker linker = (IObjectLinker)(patypeinfo!=null && patypeinfo.getLinker()!=null? patypeinfo.getLinker(): null);
// boolean linked = false;
// if(linker!=null)
// {
// linked = linker.linkObject(topse.getObject(), pse.getObject(), linkinfo==null? null: linkinfo,
// pathname.toArray(new jadex.xml.stax.QName[pathname.size()]), readcontext);
// }
//
// if(!linked)
// {
// linker = pse.getReaderHandler();
// linker.linkObject(topse.getObject(), pse.getObject(), linkinfo==null? null: linkinfo,
// pathname.toArray(new jadex.xml.stax.QName[pathname.size()]), readcontext);
// }
}
else
{
// Save the finished object as child for its parent.
readcontext.addChild(pse.getObject(), new LinkData(topse.getObject(), linkinfo==null? null: linkinfo,
(jadex.xml.stax.QName[])pathname.toArray(new jadex.xml.stax.QName[pathname.size()])));
}
}
else
{
StackElement se = readcontext.getTopStackElement();
readcontext.getReporter().report("No parent object found for: "+ SUtil.arrayToString(fullpath), "link error", se, se.getLocation());
}
}
}
readcontext.removeStackElement();
}
else
{
readcontext.setReadIgnore(readcontext.getReadIgnore()-1);
}
}
protected AReadContext createReadContext(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, IXMLReader parser, XMLReporter reporter, Object callcontext, ClassLoader classloader) {
return new AReadContext(tipmanager, handler, parser, reporter, callcontext, classloader);
}
protected abstract IXMLReader createXMLReader(Reader input);
protected abstract IXMLReader createXMLReader(InputStream input);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy