package eu.dnetlib.contract.spring.beans;

import java.security.InvalidParameterException;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import eu.dnetlib.contract.runner.InvokerData;
import eu.dnetlib.contract.spring.beans.factory.ComplexObjectFactoryBean;


/**
 * {@link InvokerData} bean definition parser.
 * @author mhorst
 *
 */
public class ComplexObjectBeanDefinitionParser extends AbstractBeanDefinitionParser {

	public static final String XML_FILE_LOC_ATTR_NAME	= "xmlFileLoc";
	
	public static final String XML_CONTENT_ELEMENT_NAME	= "xml-content";
	public static final String XML_CONTENT_PROP_NAME	= "xmlContent";
	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
	 */
	@Override
	protected AbstractBeanDefinition parseInternal(Element element,
			ParserContext parserContext) {
		BeanDefinitionBuilder factory = BeanDefinitionBuilder
				.rootBeanDefinition(ComplexObjectFactoryBean.class);
		
//		handles xml file location
		String xmlFileLocAttr = element.getAttribute(XML_FILE_LOC_ATTR_NAME);
		if (AbstractCheckPointBeanDefinitionParser.isAttributeSet(xmlFileLocAttr)) {
			factory.addPropertyValue(XML_FILE_LOC_ATTR_NAME, xmlFileLocAttr);
		}
		
//		handles xml file content
		Element xmlContentElement = DomUtils.getChildElementByTagName(element,XML_CONTENT_ELEMENT_NAME);
		if (xmlContentElement!=null) {
			factory.addPropertyValue(XML_CONTENT_PROP_NAME, 
					getXMLObjectRepresentation(xmlContentElement));
		}
		return factory.getBeanDefinition();

	}

	/**
	 * Returns CDATA content of xmlContentElement
	 * @param xmlContentElement
	 * @return CDATA content of xmlContentElement
	 */
	protected String getXMLObjectRepresentation(Element xmlContentElement) {
		NodeList children = xmlContentElement.getChildNodes();
		for (int i=0; i<children.getLength(); i++) {
			if (children.item(i) instanceof CDATASection) {
				CDATASection cdataSection = (CDATASection) children.item(i);
				return cdataSection.getData();
			}
		}
		throw new InvalidParameterException("couldn't find required CDATA section in element " + 
				xmlContentElement.getLocalName());
	}
	

}


