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

jadex.xml.writer.Writer Maven / Gradle / Ivy

package jadex.xml.writer;

import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;

import jadex.commons.collection.Tree;
import jadex.commons.collection.TreeNode;
import jadex.xml.IPreProcessor;
import jadex.xml.SXML;
import jadex.xml.StackElement;
import jadex.xml.TypeInfo;
import jadex.xml.stax.QName;

/**
 *  XML writer for conversion of objects to XML.
 */
public class Writer extends AWriter
{
	//-------- static part --------
	
	
	/** The xml output factory. */
	protected static final XMLOutputFactory	FACTORY = XMLOutputFactory.newInstance();
//	factory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
	
	//-------- attributes --------
	
	/** Control flag for generating ids. */
	protected boolean genids;	
	
	/** Control flag for generating indention. */
	protected boolean indent;
	
	/** Control flag for generating newlines. */
	protected boolean newline;
	
	//-------- constructors --------

	/**
	 *  Create a new reader (with genids=true and indent=true).
	 *  @param readerhandler The handler.
	 */
	public Writer()
	{
		this(true);
	}
	
	/**
	 *  Create a new reader (with genids=true and indent=true).
	 *  @param readerhandler The handler.
	 */
	public Writer(boolean genids)
	{
		this(genids, true, true);
	}
	
	/**
	 *  Create a new reader.
	 *  @param readerhandler The handler.
	 */
	public Writer(boolean genids, boolean indent, boolean newline)
	{
		this.genids = genids;
		this.indent = indent;
		this.newline = newline;
	}
	
	//-------- methods --------
	
	/**
	 *  Write the properties to an xml.
	 *  @param input The input stream.
	 *  @param classloader The classloader.
	 * 	@param context The context.
 	 */
	public void write(IObjectWriterHandler handler, Object object, OutputStream out, ClassLoader classloader, final Object context) throws Exception
	{
		write(handler, object, SXML.DEFAULT_ENCODING, out, classloader, context);
	}
		
	/**
	 *  Write the properties to an xml.
	 *  @param input The input stream.
	 *  @param classloader The classloader.
	 * 	@param context The context.
 	 */
	public void write(IObjectWriterHandler handler, Object object, String encoding, OutputStream out, ClassLoader classloader, final Object context) throws Exception
	{
		XMLStreamWriter	writer;
		synchronized(FACTORY)
		{
			writer	= FACTORY.createXMLStreamWriter(out, encoding);
		}
		
		if(encoding!=null)
			writer.writeStartDocument(encoding, "1.0"); 
		writeNewline(writer);
		
		WriteContextDesktop wc = new WriteContextDesktop(handler, writer, context, object, classloader);
		writeObject(wc, object, null);
		writer.writeEndDocument();
		writer.close();
	}
	
	/**
	 *  Write an object to xml.
	 *  
	 *  Note:
	 *  Must have tag parameter to support writing an object using an arbitrary tag.
	 *  Cannot write tag in beforehand, because it must be written in one pass. 
	 */
	protected void writeObject(WriteContextDesktop wc, Object object, QName tag) throws Exception
	{
		XMLStreamWriter writer = getWriter(wc);
		List stack = wc.getStack();
		
		// Special case null
		if(object==null)
		{
//			writeStartObject(writer, tag==null? SXML.NULL: tag, stack.size());
			writeStartObject(writer, SXML.NULL, stack.size());
			writeEndObject(writer, stack.size());
			return;
		}
		
//		if(tagname!=null)
//			System.out.println("tagname: "+tagname);
//		if(object.getClass().getName().indexOf("ComponentIdentifier")!=-1)
//			System.out.println("cfs");
		
		TypeInfo typeinfo = wc.getHandler().getTypeInfo(object, getXMLPath(stack), wc); 
		QName[] path = new QName[0];
		
		// Preprocess object.
		IPreProcessor[] preprocs = wc.getHandler().getPreProcessors(object, typeinfo);
		if(preprocs!=null && preprocs.length>0)
		{
//			System.out.println("found: "+object);
			for(int i=0; i attrs = wi.getAttributes();
			if(attrs!=null)
			{
				for(Iterator it=attrs.keySet().iterator(); it.hasNext(); )
				{
					Object propname = it.next();
					String value = (String)attrs.get(propname);
					if(propname instanceof String)
					{
						writer.writeAttribute((String)propname, value);
					}
					else if(propname instanceof QName)
					{
						QName attrname = (QName)propname;
						// Create tag with prefix if it has a namespace but no prefix.
						if(!XMLConstants.NULL_NS_URI.equals(attrname.getNamespaceURI()) && XMLConstants.DEFAULT_NS_PREFIX.equals(attrname.getPrefix()))
						{
							attrname = wc.getHandler().getTagWithPrefix(tag, wc);
						}
						String uri = attrname.getNamespaceURI();
						String prefix = attrname.getPrefix();
						String localname = attrname.getLocalPart();
						
						if(!XMLConstants.NULL_NS_URI.equals(uri))
						{
							if(!prefix.equals(writer.getPrefix(uri)))
							{
								writer.writeAttribute(prefix, uri, localname, value);
								writer.writeNamespace(prefix, uri);
							}
							else
							{
								writer.writeAttribute(prefix, uri, localname, value);
							}
						}
						else
						{
							writer.writeAttribute(localname, value);
						}
						
						//		System.out.println("name"+tag.getLocalPart()+" prefix:"+prefix+" writerprefix:"+writer.getPrefix(uri)+" uri:"+uri);
					}
				}
			}
			
			// Content
			
			if(wi.getContent()!=null)
			{
				String content = wi.getContent();
				if(content!=null)
				{
					// Uses cdata when contains <, > or &
					// Must not use cdata when content is already cdata (nested cdata are not allowed)
					if((content.indexOf("<")!=-1 || content.indexOf(">")!=-1 || content.indexOf("&")!=-1)
						&& content.indexOf(" stack = wc.getStack();
			
		List children = node.getChildren();
		for(int i=0; i stack)
	{
		QName[] ret = new QName[stack.size()];
		for(int i=0; i