
package de.ivu.elect.jee.exchange;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;


import static java.util.Collections.emptyMap;

public class XmlMarshaller<T> {

  private static final JAXBUtil jaxbUtil = new JAXBUtil();

  public XmlMarshaller() {
    super();
  }

  public void serialize(T jaxbElement, OutputStream os) throws JAXBException {
    serialize(jaxbElement, os, emptyMap());
  }

  public void serialize(T jaxbElement, OutputStream os, Map<String, Object> marshallerProperties) throws JAXBException {
    jaxbUtil.marshal(jaxbElement, os, marshallerProperties);
  }

  public void serialize(JAXBElement<T> jaxbElementWrapped, T jaxbElement, OutputStream os) throws JAXBException {
    serialize(jaxbElementWrapped, jaxbElement, os, emptyMap());
  }

  public void serialize(JAXBElement<T> jaxbElementWrapped, T jaxbElement, OutputStream os, Map<String, Object> marshallerProperties) throws JAXBException {
    jaxbUtil.marshal(jaxbElementWrapped, jaxbElement, os, marshallerProperties);
  }

  public T deserialize(Class<T> clazz, InputStream is) throws JAXBException {
    return deserialize(clazz, is, emptyMap());
  }

  public T deserialize(Class<T> clazz, InputStream is, Map<String, Object> unmarshallerProperties) throws JAXBException {
    try {
      return jaxbUtil.unmarshal(clazz, is, unmarshallerProperties);
    } catch (ParserConfigurationException | SAXException e) {
      throw new RuntimeException(e.getMessage(), e);
    }
  }

  // ELECT-9722 XML-Validierung völlig sinnfrei (fachliche Valdierung erfolgt später) => raus
//  public Violations validate(InputStream is, File xmlSchemaLocation, Class< ? > contentClass) {
//    return validate(is, xmlSchemaLocation, contentClass, emptyMap());
//  }
//
//  public Violations validate(InputStream is, File xmlSchemaLocation, Class< ? > contentClass, Map<String, Object> unmarshallerProperties) {
//    XmlViolationCollector violationCollector = new XmlViolationCollector();
//    violationCollector.setSchemaLocation(xmlSchemaLocation);
//
//    Schema schema = loadXmlSchema(xmlSchemaLocation);
//
//    return getViolations(is, contentClass, violationCollector, schema, unmarshallerProperties);
//  }
//
//  public Violations validate(InputStream is, URL xmlSchemaLocation, Class< ? > contentClass) {
//    return validate(is, xmlSchemaLocation, contentClass, emptyMap());
//  }
//
//  public Violations validate(InputStream is, URL xmlSchemaLocation, Class< ? > contentClass, Map<String, Object> unmarshallerProperties) {
//    XmlViolationCollector violationCollector = new XmlViolationCollector();
//    violationCollector.setSchemaLocation(xmlSchemaLocation);
//
//    Schema schema = loadXmlSchema(xmlSchemaLocation);
//
//    return getViolations(is, contentClass, violationCollector, schema, unmarshallerProperties);
//  }
//
//  private Violations getViolations(InputStream is, Class< ? > contentClass, XmlViolationCollector violationCollector, Schema schema, Map<String, Object> unmarshallerProperties) {
//    Throwable error = null;
//
//    try {
//      jaxbUtil.validateAndUnmarshal(contentClass, is, schema, violationCollector, unmarshallerProperties);
//    } catch (JAXBException unmarshallingOrValidationFailed) {
//      // Dieser Fehler ist wahrscheinlich auf ein Validierungsproblem zurückzuführen.
//      // Derartige Probleme werden im validationCollector aufgezeichnet.
//    } catch (SAXException | ParserConfigurationException e) {
//      error = e;
//    }
//
//    Violations result = violationCollector.getViolations();
//
//    if (error != null) {
//      result.addError("validation.xml.error", error.getLocalizedMessage());
//    }
//
//    return result;
//  }
//
//  private Schema loadXmlSchema(File schemaFile) {
//    try {
//      return getSchemaFactory().newSchema(schemaFile);
//    } catch (SAXException logged) {
//      throw new RuntimeException("Das konfigurierte XML-Schema \"" + schemaFile + "\" konnte nicht geladen werden.", logged);
//    }
//  }
//
//  private Schema loadXmlSchema(URL schemaFile) {
//    try {
//      return getSchemaFactory().newSchema(schemaFile);
//    } catch (SAXException logged) {
//      throw new RuntimeException("Das konfigurierte XML-Schema \"" + schemaFile.toExternalForm() + "\" konnte nicht geladen werden.", logged);
//    }
//  }
//
//  private SchemaFactory getSchemaFactory() throws SAXNotRecognizedException, SAXNotSupportedException {
//    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//    // funktioniert nicht bei Validierung  schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // ELECT-5566
//    // funktioniert nicht bei Validierung schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // ELECT-5566
//
//    return schemaFactory;
//  }
}
