package pl.qumak.xml;

import com.google.common.collect.Maps;
import org.springframework.core.io.Resource;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.xml.transform.StringSource;
import org.xml.sax.SAXException;
import pl.qumak.exception.InvalidSchemaException;
import pl.qumak.exception.XmlParseException;


import javax.xml.bind.UnmarshalException;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import java.util.Map;

public class MarshallerBase extends Jaxb2Marshaller {

    public MarshallerBase(String[] jaxbContextPath) {
        this(jaxbContextPath, null);
    }

    private MarshallerBase(String[] jaxbContextPath, Resource[] schemaResources) {
        setContextPaths(jaxbContextPath);
        Map<String, String> map = Maps.newHashMap();
        map.put("jaxb.encoding", "UTF-8");
        setMarshallerProperties(map);
        if (schemaResources != null && schemaResources.length > 0) {
            setSchemas(schemaResources);
            setValidationEventHandler(new DefaultValidationEventHandler());
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T unmarshal(String xml) {
        StringSource source = new StringSource(xml);
        try {
            return (T) unmarshal(source);
        } catch (UnmarshallingFailureException e) {
            UnmarshalException unmarshalException = (UnmarshalException) e.getCause();
            if (unmarshalException.getLinkedException() instanceof SAXException) {
                throw new XmlParseException("Error while parsing xml:" + xml);
            } else {
                throw new InvalidSchemaException("Given XML doesn't match schema xml" + xml);
            }
        }
    }
}
