/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package de.christofreichardt.jaxws.securitypriceservice;

import de.christofreichardt.diagnosis.AbstractTracer;
import de.christofreichardt.diagnosis.LogLevel;
import de.christofreichardt.diagnosis.Traceable;
import java.io.OutputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;

/**
 *
 * @author Christof Reichardt
 */
abstract public class AbstractXMLSerializer implements Traceable {
  private final DOMImplementationRegistry domImplRegistry;
  private final LSOutput lsOutput;
  private final LSSerializer serializer;
  
//  private final Transformer transformer;

  protected AbstractXMLSerializer() {
    this.domImplRegistry = createDOMImplRegistry();
    DOMImplementationLS domImplLS = (DOMImplementationLS) this.domImplRegistry.getDOMImplementation("LS");
    if (domImplLS == null)
      throw new RuntimeException("No Load and Save DOM implementation found.");
    this.lsOutput = domImplLS.createLSOutput();
    this.serializer = domImplLS.createLSSerializer();
    
//    TransformerFactory transformerFactory = TransformerFactory.newInstance();
//    try {
//      this.transformer = transformerFactory.newTransformer();
//    }
//    catch (TransformerConfigurationException ex) {
//      throw new RuntimeException(ex);
//    }
  }

  private DOMImplementationRegistry createDOMImplRegistry() {
    AbstractTracer tracer = getCurrentTracer();
    tracer.entry("DOMImplementationRegistry", this, "createDOMImplRegistry()");
    
    try {
      try {
        return DOMImplementationRegistry.newInstance();
      }
      catch (ClassNotFoundException | InstantiationException | IllegalAccessException | ClassCastException | DOMException ex) {
        tracer.logException(LogLevel.ERROR, ex, getClass(), "createDOMImplRegistry()");
        throw new RuntimeException("Cannot create DOMImplRegistry.");
      }
    }
    finally {
      tracer.wayout();
    }
  }
  
  public void serialize(Node node, OutputStream outputStream) {
    AbstractTracer tracer = getCurrentTracer();
    tracer.entry("void", this, "serialize(Node node, OutputStream outputStream)");
    
    try {
      this.lsOutput.setByteStream(outputStream);
      this.serializer.write(node, this.lsOutput);
      
//      try {
//        this.transformer.transform(new DOMSource(node), new StreamResult(outputStream));        
//      }
//      catch (TransformerException ex) {
//        tracer.logException(LogLevel.ERROR, ex, getClass(), "void serialize(Node node, OutputStream outputStream)");
//        throw new RuntimeException(ex);
//      }
    }
    finally {
      tracer.wayout();
    }
  }
}
