All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.xml.reader.PullParserReader Maven / Gradle / Ivy

Go to download

This Project includes the a variant of the Jadex XML Parser using the Android XML Pull API.

The newest version!
package jadex.xml.reader;

import jadex.commons.SUtil;
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.QName;
import jadex.xml.stax.XMLReporter;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.XMLConstants;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

public class PullParserReader extends AReader
{

	private XmlPullParserFactory factory;
	private XMLReporter reporter;
	private boolean bulklink;

	public PullParserReader()
	{
		this(false, null, false);
	}

	public PullParserReader(boolean validate, XMLReporter reporter, boolean bulklink)
	{
		this(validate, false, reporter, bulklink);
	}

	public PullParserReader(boolean validate, boolean coalescing, XMLReporter reporter, boolean bulklink)
	{
		try
		{
			factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(true);
			factory.setValidating(validate);
			this.reporter = reporter;
			this.bulklink = bulklink;
		} catch (XmlPullParserException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, InputStream input, ClassLoader classloader,
			Object callcontext) throws Exception
	{
		return read(tipmanager, handler, new InputStreamReader(input, SXML.DEFAULT_ENCODING), classloader, callcontext);
	}

	@Override
	public Object read(TypeInfoPathManager tipmanager, IObjectReaderHandler handler, Reader input, ClassLoader classloader,
			Object callcontext) throws Exception
	{
		XmlPullParser parser = factory.newPullParser();
//		BufferedReader bufferedReader = new BufferedReader(input);
//		String line;
//		while (bufferedReader.ready()) {
//			 line = bufferedReader.readLine();
//			 System.out.println(line);
//		}
//		
//		input.reset();
		
		parser.setInput(input);
		ReadContextAndroid readcontext = new ReadContextAndroid(tipmanager, handler, parser, reporter, callcontext, classloader);
		READ_CONTEXT.set(readcontext);
		try
		{
			int type = 0;
			while (type != XmlPullParser.END_DOCUMENT)
			{
				type = parser.nextToken();
				switch (type)
				{
					case XmlPullParser.CDSECT :
						// StaX: CDATA
					case XmlPullParser.TEXT :
						// StaX: CHARACTERS
						handleContent(readcontext);
						break;
					case XmlPullParser.COMMENT :
						// StaX: COMMENT
						handleComment(readcontext);
						break;
					case XmlPullParser.START_TAG :
						// StaX: START_ELEMENT
						handleStartTag(readcontext);
						break;
					case XmlPullParser.END_TAG :
						// StaX: END_ELEMENT
						handleEndTag(readcontext);
						break;

					case XmlPullParser.DOCDECL :
						// StaX: DTD
					case XmlPullParser.ENTITY_REF :
						// StaX: ENTITY_REFERENCE
						// workaround: Android Pull Parser handles %amp; as reference.
						char[] textCharacters = readcontext.getParser().getTextCharacters(new int[2]);
						if ("amp".equals(readcontext.getParser().getName())) {
							handleContent(readcontext);
						}
					case XmlPullParser.IGNORABLE_WHITESPACE :
						// StaX: SPACE
					case XmlPullParser.PROCESSING_INSTRUCTION :
						// StaX: PROCESSING_INSTRUCTION
					case XmlPullParser.START_DOCUMENT :
						// StaX: START_DOCUMENT

					default :
						break;
				}
			}
			for (int i = 1; readcontext.getPostProcessors().size() > 0; i++)
			{
				List ps = (List) readcontext.getPostProcessors().remove(new Integer(i));
				if (ps != null)
				{
					for (int j = 0; j < ps.size(); j++)
					{
						((IPostProcessorCall) ps.get(j)).callPostProcessor();
					}
				}
				// System.out.println("i: "+i);
			}
		} catch (RuntimeException e)
		{
			jadex.xml.stax.ILocation loc = readcontext.getStackSize() > 0 ? readcontext.getTopStackElement().getLocation() : readcontext
					.getLocation();
			readcontext.getReporter().report(e.toString(), "XML error", readcontext, loc);
		} finally
		{
			READ_CONTEXT.set(null);
		}

		return readcontext.getRootObject()==NULL ? null : readcontext.getRootObject();
	}

	private void handleContent(ReadContextAndroid readcontext)
	{
		if (readcontext.getReadIgnore() == 0)
			readcontext.getTopStackElement().addContent(readcontext.getParser().getText());
		else if (DEBUG)
			System.out.println("Ignoring: " + readcontext.getParser().getText());
	}

	private void handleComment(ReadContextAndroid readcontext)
	{
		if (readcontext.getReadIgnore() == 0)
			readcontext.setComment(readcontext.getParser().getText());
		else if (DEBUG)
			System.out.println("Ignoring: " + readcontext.getParser().getText());
	}

	private void handleStartTag(ReadContextAndroid readcontext) throws Exception
	{
		XmlPullParser parser = readcontext.getParser();

		if (readcontext.getReadIgnore() > 0)
		{
			readcontext.setReadIgnore(readcontext.getReadIgnore() + 1);
			if (DEBUG)
				System.out.println("Ignoring: " + parser.getName());
		} 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; i < attrcnt; i++)
				{
					String attrname = parser.getAttributeName(i);
					String attrval = parser.getAttributeValue(i);

					rawattrs.put(attrname, attrval);
				}
			}

			Object object = null;

			// System.out.println("here: "+parser.getPrefix()+" "+parser.getNamespaceURI()+" "+parser.getName()+" "+parser.getName());
			QName localname = new QName(parser.getNamespace(), parser.getName(), parser.getPrefix());

			// QName localname = parser.getPrefix()==null ||
			// parser.getPrefix()==XMLConstants.DEFAULT_NS_PREFIX? new
			// QName(parser.getName())
			// : new QName(parser.getNamespaceURI(), parser.getName(),
			// parser.getPrefix());

			jadex.xml.stax.QName[] fullpath = readcontext.getXMLPath(localname);

			// Get type info and corresponding handler.
			TypeInfo typeinfo = readcontext.getPathManager().getTypeInfo(localname, fullpath, rawattrs);
			IObjectReaderHandler handler = typeinfo != null ? typeinfo.getReaderHandler() : null;
			if (handler == null)
			{
				if (readcontext.getTopStackElement() != null && readcontext.getTopStackElement().getReaderHandler() != null)
				{
					handler = readcontext.getTopStackElement().getReaderHandler();
				} else if (readcontext.getDefaultHandler() != null)
				{
					handler = readcontext.getDefaultHandler();
				} else
				{
					readcontext.getReporter().report("No handler for element: " + localname, "type info error", readcontext,
							readcontext.getLocation());
				}
			}

			// Find out if we need to ignore.
			if (readcontext.getStackSize() > 0)
			{
				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.getName());
					}
				}
			}

			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, readcontext.getLocation());
						readcontext.addStackElement(se);
					} else
					{
						StackElement se = new StackElement(handler, localname, null, rawattrs, typeinfo, readcontext.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, readcontext.getLocation());
					}

					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, readcontext.getLocation()));

					// Handle attributes.
					int atcnt = attrcnt;
					if (rawattrs != null)
					{
						if (rawattrs.containsKey(SXML.ID))
							atcnt--;
						if (rawattrs.containsKey(SXML.ARRAYLEN))
							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 < parser.getAttributeCount(); i++)
							{
								QName attrname = parser.getAttributePrefix(i) == null
										|| parser.getAttributePrefix(i) == XMLConstants.DEFAULT_NS_PREFIX ? new QName(
										parser.getAttributeName(i)) : new QName(parser.getAttributeNamespace(i),
										parser.getAttributeName(i), parser.getAttributePrefix(i));

								// System.out.println("here: "+attrname);

								if (!SXML.ID.equals(attrname.getLocalPart()) && !SXML.ARRAYLEN.equals(attrname.getLocalPart()))
								{
									String attrval = parser.getAttributeValue(i);
									attrs.remove(attrname);

									Object attrinfo = typeinfo != null ? typeinfo.getAttributeInfo(attrname) : null;
									if (!(attrinfo instanceof AttributeInfo && ((AttributeInfo) attrinfo).isIgnoreRead()))
									{
										// ITypeConverter attrconverter =
										// typeinfo!=null ?
										// typeinfo.getAttributeConverter(attrname)
										// : null;
										// Object val = attrconverter!=null?
										// attrconverter.convertObject(attrval,
										// root, classloader): attrval;

										handler.handleAttributeValue(object, attrname, attrpath, attrval, attrinfo, readcontext);

										if (attrinfo instanceof AttributeInfo
												&& AttributeInfo.ID.equals(((AttributeInfo) attrinfo).getId()))
										{
											// System.out.println("ID: "+attrval+", "+object);
											readcontext.getReadObjects().put(attrval, object);
										}
									}
								}
							}
							// Handle unset attributes (possibly have default
							// value).
							for (Iterator it = attrs.iterator(); it.hasNext();)
							{
								QName attrname = (QName) it.next();
								Object attrinfo = typeinfo.getAttributeInfo(attrname);

								// Hack. want to read attribute info here
								handler.handleAttributeValue(object, attrname, 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.getName());
		}
	}

	private void handleEndTag(final ReadContextAndroid readcontext) throws Exception
	{
		if(readcontext.getReadIgnore()==0)
		{
			XmlPullParser 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 = new QName(parser.getNamespace(), parser.getName(), parser.getPrefix());
			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);
						}
						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);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy