package examples.xml.biztalk;

import org.w3c.dom.*;
import java.io.*;
import java.util.*;

/**
 * A generic builder of Biztalk documents. Implements examples.xml.biztalk.OutgoingMessage.
 *
 * @author Copyright (c) 2000 by BEA Systems, Inc. All Rights Reserved.
 */
public class DOMOutgoingMessage implements OutgoingMessage {
  private String type;
  private String space;
  private String toAddress;
  private String toReferenceID;
  private String toProcess;
  private String toHandle;
  private String fromAddress;
  private String fromReferenceID;
  private String fromProcess;
  private String fromHandle;
  private String msgID;
  private String msgSubject;
  private String docName;
  private String docDesc;
  private String body;
  private String timeStamp;
  private StringBuffer doc;
  // constructor

  public DOMOutgoingMessage() {
  }

  public String getType(){return type;}

  public String getNameSpace(){return space;}

  public String getFromAddress(){return fromAddress;}

  public String getFromReferenceID(){return fromReferenceID;}

  public String getFromProcess(){return fromProcess;}

  public String getFromHandle(){return fromHandle;}

  public String getToAddress(){return toAddress;}

  public String getToReferenceID(){return toReferenceID;}

  public String getToProcess(){return toProcess;}

  public String getToHandle(){return toHandle;}

  public String getBodyAsXML(){return body;}

  public String getDocName(){return docName;}

  public String getDocDesc(){return docDesc;}

  public String getMsgID(){return msgID;}
     
  public String getMsgSubject(){return msgSubject;}

  public String getTimeStamp() {return timeStamp;}

  public void setType(String docType){type = docType;}

  public void setNameSpace(){
    space = "\"urn:schemas-biztalk-org/biztalk_1.xml\"";
  }

  public void setFromAddress(String addr){fromAddress = addr;}

  public void setFromReferenceID(String id){fromReferenceID = id;}

  public void setFromProcess(String process){fromProcess = process;}

  public void setFromHandle(String handle){fromHandle = handle;}

  public void setToAddress(String path){toAddress = path;}

  public void setToReferenceID(String id){toReferenceID = id;}

  public void setToProcess(String process){toProcess = process;}

  public void setToHandle(String handle){toHandle = handle;}

  public void setBodyAsXML(String docBody){body = docBody;}

  public void setDocName(String doc){docName = doc;}

  public void setDocDesc(String desc){docDesc = desc;}

  public void setMsgID(String msgid){msgID = msgid;}
     
  public void setMsgSubject(String subj){msgSubject = subj;}

  public void setTimeStamp() {
    GregorianCalendar cal = new GregorianCalendar();
    timeStamp = new String (
           cal.get(Calendar.YEAR)+
	   "-"+
           (cal.get(Calendar.MONTH)+1)+
           "-"+
           cal.get(Calendar.DAY_OF_MONTH)+
	   "T"+
           cal.get(Calendar.HOUR_OF_DAY)+
	   ":"+
           cal.get(Calendar.MINUTE)+
	   ":"+
           cal.get(Calendar.SECOND)+
	   "+"+
           (cal.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
  }
  public String toString() {
    String newline = "\n";
    StringBuffer xml = new StringBuffer();
    xml.append("<?xml version='1.0'?>"+newline);
    xml.append("<biztalk_1 xmlns="+getNameSpace()+">"+newline);
    xml.append(" <header>"+newline);
    xml.append("  <delivery>"+newline);
    xml.append("   <message>"+newline);
    xml.append("    <messageID>"+getMsgID()+"</messageID>"+newline);
    xml.append("    <sent>"+getTimeStamp()+"</sent>"+newline);
    xml.append("    <subject>"+getMsgSubject()+"</subject>"+newline);
    xml.append("   </message>"+newline);
    xml.append("   <to>"+newline);
    xml.append("    <address>"+getToAddress()+"</address>"+newline);
    xml.append("    <state>"+newline);
    xml.append("     <referenceID>"+getToReferenceID()+"</referenceID>"+newline);
    xml.append("     <process>"+getToProcess()+"</process>"+newline);
    xml.append("     <handle>"+getToHandle()+"</handle>"+newline);
    xml.append("    </state>"+newline);
    xml.append("   </to>"+newline);
    xml.append("   <from>"+newline);
    xml.append("    <address>"+getFromAddress()+"</address>"+newline);
    xml.append("    <state>"+newline);
    xml.append("     <referenceID>"+getFromReferenceID()+"</referenceID>"+newline);
    xml.append("     <process>"+getFromProcess()+"</process>"+newline);
    xml.append("     <handle>"+getFromHandle()+"</handle>"+newline);
    xml.append("    </state>"+newline);
    xml.append("   </from>"+newline);
    xml.append("  </delivery>"+newline);
    xml.append("  <manifest>"+newline);
    xml.append("   <document>"+newline);
    xml.append("    <name>"+getDocName()+"</name>"+newline);
    xml.append("    <description>"+getDocDesc()+"</description>"+newline);
    xml.append("   </document>"+newline);
    xml.append("  </manifest>"+newline);
    xml.append(" </header>"+newline);
    xml.append(" <body>"+newline);
    xml.append(getBodyAsXML()+newline);
    xml.append(" </body>"+newline);
    xml.append("</biztalk_1>");
    return xml.toString();
  }


  public void setBodyAsObject(Object obj) {
  //
  // convert obj into XML fragment and place in body field.
  // This implementation requires that obj be a DOM Node object.
  //
    doc = new StringBuffer();
    doNode((Node)obj);
    body = doc.toString();
  }

  private void doNode(Node node) {
    short nt = node.getNodeType();
    switch (nt) {
      case Node.ELEMENT_NODE: doElement((Element) node); break;
      case Node.ATTRIBUTE_NODE: doAttr((Attr) node); break;
      case Node.TEXT_NODE: doText((Text) node); break;
      case Node.CDATA_SECTION_NODE: doCdata((CDATASection)node); break;
      case Node.ENTITY_REFERENCE_NODE: doEntityRef((EntityReference) node); break;
      case Node.ENTITY_NODE: doEntity((Entity) node); break;
      case Node.PROCESSING_INSTRUCTION_NODE: doPI((ProcessingInstruction) node); break;
      case Node.COMMENT_NODE: doComment((Comment) node); break;
      case Node.DOCUMENT_NODE: doDocument((Document) node); break;
      case Node.DOCUMENT_FRAGMENT_NODE: doDocFrag((DocumentFragment) node); break;
      case Node.NOTATION_NODE: doNotation((Notation) node); break;
      default: doError(node); break;
    }
    doc.append("\n"); // put in some line breaks after each element
    //
    // recurse thru children
    //
    NodeList nl = node.getChildNodes();
    int items = nl.getLength();
    for (int i=0; i<items; i++) {
      doNode((Node)nl.item(i));
    }
    //
    // add end markup
    //
    if (nt == Node.ELEMENT_NODE) {
      doc.append("</"+node.getNodeName()+">");
    }
  }


  private void doElement(Element node){
    doc.append("<"+node.getNodeName());
    NamedNodeMap nm = node.getAttributes();
    if (nm != null) {
      doc.append(" ");
      int items = nm.getLength();
      for (int i=0; i<items; i++) {
        doNode((Node)nm.item(i));
      }
    }
  }

  private void doAttr(Attr node) {
    doc.append(node.getNodeName()+"=\""+node.getNodeValue()+"\" ");
  }

  private void doText(Text node) {
    doc.append(node.getNodeValue());
  }

  private void doCdata(CDATASection node) {
    doc.append("<![CDATA["+node.getNodeValue()+"]]>");
  }

  private void doEntityRef(EntityReference node) {
    doc.append("&"+node.getNodeValue()+";");
  }

  private void doEntity(Entity node) {
    doc.append("<!ENTITY "+node.getNodeName()+">");
  }

  private void doPI(ProcessingInstruction node) {
    doc.append("<? "+node.getNodeName()+" "+node.getNodeValue()+"?>");
  }

  private void doComment(Comment node) {
  }

  private void doDocument(Document node) {
    doc.append("<?xml version=\'1.0\'?>\n");
  }

  private void doDocFrag(DocumentFragment node) {
  }

  private void doNotation(Notation node) {
    doc.append("<!NOTATION "+node.getNodeName()+" ");
    doc.append(node.getSystemId());
    doc.append(node.getPublicId());
    doc.append(" >");
  }

  private void doError(Node node) {
  }
}
