package org.apache.cocoon.xml;

import org.apache.cocoon.xml.dom.DOMBuilder;
import org.apache.cocoon.xml.dom.DOMStreamer;
import org.apache.xpath.XPathAPI;
import org.apache.xpath.objects.XObject;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.Locator;
import org.xml.sax.Attributes;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;

public class AbstractDOMObject implements DOMObject {
  private Document doc = null;
  private Node docNode = null;
  private DOMBuilder domBuilder = null;
  private boolean finished = false;

  public AbstractDOMObject(){
    DocumentBuilder docBuilder = null;
    try {
      docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    }
    catch(ParserConfigurationException pce){
    }
    this.doc = docBuilder.newDocument();
    this.docNode = doc.createDocumentFragment();
    this.domBuilder = new DOMBuilder(this.docNode);
  }

  protected XObject getXObject(String XPath){
    try{
      // NodeIterator ni = XPathAPI.selectNodeIterator(document, XPath);
      XObject xobj = XPathAPI.eval(docNode, XPath);
      return(xobj);
    } 
    catch(TransformerException e){
      return(null);
    }
  }

  protected Node getNode(String XPath){
    try{
      Node node = XPathAPI.selectSingleNode(docNode, XPath);
      return(node);
    } 
    catch(TransformerException e){
      return(null);
    }
  }

  /* DOMObject */

  public boolean isFinished(){
    return(finished);
  }

  public void markFinished(){
    finished = true;
  }

  public ContentHandler getContentHandler(){
    //return(this);
    return(domBuilder);
  }
  
  public String getValue (String XPath){
    Node n = getNode(XPath);
    if(n != null){
      if(n.getNodeType() == Node.TEXT_NODE){
        return(n.getNodeValue());
      }
      else{
        /* maybe there is a binding ? */
        return(null);        
      }
    }
    else{
      return(null);
    }
  }

  public void setValue ( String XPath, String value ){
    Node n = getNode(XPath);
    if(n != null){
      if(n.getNodeType() == Node.TEXT_NODE){
        n.setNodeValue(value);
      }
     else{
        /* maybe there is a binding ? */
     }
    }
    else{
    }
  }


  /* XMLFragment */
  public void toDOM(Node node)
    throws Exception
  {
    if(isFinished())
      node.appendChild(docNode);
  }

  public void toSAX(ContentHandler handler)
    throws SAXException
  {
    if(isFinished()){
      DOMObjectOutputWrapper wrapper = new DOMObjectOutputWrapper(handler);
      DOMStreamer streamer = new DOMStreamer(wrapper);
      streamer.stream(this.docNode);
    }
  }

  /* XMLConsumer */
  /*
  public void setDocumentLocator(Locator locator){
  }

  public void startDocument()
    throws SAXException {
  }

  public void endDocument()
    throws SAXException
  {
  }

  public void startPrefixMapping(String prefix, String uri)
    throws SAXException
  {
  }

  public void endPrefixMapping(String prefix)
    throws SAXException
  {
  }

  public void startElement(String uri, String loc, String raw, Attributes a)
    throws SAXException
  {
  }

  public void endElement(String uri, String loc, String raw)
    throws SAXException
  {
  }

  public void characters(char ch[], int start, int len)
    throws SAXException
  {
  }

  public void ignorableWhitespace(char ch[], int start, int len)
    throws SAXException
  {
  }

  public void processingInstruction(String target, String data)
    throws SAXException {
  }

  public void skippedEntity(String name)
    throws SAXException {
  }

  public void startDTD(String name, String publicId, String systemId)
    throws SAXException {
  }

  public void endDTD()
    throws SAXException {
  }

  public void startEntity(String name)
    throws SAXException {
  }

  public void endEntity(String name)
    throws SAXException {
  }

  public void startCDATA()
    throws SAXException {
  }

  public void endCDATA()
    throws SAXException {
  }

  public void comment(char ch[], int start, int len)
    throws SAXException {
  }
  */
}
