package org.seasar.framework.container.factory;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.util.SAXParserFactoryUtil;
import org.seasar.framework.xml.SaxHandler;
import org.seasar.framework.xml.SaxHandlerParser;
import org.seasar.framework.xml.TagHandlerContext;

/**
 * @author higa
 *
 */
public final class XmlS2ContainerBuilder implements S2ContainerBuilder {

	public static final String PUBLIC_ID = "-//SEASAR//DTD S2Container//EN";
	public static final String PUBLIC_ID21 = "-//SEASAR2.1//DTD S2Container//EN";
	public static final String DTD_PATH =
		"org/seasar/framework/container/factory/components.dtd";
	public static final String DTD_PATH21 =
		"org/seasar/framework/container/factory/components21.dtd";
	private static S2ContainerTagHandlerRule rule_ =
		new S2ContainerTagHandlerRule();

	public S2Container build(String path, ClassLoader classLoader) {
		S2Container container = null;
		ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
		try {
			if (classLoader != null) {
				Thread.currentThread().setContextClassLoader(classLoader);
			}
			container = build(path);
		} finally {
			Thread.currentThread().setContextClassLoader(oldLoader);
		}
		return container;
	}

	public S2Container build(String path) {
		SaxHandlerParser parser = createSaxHandlerParser(null, path);
		return (S2Container) parser.parse(path);
	}
	
	public S2Container include(S2Container parent, String path) {
		SaxHandlerParser parser = createSaxHandlerParser(parent, path);
		S2Container child = (S2Container) parser.parse(path);
		parent.include(child);
		return child;
	}
	
	private SaxHandlerParser createSaxHandlerParser(S2Container parent, String path) {
		SAXParserFactory factory = SAXParserFactoryUtil.newInstance();
		factory.setValidating(true);
		SAXParser saxParser = SAXParserFactoryUtil.newSAXParser(factory);
		SaxHandler handler = new SaxHandler(rule_);
		TagHandlerContext ctx = handler.getTagHandlerContext(); 
		ctx.addParameter("parent", parent);
		ctx.addParameter("path", path);
		handler.registerDtdPath(PUBLIC_ID, DTD_PATH);
		handler.registerDtdPath(PUBLIC_ID21, DTD_PATH21);
		return new SaxHandlerParser(handler, saxParser);
	}
}
