package com.thaiopensource.validate.schematron;

import com.thaiopensource.resolver.Resolver;
import com.thaiopensource.resolver.xml.transform.Transform;
import com.thaiopensource.util.PropertyMap;
import com.thaiopensource.validate.ResolverFactory;
import com.thaiopensource.validate.ValidateProperty;
import com.thaiopensource.validate.Validator;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.ErrorHandler;

import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;

class ValidatorImpl implements Validator {
  private final Templates templates;
  private final SAXTransformerFactory factory;
  private final ContentHandler outputHandler;
  private TransformerHandler transformerHandler;
  private final Resolver resolver;

  ValidatorImpl(Templates templates, SAXTransformerFactory factory, PropertyMap properties) {
    this.templates = templates;
    this.factory = factory;
    ErrorHandler eh = properties.get(ValidateProperty.ERROR_HANDLER);
    outputHandler = new OutputHandler(eh);
    resolver = ResolverFactory.createResolver(properties).getResolver();
    initTransformerHandler();
  }

  public ContentHandler getContentHandler() {
    return transformerHandler;
  }

  public DTDHandler getDTDHandler() {
    return transformerHandler;
  }

  public void reset() {
    initTransformerHandler();
  }

  private void initTransformerHandler() {
    try {
      transformerHandler = factory.newTransformerHandler(templates);
      // When you specify a URIResolver, XSLTC uses a DOMCache, which
      // doesn't seem to work too well.
      if (!SchemaReaderImpl.isXsltc(factory.getClass()))
        transformerHandler.getTransformer().setURIResolver(Transform.createSAXURIResolver(resolver));
      // XXX set up transformer with an ErrorListener that just throws
      // XXX (what about errors from document() calls?)
    }
    catch (TransformerConfigurationException e) {
      throw new RuntimeException("could not create transformer");
    }
    transformerHandler.setResult(new SAXResult(outputHandler));
  }
}
