/////////////////////////////////////////////////////////////////
//Copyright (C) 2005 NTT CORPORATION.
//
//	学習履歴進捗対比表示用XML設定情報管理クラス
//
//		変更履歴
//			2005.02.03  新規作成  Katsuhiko.Sakurai(UNITEC)
//
//	機能
//
//	このクラスは学習履歴進捗対比表示用XML設定情報管理クラスです。
//
////////////////////////////////////////////////////////////////
package jp.co.ntt.lms.lo.progress.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

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

import jp.co.ntt.lms.xmo.util.DebugLog;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 学習履歴進捗対比表示用XML設定情報管理クラスです。
 * 
 * @author Katsuhiko Sakurai (UNITEC)
 * @version 1.0
 */
public class LearningProgressConfigurationManager {
	
	private HashMap loProgressConfigurationMap = null;
	private LearningStatusConfiguration learningStatusConfiguration = null;
	
	private final String FILE_PATH = "/conf/lo/progress/LearningProgress.xml";
	
	/**
	 * コンストラクタです。
	 * 
	 */
	public LearningProgressConfigurationManager() {
		this.loProgressConfigurationMap = new HashMap();
		this.learningStatusConfiguration = new LearningStatusConfiguration();
		
		try {
			// 設定ファイル読み込み
			this.loadConfiguration();
		} catch (Exception e) {
			DebugLog.write(this.getClass(), e, DebugLog.MID);
			DebugLog.write(this.getClass(), "学習履歴進捗対比表示用XML設定ファイル読み込みエラー", DebugLog.MID);
		}
	}
	
	/**
	 * LO設定情報を取得します。
	 * 
	 * @param loID 対象となるLOID
	 * @return LOConfiguraton LO設定情報
	 */
	public LOConfiguration getLOCongifuration( String loID ) {
		return (LOConfiguration)this.loProgressConfigurationMap.get(loID);
	}
	
	/**
	 * 学習状況設定情報を取得します。
	 * 
	 * @return LearningStatusConfiguration 学習状況設定情報
	 */
	public LearningStatusConfiguration getLearningStatusConfiguration() {
		return this.learningStatusConfiguration;
	}
	
	/**
	 * 外部設定ファイルを読み込みます。
	 * 
	 * @throws FileNotFoundException
	 * @throws SAXException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 */
	private void loadConfiguration() throws FileNotFoundException, SAXException, IOException, ParserConfigurationException {
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();

		DebugLog.write( this.getClass(), "進捗設定XML読み込み開始 : " , DebugLog.ROW );
		
		Node root = null;
		InputStream in = null;
		try {
			in = this.getClass().getResourceAsStream(FILE_PATH);
			// ファイルからDOMに変換
			root = builder.parse(in);
			//root = builder.parse(FILE_PATH);
		
		} finally {
			if (in != null ) in.close();
		}
		
		NodeList loNodeList = root.getFirstChild().getChildNodes();
		
		for (int i = 0; i < loNodeList.getLength(); i++) {

			//LOノードを取り出す  
			Node loNode = loNodeList.item(i);
			
			// テキストNODEの場合処理なし
			if ( loNode.getNodeType() == Node.TEXT_NODE  
					|| loNode.getNodeType() == Node.COMMENT_NODE) continue;
			
			// ■学習状況のキーワードの設定を取得
			if (loNode.getNodeName().equals("learningStatus")) {
				
				this.setLearningStatusToConfiguration(loNode, this.learningStatusConfiguration);
			
			// ■LOごとの設定値を取得
			} else if(loNode.getNodeName().equals("lo")) {
				
				// LO情報を格納するLOCongigurationを生成
				LOConfiguration loConfig = new LOConfiguration();
				
				// ●LOIDの設定
				this.setLOIDToConfiguration( loNode, loConfig );
				
				DebugLog.write( this.getClass(), "LOID : " + loConfig.getLoID(), DebugLog.ROW );

				// LOIDが設定されていない場合処理なし
				if ( loConfig.getLoID() == null ) continue;
				
				// LOの子供ノードを取得
				NodeList loChildNodeList = loNode.getChildNodes();
				
				for (int j = 0; j < loChildNodeList.getLength(); j++) {
					
					Node loChildNode = loChildNodeList.item(j);
					
					// テキストNODEの場合処理なし
					if ( loChildNode.getNodeType() == Node.TEXT_NODE  
							|| loChildNode.getNodeType() == Node.COMMENT_NODE) continue;

					// 学習ノードの情報を取得
					if ( loChildNode.getNodeName().equals("learning")) {
						
						// ●学習情報の設定
						this.setLearningInfoToConfiguration(loChildNode, loConfig);
						
					// 進捗率関連ノードの情報を取得
					} else	if ( loChildNode.getNodeName().equals("progressRate") ) {
						
						NodeList progressRateChildNodeList = loChildNode.getChildNodes();
						
						for (int k = 0; k < progressRateChildNodeList.getLength(); k++) {
							
							Node progressRateChildNode = progressRateChildNodeList.item(k);
							
							// テキストNODEの場合処理なし
							if ( progressRateChildNode.getNodeType() == Node.TEXT_NODE 
									|| progressRateChildNode.getNodeType() == Node.COMMENT_NODE) continue;

							// 進捗率ノードの情報を取得
							if ( progressRateChildNode.getNodeName().equals("statusRate") ) {
						
								// ●進捗率の設定
								this.setStatusRateToConfiguration(progressRateChildNode, loConfig);
								
							// ユニットごとの重みを取得
							} else if ( progressRateChildNode.getNodeName().equals("unitWeight") ) {

								//●ユニットごとの重み設定
								this.setUnitWeightToConfiguration(progressRateChildNode, loConfig);
							}
						}
						
	 				// 進捗状況関連の設定値取得
					} else if ( loChildNode.getNodeName().equals("progressStatus") ) {

						//●ユニットごとの重み設定
						this.setProgressStatusToConfiguration(loChildNode, loConfig);
					}
				}

				// LOの進捗情報を保存
				this.loProgressConfigurationMap.put(loConfig.getLoID(), loConfig);
			}
		}
	}
	
	/**
	 * 学習状況を設定値管理に設定します。
	 * 
	 * @param learningStatusNode 学習状況ノード
	 * @param configuration 学習状況保持データ
	 */
	private void setLearningStatusToConfiguration(Node learningStatusNode, LearningStatusConfiguration configuration) {
		
		Node idAttribute = learningStatusNode.getAttributes().getNamedItem("id");
		Node screenNameAttribute = learningStatusNode.getAttributes().getNamedItem("screenName");
		
		if (idAttribute == null || screenNameAttribute == null) return;
		
		// 学習状況のキーワードの取得
		// ●完了
		if ( idAttribute.getNodeValue().equals("Complete") ) {
			configuration.setCompleteScreenName( screenNameAttribute.getNodeValue() );
		// ●未完了
		} else if ( idAttribute.getNodeValue().equals("NotComplete") ) {
			configuration.setNotCompleteScreenName( screenNameAttribute.getNodeValue());
		// ●未着手
		} else if ( idAttribute.getNodeValue().equals("NotStart") ) {
			configuration.setNotStartScreenName( screenNameAttribute.getNodeValue());
		}			
	}

	/**
	 * LOIDを設定値管理に設定します。
	 * 
	 * @param loNode LOノード
	 * @param configuration LO情報保持データ
	 */
	private void setLOIDToConfiguration(Node loNode, LOConfiguration configuration) {
		
		Node idAttribute = loNode.getAttributes().getNamedItem("id");
		if (idAttribute == null) return;
		
		configuration.setLoID(idAttribute.getNodeValue());
	}
	
	/**
	 * 学習情報を設定値管理に設定します。
	 * 
	 * @param learningNode 学習ノード
	 * @param configuration LO情報保持データ
	 */
	private void setLearningInfoToConfiguration(Node learningNode, LOConfiguration configuration) {
		
		Node startDateAttribute = learningNode.getAttributes().getNamedItem("startdate");
		Node timeSpanAttribute = learningNode.getAttributes().getNamedItem("timespan");
		if (startDateAttribute == null || timeSpanAttribute == null) return;

		// 学習開始日
		configuration.setStartDate(startDateAttribute.getNodeValue());

		// 学習時間
		configuration.setTimeSpan(timeSpanAttribute.getNodeValue());
	}

	/**
	 * 進捗率を設定値管理に設定します。
	 * 
	 * @param statusNode 状態ノード
	 * @param configuration LO情報保持データ
	 */
	private void setStatusRateToConfiguration(Node statusNode, LOConfiguration configuration) {

		// ステータスごとの進捗率の取得
		NodeList statusNodeList = statusNode.getChildNodes();
		
		for (int i = 0; i < statusNodeList.getLength(); i++) {
			
			Node statusRateNode = statusNodeList.item(i);
			
			// テキストNODEの場合処理なし
			if ( statusRateNode.getNodeType() == Node.TEXT_NODE  
					|| statusRateNode.getNodeType() == Node.COMMENT_NODE) continue;

			Node idAttribute = statusRateNode.getAttributes().getNamedItem("id");
			Node rateAttribute = statusRateNode.getAttributes().getNamedItem("rate");
			if (idAttribute == null || rateAttribute == null) continue;

			// ●完了
			if ( idAttribute.getNodeValue().equals("Complete") ) {
				configuration.setCompleteRate( rateAttribute.getNodeValue() );
			// ●未完了
			} else if ( idAttribute.getNodeValue().equals("NotComplete") ) {
				configuration.setNotCompleteRate( rateAttribute.getNodeValue() );
			// ●未着手
			} else if ( idAttribute.getNodeValue().equals("NotStart") ) {
				configuration.setNotStartRate( rateAttribute.getNodeValue() );
			}			
		}
	}
	
	/**
	 * ユニットの重みを設定値管理に設定します。
	 * 
	 * @param unitWeightNode ユニットの重みノード
	 * @param configuration LO情報保持データ
	 */
	private void setUnitWeightToConfiguration(Node unitWeightNode, LOConfiguration configuration){

		// ユニットごとの重みの取得
		NodeList unitNodeList = unitWeightNode.getChildNodes();
		
		for (int i = 0; i < unitNodeList.getLength(); i++) {

			Node unitNode = unitNodeList.item(i);
			
			// テキストNODEの場合処理なし
			if ( unitNode.getNodeType() == Node.TEXT_NODE  
					|| unitNode.getNodeType() == Node.COMMENT_NODE) continue;

			Node idAttribute = unitNode.getAttributes().getNamedItem("id");
			Node weightAttribute = unitNode.getAttributes().getNamedItem("weight");
			if (idAttribute == null || weightAttribute == null) continue;

			//●ユニットごとの重み設定
			configuration.setUnitWeight(idAttribute.getNodeValue(), weightAttribute.getNodeValue());
		}
	}
	
	/**
	 * 進捗状況を設定値管理に設定します。
	 * 
	 * @param progressStatus 進捗状況
	 * @param configuration LO情報保持データ
	 */
	private void setProgressStatusToConfiguration(Node progressStatus, LOConfiguration configuration) {

		// 進捗状況取得
		NodeList levelNodeList = progressStatus.getChildNodes();
		
		for (int i = 0; i < levelNodeList.getLength(); i++) {
			
			Node levelNode = levelNodeList.item(i);
			
			// テキストNODEの場合処理なし
			if ( levelNode.getNodeType() == Node.TEXT_NODE 
					|| levelNode.getNodeType() == Node.COMMENT_NODE) continue;

			Node nameAttribute = levelNode.getAttributes().getNamedItem("name");
			Node minAttribute = levelNode.getAttributes().getNamedItem("min");
			Node maxAttribute = levelNode.getAttributes().getNamedItem("max");
			if (nameAttribute == null || minAttribute == null || maxAttribute == null) continue;

			// ●進捗率の設定
			configuration.setProgressStatus(nameAttribute.getNodeValue(),
											minAttribute.getNodeValue(),
											maxAttribute.getNodeValue());
			
		}
	}
}
