/*
 * Webブラウザから、サーバのXMLドキュメントにアクセスするための、
 * JavaScriptライブラリ。
 *   ・W3C DOM Level 3 Load and Save Specification
 *   ・W3C DOM Level 3 XPath Specification
 *   ・XML Path Language
 * 等を、Webブラウザの違いを越えて、何とか使えるようにする。
 * 但し、現時点(2005/02/05)で、W3CのLoad and Saveをサポートしている
 * Webブラウザは、少なくとも一般に流通しているものはありません。
 * そこで、IEをMozillaが共にサポートしている、XHMHTTPという機能を
 * 利用することにします。
 * この方法のメリットは、元々IEがサポートしていた機能を、Mozillaが
 * 同じインターフェイスで実装したものなので、同じAPIが利用できる
 * と言う点です。
 * デメリットは、そもそもMicrosoftが定義したインターフェイスなので、
 * 今後他のWebブラウザで利用できるようになる可能性が、極めて低いこと
 * でしょうか。
 *
 * ちなみに、W3CのLoad and Saveでは、以下のようなコーディングになります。
 *---------------------------------------------------------------------------*
 * var SYNC_LOAD  = 1;
 * var ASYNC_LOAD = 2;
 *
 * var parser = document.implementation.createLSParser(SYNC_LOAD, null);
 * var loadedDoc = parser.parseURI("http://www.xxxx.com/");
 *
 * var parser = document.implementation.createLSParser(ASYNC_LOAD, null);
 * parser.addEventListener("load", listener, false);
 * var loadedDoc = parser.parseURI("http://www.xxxx.com/");
 *---------------------------------------------------------------------------*
 * こんな感じです。
 *
 * Firefox1.0以上、IE6.0以上を、ターゲットとする。
 * IE5.5の場合は、MSXML3.0以上が必須。
 *
 * このファイルの利用について
 * このファイルの内容は、個人利用・商用利用に関わらず、一部または全部を、
 * 自由に利用していただいてかまいません。
 * 但し、引用元の表示か、著作者が（有）ワイシステムクリエイトであることを
 * 示す、著作権表示を必ず行ってください。
 * また、このファイルの内容を利用した事により、何らかの不利益を被った場合
 * でも、（有）ワイシステムクリエイトは、一切保証できませんので、利用者ご
 * 自身の責任において、ご利用くださるようお願いします。
 *
 * Copyright (C) 2005 Y System Create Corporation. All Rights Reserved.
 *
 * $Date: 2005/04/30 01:35:12 $
 * $Revision: 1.3 $
 */
function getVersion_com_yscjp_XmlUtil() {
    return "$Revision: 1.1 $";
}

/**
 * XMLドキュメントの、ロードとセーブを実装。
 */
function XmlLSImplement() {

    try{FTrace.start("XmlLSImplement", arguments);

    try {
        this.httpRequest = XmlUtil.createXMLHttpRequest();
    }
    catch (e) {
        AppUtil.printExceptionLog(e);
        throw e;
    }

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
}

/**
 * URIからの、XMLドキュメント同期読み込み
 * @param uri 読み込むxmlドキュメントのURI
 *            HTTPのGETメソッドでアクセスできる対象でなければならない。
 * @return 指定のURIを読み込んだ結果のドキュメント。
 *         読み込みのエラーが発生した場合や、読み込んだデータのMIMEタイプが、
 *         xmlドキュメントにパースできない場合、nullを返す。
 *         エラーの詳細は、XmlLSImplement#resultCodeと、
 *         XmlLSImplement#resultTextを参照。
 */
XmlLSImplement.prototype.perseFromURI = function (uri) {

    try{FTrace.start("XmlLSImplement.prototype.perseFromURI", arguments);

    return this.syncHttpRequest("GET", "", uri);

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
}

/**
 * URIへの、XMLドキュメント書き込み
 * @param savedValue セーブするテキストまたはドキュメント
 * @param uri 読み込むxmlドキュメントのURI
 *            HTTPのGETメソッドでアクセスできる対象でなければならない。
 * @return 指定のURIを読み込んだ結果のドキュメント。
 *         読み込みのエラーが発生した場合や、読み込んだデータのMIMEタイプが、
 *         xmlドキュメントにパースできない場合、nullを返す。
 *         エラーの詳細は、XmlLSImplement#resultCodeと、
 *         XmlLSImplement#resultTextを参照。
 */
XmlLSImplement.prototype.writeToURI = function (savedValue, uri) {

    try{FTrace.start("XmlLSImplement.prototype.writeToURI", arguments);

    return this.syncHttpRequest("POST",
                                XmlUtil.writeToString(savedValue),
                                uri);

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
}

/**
 * httpリクエストの同期発行
 * @param method GET/POST
 * @param savedValue セーブするテキストまたはドキュメント。
 * @param uri 読み込むxmlドキュメントのURI
 *            HTTPのGETメソッドでアクセスできる対象でなければならない。
 * @return 指定のURIを読み込んだ結果のドキュメント。
 *         読み込みのエラーが発生した場合や、読み込んだデータのMIMEタイプが、
 *         xmlドキュメントにパースできない場合、nullを返す。
 *         エラーの詳細は、XmlLSImplement#resultCodeと、
 *         XmlLSImplement#resultTextを参照。
 */
XmlLSImplement.prototype.syncHttpRequest = function (method, savedValue, uri) {

    try{FTrace.start("XmlLSImplement.prototype.syncHttpRequest", arguments);

    this.resultCode = -1;
    this.resultText = "Not Send";

    try {
        this.httpRequest.open(method, uri, false);
        this.httpRequest.setRequestHeader("Content-Type", "text/xml");
//            AppUtil.printLog("savedValue(" + savedValue.xml + ")");
        this.httpRequest.send(savedValue);
        this.resultCode = this.httpRequest.status;
        this.resultText = this.httpRequest.responseText;

        if (200 != this.resultCode) {

            AppUtil.printErrorLog(this.resultCode + " : " + this.resultText);
        }
        return XmlUtil.modifyDocument(this.httpRequest.responseXML);
    }
    catch (e) {
        AppUtil.printExceptionLog(e);
        AppUtil.printErrorLog(this.resultCode + " : " + this.resultText);
    }
    return null;

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
}

/**
 * URIからの、XMLドキュメント非同期読み込み
 * @param uri 読み込むxmlドキュメントのURI
 *            HTTPのGETメソッドでアクセスできる対象でなければならない。
 * @param listener ロードイベントのリスナクラス。
 *
 * @return 指定のURIを読み込んだ結果のドキュメント。
 *         読み込みのエラーが発生した場合や、読み込んだデータのMIMEタイプが、
 *         xmlドキュメントにパースできない場合、nullを返す。
 *         エラーの詳細は、XmlLSImplement#resultCodeと、
 *         XmlLSImplement#resultTextを参照。
 */
XmlLSImplement.prototype.perseAsyncFromURI = function (uri, listener) {

    try{FTrace.start("XmlLSImplement.prototype.perseAsyncFromURI", arguments);

    var httpRequest = this.httpRequest;

    /*
     * ドキュメントのロードイベントに設定する、
     * ハンドラ関数の定義。
     * コンストラクタ内やメソッド内で関数を定義すると、
     * インスタンス毎に関数オブジェクトが作成されるので、
     * パフォーマンスの低下につながり、リソース(メモリ)も
     * 消費する。
     * このためあまりやりたくはないが、イベントハンドラに
     * インスタンスメソッドを設定できないので、
     * この場合だけは例外とする。
     * 誰か、良い方法を知っている人はいないかな？
     */
    var handler = function(evnt) {

        AppUtil.printLog("ロードされました");
        if (4 == httpRequest.readyState) {

            if (200 == httpRequest.status &&
                null != httpRequest.responseXML) {

                var xmlDoc = XmlUtil.modifyDocument(httpRequest.responseXML);
                listener.documentLoaded(xmlDoc);
            }
/*            AppUtil.printErrorLog("ERROR status:"+httpRequest.status);*/
        }
    }

    this.httpRequest.onreadystatechange = handler;

    try {

        this.httpRequest.open("GET", uri, true);
        this.httpRequest.send("");
    }
    catch(e) {

        AppUtil.printExceptionLog(e);
    }

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
}

/*
 * Webブラウザによる違いを吸収するユーティリティクラス。
 * 全てのメソッドが、クラスメソッド。
 * コンストラクタは、ダミー。
 */
function XmlUtil() {}

if (window.XMLHttpRequest && window.DOMParser) {

    /*
     * Mozillaの場合
     */
    /*
     * XMLHttpRequestのインスタンスを返す。
     */
    XmlUtil.createXMLHttpRequest = function () {

    try{FTrace.start("XmlUtil.createXMLHttpRequest", arguments);

        return new XMLHttpRequest();

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * 文字列のパース
     * @param stringValue XMLドキュメントにパースする、文字列。
     * @return パースした結果の、XMLドキュメント
     */
    XmlUtil.perseFromString = function (stringValue) {

    try{FTrace.start("XmlUtil.perseFromString", arguments);

        var parser = new DOMParser();
        return parser.parseFromString(stringValue, 'text/xml');

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * XMLドキュメントのシリアライズ(テキスト化)
     * @param node テキストに変換するXMLノード
     * @return シリアライズした文字列
     */
    XmlUtil.writeToString = function (node) {

    try{FTrace.start("XmlUtil.writeToString", arguments);

        var serializer = new XMLSerializer();
        return serializer.serializeToString(node);

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * ドキュメントに、XPathを利用できるよう設定する。
     * この処理が必要なのは、IEだけなので、
     * Mozillaではダミーのメソッド。
     */
    XmlUtil.modifyDocument = function (document) {

    try{FTrace.start("XmlUtil.modifyDocument", arguments);

        return document;

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * ドキュメントから、XPathにより、指定のノードを一つ取得する。
     */
    XmlUtil.singleNodeValue = function (xmlDoc, xPath) {

    try{FTrace.start("XmlUtil.singleNodeValue", arguments);

        var context= xmlDoc.documentElement;
        var resolver = xmlDoc.createNSResolver(xmlDoc.documentElement);
        var expression= xmlDoc.createExpression(xPath, resolver);
        var result =
            expression.evaluate(context,
                                XPathResult.FIRST_ORDERED_NODE_TYPE,
                                null);

        return result.singleNodeValue;

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }
}
else if (window.ActiveXObject) {

    /*
     * IEの場合
     */
    /*
     * XMLHttpRequestのインスタンスを返す。
     */
    XmlUtil.createXMLHttpRequest = function () {

    try{FTrace.start("XmlUtil.createXMLHttpRequest", arguments);

        return new ActiveXObject("Msxml2.XMLHTTP");

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * 文字列のパース
     * @param stringValue XMLドキュメントにパースする、文字列。
     * @return パースした結果の、XMLドキュメント
     */
    XmlUtil.perseFromString = function (stringValue) {

    try{FTrace.start("XmlUtil.perseFromString", arguments);

        newDoc = new ActiveXObject("Microsoft.XMLDOM");
        newDoc.setProperty("SelectionLanguage", "XPath");
        newDoc.loadXML(stringValue);
        return newDoc

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * XMLドキュメントのシリアライズ(テキスト化)
     * @param node テキストに変換するXMLノード
     * @return シリアライズした文字列
     */
    XmlUtil.writeToString = function (node) {

    try{FTrace.start("XmlUtil.writeToString", arguments);

        return node.xml;

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * ドキュメントに、XPathを利用できるよう設定する。
     */
    XmlUtil.modifyDocument = function (document) {

    try{FTrace.start("XmlUtil.modifyDocument", arguments);

//        document.setProperty("SelectionLanguage", "XPath");
        return document;

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }

    /*
     * ドキュメントから、XPathにより、指定のノードを一つ取得する。
     */
    XmlUtil.singleNodeValue = function (xmlDoc, xPath) {

    try{FTrace.start("XmlUtil.singleNodeValue", arguments);

        return xmlDoc.selectSingleNode(xPath);

    }catch(e){FTrace.stop();throw e;}finally{FTrace.end();}
    }
}
else {

    AppUtil.printErrorLog("XML not Supported.");
}


/*
 * テスト用サンプル
 */
function ExampleListener() {}

ExampleListener.prototype.documentLoaded = function (xmlDoc) {

    var pattern = "/body/extext[@id=\"d20050207\"]";
    var targetNode = XmlUtil.singleNodeValue(xmlDoc, pattern);
    AppUtil.printLog("読み込みました: ("+targetNode.firstChild.nodeValue+")");
//    var year = "2001";
//    var month = "01";
//    var date = "01";
//    var xPath1  = "descendant::y[attribute::year=\""+year+"\"]" +
//                 "/m[attribute::month=\""+month+"\"]" +
//                 "/d[attribute::date=\""+date+"\"]";
//    year = "2003";
//    var xPath2  = "descendant::y[attribute::year=\""+year+"\"]" +
//                 "/m[attribute::month=\""+month+"\"]" +
//                 "/d[attribute::date=\""+date+"\"]";
//    year = "2004";
//    month = "12";
//    date = "31";
//    var xPath3  = "descendant::y[attribute::year=\""+year+"\"]" +
//                 "/m[attribute::month=\""+month+"\"]" +
//                 "/d[attribute::date=\""+date+"\"]";
////    var xPath1  = "descendant::extext[attribute::date=\"20050201\"]";
////    var xPath2  = "descendant::extext[attribute::date=\"20050202\"]";
////    var xPath3  = "descendant::extext[attribute::date=\"20050208\"]";
//    AppUtil.printLog("テスト１開始");
//    var targetNode = XmlUtil.singleNodeValue(xmlDoc, xPath1);
//    AppUtil.printLog("読み込みました: ("+targetNode.firstChild.nodeValue+")");
//    AppUtil.printLog("テスト２開始");
//    targetNode = XmlUtil.singleNodeValue(xmlDoc, xPath2);
//    AppUtil.printLog("読み込みました: ("+targetNode.firstChild.nodeValue+")");
//    AppUtil.printLog("テスト３開始");
//    targetNode = XmlUtil.singleNodeValue(xmlDoc, xPath3);
//    AppUtil.printLog("読み込みました: ("+targetNode.firstChild.nodeValue+")");
}
var xmlLSImplement;
var inputEle;
function initXmlLoad() {

    AppUtil.EXECUTION = AppUtil.DEBUGLOG;
    AppUtil.applcationInit();
    xmlLSImplement = new XmlLSImplement();
    inputEle = document.getElementById("in");
}

function load() {

    AppUtil.printLog("開始！！！！");
//    var xmlLSImplement = new XmlLSImplement();
    var listener = new ExampleListener();

//    try {
        //xmlLSImplement.perseFromURI("../../cgi-bin/loadxml.cgi", listener);
        var doc = xmlLSImplement.perseFromURI("../../cgi-bin/loadxml2.cgi");
//        AppUtil.printLog(doc.getElementById(''));
        //xmlLSImplement.perseAsyncFromURI("../../cgi-bin/loadxml.cgi", listener);
        listener.documentLoaded(doc);
//    }
//    catch (e) {
//        AppUtil.printExceptionLog(e);
//        AppUtil.printLog("resultCode:"+xmlLSImplement.resultCode);
//        AppUtil.printLog("resultText:"+xmlLSImplement.resultText);
//    }
}

function save() {

    AppUtil.printLog("開始！！！！");
//    var xmlLSImplement = new XmlLSImplement();

    try {

        xmlLSImplement.writeToURI(inputEle.value, "../../cgi-bin/save.cgi");
    }
    catch (e) {
        AppUtil.printExceptionLog(e);
        AppUtil.printLog("resultCode:"+xmlLSImplement.resultCode);
        AppUtil.printLog("resultText:"+xmlLSImplement.resultText);
    }
}
