/**
 * Copyright @ 2000 Peter Roßbach (pr@webapp.de) and Lars Röwekamp (Lars@openKnowlege.de)
 *
 * Source is only for non commercialand coaching usage.
 *
 * Not Warranty to use it.
 */

package de.ix.jspTutorial.xml;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;

import org.xml.sax.SAXException;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

// vendor specific classes - not needed when using DocumentBuilder
// and DocumnetBuilderFactory ... !
import org.apache.xerces.parsers.DOMParser;

import de.ix.jspTutorial.constants.*;
import de.ix.jspTutorial.model.Order;

public class XMLOrderBuilder implements XMLConstants {



  public XMLOrderBuilder( ){

  }


  /**
   * Build a new DOM containing all important
   * information of a given order
   *
   * @param order order, to be represented
   * @return new DOM document
   */
  public Document createXMLOrder(Order order) {

    Document document = null;

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    try {

      DocumentBuilder builder = factory.newDocumentBuilder();
      document = builder.newDocument();

      // document.getDOMImplementation oder ähnlich
      // add DocType info

      // add root element
      Element root = (Element) document.createElement(XML_ROOT_TAG);
      document.appendChild(root);

      // add order tag
      Element orderElement = order.generateXML(document);
      root.appendChild(orderElement);

    } catch (ParserConfigurationException pce) {

      // Parser with specified options can't be built
      pce.printStackTrace();
    }

    return document;

  }




   /**
    * create XML output string
    *
    * @param node     xml node
    * @param prefix   prefix for formatted output
    *
    */
   public String generateXMLString(Node node, String prefix) {

    StringBuffer infoStr = new StringBuffer();

    switch (node.getNodeType()) {

      case Node.DOCUMENT_NODE:

          infoStr.append("<?xml-version=\"1.0\"?>\n");

          NodeList firstLevelNodes = node.getChildNodes();
          if (firstLevelNodes != null) {
            for (int i=0; i < firstLevelNodes.getLength(); i++) {
              infoStr.append(generateXMLString(firstLevelNodes.item(i), ""));
            }
          }
        break;

      case Node.ELEMENT_NODE:
          String name = node.getNodeName();
          infoStr.append(prefix + "<"+name);
          NamedNodeMap attributes = node.getAttributes();
          if (attributes != null) {
            for (int i=0; i<attributes.getLength(); i++) {
              Node current = attributes.item(i);
              infoStr.append(" "    + current.getNodeName()   +
                               "=\""  + current.getNodeValue()  +
                               "\"" );
            }
          }
          infoStr.append(">\n");

          // recurse child subtree
          NodeList children = node.getChildNodes();
          if (children != null) {
            for (int i=0; i<children.getLength(); i++) {
              infoStr.append(generateXMLString(children.item(i), prefix + "    "));
            }
          }
          infoStr.append(prefix + "</"+name+">\n");
        break;


      case Node.TEXT_NODE:
      case Node.CDATA_SECTION_NODE:
          infoStr.append(prefix + node.getNodeValue().trim()+"\n");
        break;

      case Node.PROCESSING_INSTRUCTION_NODE:
          infoStr.append("<?" + node.getNodeName()  +
                         " "  + node.getNodeValue() +
                         "?>\n");
        break;

      case Node.ENTITY_REFERENCE_NODE:
          infoStr.append("&" + node.getNodeName()+"\n");
        break;

      case Node.DOCUMENT_TYPE_NODE:
          DocumentType docType = (DocumentType)node;
          infoStr.append("<!DOCTYPE " + docType.getName());

          if (docType.getPublicId() != null) {
            infoStr.append(" PUBLIC \"" +
                               docType.getPublicId() +
                               "\" ");
          } else {
            infoStr.append(" SYSTEM ");
          }
          infoStr.append("\"" + docType.getSystemId() + "\">\n");
        break;

    }

    return infoStr.toString();

   }



  /**
    * create output for a XML node
    *
    * @param node     xml node
    * @param prefix   prefix for formatted output
    *
    */
  public void writeOut(Node node, String prefix) {

    switch (node.getNodeType()) {

      case Node.DOCUMENT_NODE:

          System.out.println("<?xml-version=\"1.0\"?>\n");

          NodeList firstLevelNodes = node.getChildNodes();
          if (firstLevelNodes != null) {
            for (int i=0; i < firstLevelNodes.getLength(); i++) {
              writeOut(firstLevelNodes.item(i), "");
            }
          }
        break;

      case Node.ELEMENT_NODE:
          String name = node.getNodeName();
          System.out.print(prefix + "<"+name);
          NamedNodeMap attributes = node.getAttributes();
          if (attributes != null) {
            for (int i=0; i<attributes.getLength(); i++) {
              Node current = attributes.item(i);
              System.out.print(" "    + current.getNodeName()   +
                               "=\""  + current.getNodeValue()  +
                               "\"" );
            }
          }
          System.out.println(">");

          // recurse child subtree
          NodeList children = node.getChildNodes();
          if (children != null) {
            for (int i=0; i<children.getLength(); i++) {
              writeOut(children.item(i), prefix + "    ");
            }
          }
          System.out.println(prefix + "</"+name+">");
        break;


      case Node.TEXT_NODE:
      case Node.CDATA_SECTION_NODE:
          System.out.println(prefix + node.getNodeValue().trim());
        break;

      case Node.PROCESSING_INSTRUCTION_NODE:
          System.out.println("<?" + node.getNodeName()  +
                             " "  + node.getNodeValue() +
                             "?>");
        break;

      case Node.ENTITY_REFERENCE_NODE:
          System.out.println("&" + node.getNodeName());
        break;

      case Node.DOCUMENT_TYPE_NODE:
          DocumentType docType = (DocumentType)node;
          System.out.print("<!DOCTYPE " + docType.getName());

          if (docType.getPublicId() != null) {
            System.out.print(" PUBLIC \"" +
                               docType.getPublicId() +
                               "\" ");
          } else {
            System.out.print(" SYSTEM ");
          }
          System.out.println("\"" + docType.getSystemId() + "\">");
        break;

    }

  }



}

