/***
 *** Title: ResponseInfo.java
 *** Author: Itsuki Noda
 *** Date: 2006.08.18
 ***/

package daruma.wfs;

import java.util.Date;
import java.io.PrintWriter;

import daruma.util.Pair;
import daruma.util.ISO8601DateFormat;

import daruma.xml.util.ElementUtil;
import daruma.xml.Lexicon;
import daruma.xml.NameSpace;
import daruma.xml.DeclaredName;
import daruma.xml.util.DOMDocumentFactory;
import daruma.xml.Lexicon;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.Node;

import javax.xml.transform.TransformerException;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

/**
 * MISP のレスポンスを生成するための情報コンテナ
 */

public class ResponseInfo {

    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    public Document document ;

    public Element header ;
    public Element body ;
    public Node leaf ;

    public boolean headerIsOutputedP ;
    public String headerStr ;
    public String tailerStr ;

    //------------------------------------------------------------
    public ResponseInfo(boolean soapP) 
	throws SAXException
    {
	try {
	    this.document = DOMDocumentFactory.create() ;

	    this.header = null ;
	    this.body = null ;
	    this.leaf = this.document ;

	    this.headerIsOutputedP = false ;
	    this.headerStr = null ;
	    this.tailerStr = null ;

	    if(soapP) {
		setupSoapEnvelope(true) ;
	    }
	} catch(ParserConfigurationException ex) {
	    throw new SAXException( ex );
	}
    }
    
    //------------------------------------------------------------
    /**
     * SOAP Envelope をセットする。
     */
    public void setupSoapEnvelope(boolean declareStandardNS) {
	Element envelope = 
	    ElementUtil.genElementSimple(Lexicon.SoapEnvelope, null,
					 this.document, this.document, true) ;

	if(declareStandardNS) {
	    NameSpace.GML.addNsDeclToIfNeeded(envelope) ;
	    NameSpace.MISP.addNsDeclToIfNeeded(envelope) ;
	}

	Element header = 
	    ElementUtil.genElementSimple(Lexicon.SoapHeader, null,
					 this.document, envelope, true) ;
	Element body = 
	    ElementUtil.genElementSimple(Lexicon.SoapBody, null,
					 this.document, envelope, true) ;
	    
	this.header = header ;
	this.body = body ;
	this.leaf = body ;
    }

    //------------------------------------------------------------
    /**
     * document を leaf の位置で header と tailer にわける。
     */
    public void splitToHeaderTailerStr() 
	throws SAXException
    {
	try {
	    Pair<String, String> strHeaderTailer = 
		ElementUtil.splitToHeaderTailerStrAt(this.document,
						     this.leaf, true) ;
	    this.headerStr = strHeaderTailer.getFirst() ;
	    this.tailerStr = strHeaderTailer.getSecond() ;
	} catch(TransformerException ex) {
	    throw new SAXException( ex );
	}
    }

    //------------------------------------------------------------
    /**
     * document を leaf の位置で header と tailer にわける。
     */
    public void outputHeaderPart(PrintWriter ostr) 
	throws SAXException
    {
	splitToHeaderTailerStr() ;

	ostr.println(this.headerStr) ;
	this.headerIsOutputedP = true ;
    }

    //------------------------------------------------------------
    /**
     * Response 要素を leaf にセットする。
     */
    public Element setResponseToLeaf(Element response)
    {
	this.leaf = response ;
	return response ;
    }

    //------------------------------------------------------------
    /**
     * leaf に ResponseStatus を追加。
     */
    public Element addResponseStatusToLeaf(String transactionID,
					   Date bTime,
					   Date eTime)
    {
	String bTimeStr =
	    ((bTime == null) ?
	     null :
	     new ISO8601DateFormat().format(bTime)) ;
	String eTimeStr =
	    ((eTime == null) ?
	     null :
	     new ISO8601DateFormat().format(eTime)) ;

	return addResponseStatusToLeaf(transactionID, bTimeStr, eTimeStr) ;
    }

    public Element addResponseStatusToLeaf(String transactionID,
					   String bTimeStr,
					   String eTimeStr)
    {
	Element status =
	    ElementUtil.genElementSimple(Lexicon.MispResponseStatus, null,
					 this.document, this.leaf, true) ;
	// Element trans =
	    ElementUtil.genElementSimple(Lexicon.MispMostRecentTransactionID,
					 transactionID,
					 this.document, status, true) ;

	Element elapsedTime =
	    ElementUtil.genElementSimple(Lexicon.MispElapsedTime, null,
					 this.document, status, true) ;
	Element bTime =
	    ElementUtil.genElementSimple(Lexicon.GmlBeginPosition,
					 bTimeStr,
					 this.document, elapsedTime, true) ;
	if(bTimeStr == null) {
	    bTime.setAttribute(Lexicon.GmlAttrIndeterminatePositon.localname,
			       Lexicon.GmlAttrIndeterminatePositon_Unknown
			       .localname) ;
	}

	Element eTime = 
	    ElementUtil.genElementSimple(Lexicon.GmlEndPosition, 
					 eTimeStr, 
					 this.document, elapsedTime, true) ;
	if(eTimeStr == null) {
	    eTime.setAttribute(Lexicon.GmlAttrIndeterminatePositon.localname,
			       Lexicon.GmlAttrIndeterminatePositon_Unknown
			       .localname) ;
	}

	return status ;
    }
	
}

