// copyright => http://www.jxml.com/mdsax/License.txt

package com.jxml.quick.engine;

import com.jxml.quick.*;
import com.jxml.quick.access.*;
import com.jxml.quick.tf.*;
import java.net.*;
import java.io.IOException;
import org.xml.sax.SAXException;

public class QHRef extends HRef
	implements PostParse, QMeta
{
	QAccess access;
	Object parent;
	QTargetFactory parentFactory;
	int reserved;

	public static String completeURL(String base, String partial)
		throws MalformedURLException
	{
/*
		URL myURL=new URL(base);
		URL complete=new URL(myURL,partial);
		String v=complete.toString();
		if (!v.startsWith("classpath:/"))
			return v;
		if (v.startsWith("classpath:///"))
			return v;
		return "classpath:///"+v.substring(11);
*/
		if (partial.startsWith("#"))
			return base+partial;
		return partial;
	}

	public QHRef()
	{
	}

	public QHRef(String schema, String href, String expects)
	{
		super(schema,href,expects);
	}

	public QHRef(String schema, String href, String expects, String schemaClass)
	{
		super(schema,href,expects,schemaClass);
	}

	public void postParse(QContext context)
		throws QPE
	{
		try
		{
			QDoc myDoc=context.doc;
			String myKey=myDoc.getKey();
			QDoc mySchemaDoc=myDoc.getSchema();
			Object val=null;
			if (mySchemaDoc==null && schema.length()==0)
			{
				String v=completeURL(myKey,href);
				int i=v.indexOf("#");
				QDoc doc=null;
				if (i==-1)
				{
					doc=Quick.parseSchema(v);
					val=doc.getRoot();
				}
				else
				{
					doc=Quick.parseSchema(v.substring(0,i));
					String id=v.substring(i+1);
					val=doc.getValue(id);
					if (val==null)
						context.throwPE("Unknown ID: "+v);
				}
			}
			else if (mySchemaDoc==null)
			{
				//String s=completeURL(mySchemaDoc.getKey(),schema);
				//QDoc schemaDoc=Quick.parseSchema(schema);
				QDoc schemaDoc=QSchemaFactory.create(schemaClass,schema);
				String v=completeURL(myKey,href);
				int i=v.indexOf("#");
				QDoc doc=null;
				if (i==-1)
				{
					doc=Quick.uniqueParse(schemaDoc,v);
					val=doc.getRoot();
				}
				else
				{
					doc=Quick.uniqueParse(schemaDoc,v.substring(0,i));
					String id=v.substring(i+1);
					val=doc.getValue(id);
					if (val==null)
						context.throwPE("Unknown ID: "+v);
				}
			}
			else if (schema.length()==0)
			{
				System.err.println("mySchemaDoc="+mySchemaDoc);
				System.err.println("expects="+expects);
				context.throwPE("schema missing for href: "+href);
			}
			else
			{
				String s=completeURL(mySchemaDoc.getKey(),schema);
				//QDoc schemaDoc=Quick.parseSchema(s);
				QDoc schemaDoc=QSchemaFactory.create(schemaClass,s);
				String myURL=null;
				if (myKey==null)
					myURL=mySchemaDoc.getKey();
				else
					myURL=myKey;
				String v=completeURL(myURL,href);
				int i=v.indexOf("#");
				QDoc doc=null;
				if (i==-1)
				{
					doc=Quick.uniqueParse(schemaDoc,v);
					val=doc.getRoot();
				}
				else
				{
					doc=Quick.uniqueParse(schemaDoc,v.substring(0,i));
					String id=v.substring(i+1);
					val=doc.getValue(id);
					if (val==null)
						context.throwPE("Unknown ID: "+v);
				}
			}
			if (!Class.forName(expects).isAssignableFrom(val.getClass()))
				context.throwPE("Expecting "+expects+" at "+href);
			myDoc.setMeta(val,this);
			access.set(reserved,parent,parentFactory,val,context);
		}
		catch (MalformedURLException e)
		{
			context.throwPE(e);
		}
		catch (IOException e)
		{
			context.throwPE(e);
		}
		catch (ClassNotFoundException e)
		{
			context.throwPE(e);
		}
		catch (SAXException e)
		{
			context.throwPE(e);
		}
		catch (InstantiationException e)
		{
			context.throwPE(e);
		}
		catch (IllegalAccessException e)
		{
			context.throwPE(e);
		}
	}

	public void add(QAccess access,
		        Object parent,
		        QTargetFactory parentFactory,
		        QContext context)
		throws QPE
		{
			if (access==null || !access.writeable(parentFactory,context))
				context.throwPE("href requires write access");
			if (parent==null)
				context.throwPE("href may not be root");
			QDocImpl doc=(QDocImpl)context.doc;
			doc.addPostParse(this);
			this.access=access;
			this.parent=parent;
			this.parentFactory=parentFactory;
			reserved=access.reserve(parentFactory,parent,context);		//1.1.5
		}
}
