package eu.dnetlib.springutils.template;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

/**
 * instantiate a bean template defined with &lt;template:define />
 * 
 * Parameters can be passed with:
 * 
 * <pre>
 * 	&lt;template:instance name=&quot;testTemplate&quot; t:beanName=&quot;test&quot; /&gt;
 * </pre>
 * 
 * or with:
 * 
 * <pre>
 * &lt;template:instance name=&quot;testTemplate&quot;&gt;
 * 	 &lt;template:parameter name=&quot;beanName&quot; value=&quot;test&quot;/&gt;
 * 	&lt;/template:instance&gt;
 * </pre>
 * 
 * TODO: you can also pass bean references with "value-ref", "t:somename-ref" or inner bean declaration inside the
 * template:parameter element.
 * 
 * @author marko
 * 
 */
public class TemplateInstanceDefinitionParser implements BeanDefinitionParser {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(TemplateInstanceDefinitionParser.class); // NOPMD by marko on 11/24/08 5:02 PM

	/**
	 * template dao. Allows to find template definitions.
	 */
	private BeanTemplateDao templateDao;

	/**
	 * construct a template instance definition parser.
	 * 
	 * @param templateDao
	 *            template dao instance
	 */
	public TemplateInstanceDefinitionParser(BeanTemplateDao templateDao) {
		super();
		this.templateDao = templateDao;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element,
	 *      org.springframework.beans.factory.xml.ParserContext)
	 */
	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		TemplateInstance instance = new TemplateInstance(element, parserContext);
		
		final String templateName = instance.getTemplateName();
		log.debug("parsing tempate INSTANCE: " + templateName);
		
		BeanTemplate template = templateDao.getTemplate(templateName);
		log.debug("found template: " + template);
		
		if (template == null)
			stageInstance(instance);
		else
			instance.instantiate(template);

		return null;
	}

	/**
	 * put this instance expansion in a staging queue, so that when the associated template definition
	 * will be processed we can resume the instantiation. 
	 * 
	 * @param element
	 * @param parserContext
	 */
	private void stageInstance(TemplateInstance instance) {
		templateDao.registerTemplateInstance(instance);
	}

	

}
