package com.jxml.quick.ocm; // Open Conversion Model
import com.jxml.quick.*;
import org.xml.sax.*;
import java.io.*;
import java.util.*;
import com.jxml.protocol.*;

/**
 * A base class for the operating context.
<pre>
DTD:

&lt;!ELEMENT contextSupport (<a href="OCMsinkSupport.html#source">((contextSupport | transcribe | input) | sourceLink)</a>,(<a href="OCMsinkSupport.html#validator">(validatorSupport | validateLink)</a>?,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=#factory>((factory | factoryByTag)|factoryLink)</a>)>

&lt;!ATTLIST contextSupport
&nbsp;&nbsp;&nbsp;&nbsp;<a href="OCMsinkSupport.html#prefix">docNamePrefix </a>CDATA #IMPLIED
&nbsp;&nbsp;&nbsp;&nbsp;<a href="OCMsinkSupport.html#expressDefaults">expressDefaults</a> CDATA "False"
&nbsp;&nbsp;&nbsp;&nbsp;ID CDATA #IMPLIED
&nbsp;&nbsp;&nbsp;&nbsp;<a href=#schemaName>outputSchema</a> CDATA #IMPLIED
>
</pre>
 */
public class OCMcontextSupport extends OCMsinkSupport implements OCMsource
{
	/**
	 * The schema name for the output.
	 */
	public String schemaName="";

	/**
	 * The peer factory.
	 */
	public OCMpeerFactory factory=null;

	public String SYSTEM="";
	public String PUBLIC="";
	public String rootTag="";

	// implements an OCMbase method
	public OCMbase.SubBase spawn(HashMap prior)
	{
		OCMbase.SubBase rv=(OCMbase.SubBase)prior.get(this);
		if (rv!=null)
			return rv;
		OCMbase.SubBase base=new SubContextSupport(prior);
		prior.put(this,base);
		return base;
	}

	public class SubContextSupport extends OCMsinkSupport.SubSinkSupport implements OCMcontext, OCMsource.SubSource
	{
		/**
		 * Generally useful for non-xml output.
		 */
		public StringBuffer sb=null;

		/**
		 * The peer of the root data model object.
		 */
		public OCMrootPeer rootPeer=null;

		/**
		 * A map of peers.
		 */
		public HashMap peers=null;

		/**
		 * The output document.
		 */
		public QDoc outputDoc=null;

		/**
		 * The destination for SAX events.
		 * Used for peer initialization when the root peer extends QConverterSupport
		 */
		public DocumentHandler destination=null;

		public Object dataModelRoot;


		public StringBuffer getStringBuffer()
		{
			return sb;
		}

		public void setStringBuffer(StringBuffer sb)
		{
			this.sb=sb;
		}

		public SubContextSupport(HashMap prior)
		{
			super(prior);
		}

		// implements SubSource method
		public QDoc getSchemaDoc()
			throws SAXException, IOException
		{
			if ("".equals(schemaName))
				return null;
			return Quick.parseSchema(schemaName);
		}

		// Implement OCMcontext method.
		public DocumentHandler getDestination()
		{
			return destination;
		}

		// Implement OCMcontext method.
		public void setDestination(DocumentHandler destination)
		{
			this.destination=destination;
		}

		// Implement OCMcontext method.
		public OCMpeer peer(Object dataModel, OCMpeer parent)
			throws SAXException, IOException
		{
			if (dataModel==null)
				return null;
	
			OCMpeer peer=(OCMpeer)peers.get(dataModel);
			if (peer!=null)
				return peer;
	
			peer=factory.createPeer(dataModel,this,parent);
			if (peer==null)
				return null;
	
			peers.put(dataModel,peer);
			return peer;
		}

		public OCMpeer rootPeer()
			throws SAXException, IOException
		{
			return rootPeer;
		}

		public Object dataModelRoot(QDoc inputDoc)
		{
			return inputDoc.getRoot();
		}

		// Overrides OCMsinkSupport method.
		public QDoc getInputDoc()
			throws SAXException, IOException
		{
			QDoc rv=super.getInputDoc();
			peers=new HashMap();
			dataModelRoot=dataModelRoot(rv);
			Object rp=peer(dataModelRoot,null);
			if (rp==null || !(rp instanceof OCMrootPeer))
			{
				System.err.println("This class is : "+getClass().getName());
				System.err.println("Schema name : "+schemaName);
				System.err.println("Prefix is : "+prefix);
				if (rp!=null)
					System.err.println("root peer is not a root peer: "+rp.getClass().getName());
				else if (!(dataModelRoot instanceof OCMelement))
					System.err.println("dataModelRoot has no peer: "+dataModelRoot.getClass().getName());
				if (dataModelRoot instanceof OCMelement)
				{
					OCMelement el=(OCMelement)dataModelRoot;
					String name=el.getQName();
					if (!"".equals(name))
					{
						throw new OCMinvalidRootException(name);
					}
				}
				throw new OCMinvalidRootException("");
			}
			rootPeer=(OCMrootPeer)peer(dataModelRoot,null);
			return rv;
		}

		// Implement OCMsource method.
		public QDoc getDoc()
			throws SAXException, IOException
		{
			if (outputDoc!=null)
				return outputDoc;
			getInputDoc();
			if ("".equals(docName))
				outputDoc=rootPeer.convert();
			else
				outputDoc=rootPeer.convert(docName);
			return outputDoc;
		}

		// Implement OCMcontext method.
		public String express()
			throws SAXException, IOException
		{
			if ("".equals(schemaName))
			{
				getInputDoc();
				return rootPeer.express(expressDefaults);
			}
			else
				return Quick.express(getDoc(),expressDefaults);
		}

		// Implement OCMcontext method.
		public void express(PrintWriter pw)
			throws SAXException, IOException
		{
			if ("".equals(schemaName))
			{
				getInputDoc();
				rootPeer.express(pw,expressDefaults);
			}
			else
				Quick.express(getDoc(),pw,expressDefaults);
		}

		public String getPUBLIC()
		{
			return PUBLIC;
		}

		public String getSYSTEM()
		{
			return SYSTEM;
		}

		public String getRootTag()
		{
			return rootTag;
		}

		public ClassLoader getClassLoader()
		{
			return cl;
		}

		public void setClassLoader(ClassLoader cl)
		{
			this.cl=cl;
		}
	}
}
