/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	共通XML読み込みクラス
//			変更履歴
//				2004.01.08	新規作成	中村　愛
//

package jp.co.ntt.lms.xmo.util;

import java.io.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;


/**
 * 共通XML読み込みクラス
 * <PRE>
 * 処理内容：XMLファイルをパースする。
 *	要素の値を取得する。
 *	子要素のデータを取得する。
 *	子要素に移動する。
 *	親要素に移動する。
 * </PRE>
 */

public class XMLReader
{

	//////////////////////////////////////////////////////////
	//	クラス変数
	//////////////////////////////////////////////////////////

	/** XMLドキュメント */
	private	Document mDoc = null;

	/** ルートエレメント */
	private Element mRootElement = null;

	/** 現在操作中ノード */
	private Node mCurrentNode = null;

	/** 操作対象ファイル */
	private InputStreamReader mFr = null;

	/**
	*	コンストラクタ<br>
	*	XMLファイルをパースしてインスタンスを生成します。
	*	@param strFilePath XMLファイルの絶対パス
	*/
	public XMLReader(String strFilePath)
		throws FileNotFoundException,SAXException,IOException
	{
		parse(strFilePath);
	}


	/**
	 *	XMLファイルをパースします。
	 *	パースが正常終了した場合は、ルートエレメントをカレントエレメント
	 *	として設定します。
	 *	@param strFilePath XMLファイルの絶対パス
	 */

	private void parse(String strFilePath)
		throws FileNotFoundException,SAXException,IOException
	{
		//パーサのインスタンスを生成する
		DOMParser parser = new DOMParser();

		//XMLファイルを読み込む
		FileInputStream objStream = new FileInputStream( strFilePath );
		mFr = new InputStreamReader(objStream,"Windows-31J");

		//ストリームを生成する
		InputSource is = new InputSource(mFr);

		//パースする
		parser.parse(is);

		//ドキュメントを取得する
		mDoc = parser.getDocument();

		//ドキュメントが取得できた時、
		//ルートエレメントをカレントエレメントに設定する
		if(mDoc != null) {
			Element elementRoot = mDoc.getDocumentElement();
			mRootElement = elementRoot;
			mRootElement.normalize();
			mCurrentNode = mRootElement;
		}

	}


	/**
	 *	子エレメントのデータを取得します。<br>
	 *	子エレメント配下のエレメントのデータは取得できません。<br>
	 *	取得したい場合はエレメントの移動を行います。
	 *
	 *	@param strElementName	子エレメント名
	 *	@param iElemIndex	エレメント位置
	 *	@return 取得したエレメントのデータ<br>
	 *					存在しない時空文字列を返す。
	 */

	public String getChildElementData(String strElementName,int iElementIndex)
	{

		Node ndChild = null;			// 子ノード格納 
		String strEleData = null;		// エレメントデータ格納 
		
		ndChild = getChildNode(strElementName,iElementIndex);
		if(ndChild != null)
		{
			// ノードデータ取得 
			try
			{

				Node ndFirstChild = ndChild.getFirstChild();
				strEleData = "";

				if(ndFirstChild != null)
				{

					strEleData = ndFirstChild.getNodeValue();

				}
			}
			catch(DOMException derr)
			{

				strEleData = "";
				
			}
			
		}
		else		// 指定されたタグが存在しない時
		{

			strEleData = "";

		}

		return strEleData;
	}


	/**
	 *	子エレメントへ移動します。<br>
	 *	@param elementName 移動するエレメント名<br>
	 *	@param elementIndex エレメントの位置<br>
	 *	@return エレメント移動処理正常終了時trueを,異常発生時falseを返す<br>
	 *	
	 */

	public boolean moveChildElement(String elementName,int elementIndex)
	{
		//処理結果
		boolean bResult = false;

		if (mCurrentNode != null)
		{

			// エレメント名
			String strMoveEleName = elementName;

			/* 子エレメント取得 */
			Node ndChild= getChildNode(strMoveEleName,elementIndex);

			if(ndChild != null)
			{
				/* カレントノードの設定 */
				mCurrentNode = ndChild;
				bResult = true;

			}
			else
			{

				bResult = false;

			}
		}
		return bResult;
	}


	/**
	 *	親エレメントへ移動します。<br>
	 *	@return エレメント移動処理正常終了時trueを,異常発生時falseを返す<br>
	 *	
	 */

	public boolean moveParentElement()
	{
		boolean bResult = false;

		if(mCurrentNode != null)
		{
			// 親エレメント
			Node ndParent = null;
			
			// 親ノード取得
			ndParent = mCurrentNode.getParentNode();

			// 親ノードが存在する時 
			if(ndParent != null)
			{
				// 親ノードがエレメントだった場合
				if(ndParent.getNodeType() == Node.ELEMENT_NODE)
				{
					// カレントノードを設定する
					mCurrentNode = ndParent;
					bResult =  true;
				}
				else			// 親ノードがエレメントノード以外の場合
				{
					bResult = false;
				}
			}
			else				// 親ノードが存在しない時
			{
				bResult = false;
			}
		}

		return bResult;
	}




	/**
	 *	子エレメントを検索します。<br>
	 *	@param childElementName 検索するエレメント名<br>
	 *	@return 取得したノード。ノードを取得できなかった場合はnullが返る。
	 *	
	 */

	private Node getChildNode (String strChildEleName, int elementIndex)
	{
		String strEleName = new String();		// エレメント名格納
		int intChildCnt = 0;					// 子ノード数格納
		Node ndChild = null;					// 子ノード格納 
		int iTargetChild = 0;					// ターゲットエレメント数
		
		// 子ノードリスト取得 
		NodeList ndlstChild = mCurrentNode.getChildNodes();
		if (ndlstChild != null) {
			// 子ノード数取得
			intChildCnt = ndlstChild.getLength();

			// 子ノード数分エレメント名をチェックする
			for(int cnt = 0 ; cnt < intChildCnt ; cnt++)
			{
				ndChild = ndlstChild.item(cnt);

				// 取得したノードがエレメント
				if(ndChild.getNodeType() == Node.ELEMENT_NODE)
				{
					// エレメント名取得 
					strEleName = ndChild.getNodeName();

					// 取得した子エレメント名と引数が等しい時 
					if(strEleName.equals(strChildEleName))
					{

						// 指定されたインデックスと同じ位置の子要素の場合 
						if(iTargetChild == elementIndex)
						{
							break;
						}
						else
						{
							ndChild = null;
							iTargetChild++;
						}
					}
					else
					{
						ndChild = null;
					}
				}
				else
				{
					ndChild = null;

				}
			}
		}
		
		return ndChild;
	}


}


