package com.ericsson.ims.mtas.xdms.common.binder;

import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventLocator;
import javax.xml.bind.util.ValidationEventCollector;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import com.ericsson.ims.mtas.xdms.common.namespace.CustomNameSpacePrefixMapper;

public abstract class GenericBinder implements IGenericBinder
{
	public static Logger logger = LoggerFactory.getLogger(GenericBinder.class);

	protected JAXBContext context = null;

	protected Marshaller marshaller;

	protected Unmarshaller unMarshaller = null;

	protected SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);

	protected Schema schema = null;

	protected Source[] sources =
	{
			new StreamSource(GenericBinder.class.getResource("/xsd/cai3g1.2.xsd").getFile()),
			new StreamSource(GenericBinder.class.getResource("/xsd/common-types.xsd").getFile()),
			new StreamSource(GenericBinder.class.getResource("/xsd/mtas-common-types.xsd").getFile()),
			new StreamSource(GenericBinder.class.getResource("/xsd/communication-diversion.xsd").getFile()),
			new StreamSource(GenericBinder.class.getResource("/xsd/mmtel-aggregated-service.xsd").getFile())
	};

	protected String instance = "com.ericsson.ims.mtas.xdms.schema.cai3g:"
			+ "com.ericsson.ims.mtas.xdms.schema.mtas.common.types:"
			+ "com.ericsson.ims.mtas.xdms.schema.communication.diversion:";

	protected ValidationEventCollector vec = new ValidationEventCollector();

	protected CustomNameSpacePrefixMapper customNameSpace = new CustomNameSpacePrefixMapper();

	public GenericBinder(String[] preDefinedNameSpace)
	{
		customNameSpace.setPreDeclaredNamespaceUris(preDefinedNameSpace);

		try
		{
			schema = schemaFactory.newSchema(sources);
			context = JAXBContext.newInstance(instance);
			unMarshaller = context.createUnmarshaller();
			unMarshaller.setSchema(schema);
			unMarshaller.setEventHandler(vec);

			marshaller = context.createMarshaller();
			marshaller.setSchema(schema);
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

			marshaller.setEventHandler(vec);
			marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", customNameSpace);
		}
		catch (JAXBException e)
		{
			logger.error("Error while creating unmarshaller  . . . " + e.getMessage());
		}
		catch (SAXException e)
		{
			logger.error("Error while creating schema factory  . . . " + e.getMessage());
		}
	}

	public StreamSource getStream(String name)
	{
		return new StreamSource(getClass().getResource(name).getFile());
	}

	public void checkValidation()
	{
		ValidationEventLocator validationEventLocator;

		if (vec.hasEvents())
		{
			for (ValidationEvent e : vec.getEvents())
			{
				validationEventLocator = e.getLocator();

				switch (e.getSeverity())
				{
					case 0: // warning
						logger.warn(e.getMessage() + " at line " + validationEventLocator.getLineNumber() + " column "
								+ validationEventLocator.getColumnNumber());
						break;
					case 1: // error
						logger.error(e.getMessage() + " at line " + validationEventLocator.getLineNumber() + " column "
								+ validationEventLocator.getColumnNumber());
						break;
					case 2: // Fatal error
						logger.error(e.getMessage() + " at line " + validationEventLocator.getLineNumber() + " column "
								+ validationEventLocator.getColumnNumber());
						break;
				}
			}
		}
	}
}
