//
// CopyRight (C) 2002, IPA, eLC, NTT Resonant Inc. All rights reserved.
//
//	LocalObjective
//
//	変更履歴
//		2002.12.25  新規作成
//

package jp.co.ntt.lms.lo.scorm.kernel;

import java.math.BigDecimal;
import java.util.ArrayList;

import jp.co.ntt.lms.lo.scorm.kernel.exception.CommunicationModuleWrapperException;
import jp.co.ntt.lms.lo.scorm.kernel.exception.IllegalManifestException;
import jp.co.ntt.lms.lo.scorm.kernel.exception.SystemException;
import jp.co.ntt.lms.lo.scorm.util.CachedNode;
import jp.co.ntt.lms.lo.scorm.util.XMLUtil;
import jp.co.ntt.lms.lo.scorm.util.XPathUtil;

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

/**
 * Local Objective クラス<BR>
 * ActivityごとのObjective情報を表すクラス<BR>
 */
public class LocalObjective extends Objective {
	/** normalized measure */
	private BigDecimal minNormalizedMeasure;

	/** satisfied by measure */
	private Boolean satisfiedByMeasure;

	/** read satisfied target objective */
	private GlobalObjective readSatisfiedTargetObjective;

	/** read normalized measure target objective */
	private GlobalObjective readNormalizedMeasureTargetObjective;

	/** write satisfied target objectives */
	private GlobalObjective[] writeSatisfiedTargetObjectives;

	/** write normalized measure target objectives */
	private GlobalObjective[] writeNormalizedMeasureTargetObjectives;

	/** 前回attempt時の objective progress status */
	private boolean previousObjectiveProgressStatus[] = { false, false };

	/** 前回attempt時の objective satisfied status */
	private boolean previousObjectiveSatisfiedStatus[] = { false, false };

	/** 前回attempt時の objective measure status */
	private boolean previousObjectiveMeasureStatus[] = { false, false };

	/** 前回attempt時の objective normalized measure */
	private BigDecimal previousObjectiveNormalizedMeasure[] = { zero, zero };

	/** this activity */
	private Activity activity;

	/**
	 * コンストラクタ
	 *
	 * @param activity この local objective を持つアクティビティ<BR>
	 * @param manifestNode 教材ノード情報<BR>
	 * @param objectiveNode 教材構造ファイル中の ID で対応したノード情報<BR>
	 * @param globalObjectives global objective <BR>
	 */
	public LocalObjective(
		Activity activity,
		CachedNode manifestNode,
		CachedNode objectiveNode,
		GlobalObjective[] globalObjectives)
		throws SystemException {

		super();

		try {
			this.activity = activity;

			/*
			 * satisfied by measure のセット
			 * satisfied by mesaure の atribute がない場合は null
			 */
			CachedNode satisfiedNode = objectiveNode.selectSingleChildNode("@satisfiedByMeasure");
			if (satisfiedNode != null) {
				//satisfiedByMeasure = new Boolean(satisfiedNode.getNodeValue());
				if(satisfiedNode.getNodeValue().equals("true"))
				{
					satisfiedByMeasure = new Boolean("true");
				}
				else
				{
					satisfiedByMeasure = null;
				}
			}

			/*
			 * minimum normalized measure のセット
			 * minimum normalized measure がなければ null
			 */
			CachedNode minNormalNode = objectiveNode.selectSimpleSingleNode("minNormalizedMeasure/text()");
			if (minNormalNode != null) {
				minNormalizedMeasure =
					new BigDecimal(minNormalNode.getNodeValue()).setScale(4, BigDecimal.ROUND_HALF_UP);
			}

			/*
			 * global objective の設定
			 */
			CachedNode[] mapInfo = objectiveNode.selectChildNodeList("mapInfo");

			if ((mapInfo == null) || (mapInfo.length <= 0)) {
				return;
			}

			boolean defaultReadSatisfiedStatus =
				Boolean
					.valueOf(Default.getValue("objectives/primaryObjective/mapInfo/@readSatisfiedStatus"))
					.booleanValue();
			boolean defaultReadNormalizedMeasure =
				Boolean
					.valueOf(Default.getValue("objectives/primaryObjective/mapInfo/@readNormalizedMeasure"))
					.booleanValue();
			boolean defaultWriteSatisfiedStatus =
				Boolean
					.valueOf(Default.getValue("objectives/primaryObjective/mapInfo/@writeSatisfiedStatus"))
					.booleanValue();
			boolean defaultWriteNormalizedMeasure =
				Boolean
					.valueOf(Default.getValue("objectives/primaryObjective/mapInfo/@writeNormalizedMeasure"))
					.booleanValue();

			ArrayList writeSatisfied = new ArrayList();
			ArrayList writeNormalizedMeasure = new ArrayList();

			for (int i = 0; i < mapInfo.length; i++) {
				/*
				 * target objective id のセット
				 */
				CachedNode target = mapInfo[i].selectSingleChildNode("@targetObjectiveID");

				if (target == null) {
					throw new IllegalManifestException("target objective id がありません。target objective id は設定できません。");
				}

				String targetID = target.getNodeValue();

				/*
				 * target objective のセット
				 * target objective がない場合は仮定しない(このtarget objective id を
				 * 取得して、global objective を作っているので。)
				 */
				int j;
				for (j = 0; j < globalObjectives.length; j++) {
					if (globalObjectives[j].getObjectiveID().equals(targetID)) {
						break;
					}
				}

				CachedNode node;
				boolean result;

				/*
				 * read satisfied target objectiveの設定
				 */
				node = mapInfo[i].selectSingleChildNode("@readSatisfiedStatus");
				result =
					(node == null) ? defaultReadSatisfiedStatus : Boolean.valueOf(node.getNodeValue()).booleanValue();

				if (result) {
					if (readSatisfiedTargetObjective != null) {
						throw new SystemException(
							"readSatisfiedStatusが既に設定済みです。[ActivityID:" + activity.getIdentifier() + "]");
					}

					readSatisfiedTargetObjective = globalObjectives[j];
				}

				/*
				 * read normalizedMeasure target objectiveの設定
				 */
				node = mapInfo[i].selectSingleChildNode("@readNormalizedMeasure");
				result =
					(node == null)
						? defaultReadNormalizedMeasure
						: Boolean.valueOf(node.getNodeValue()).booleanValue();

				if (result) {
					if (readNormalizedMeasureTargetObjective != null) {
						throw new SystemException(
							"readNormalizedMeasureが既に設定済みです。[ActivityID:" + activity.getIdentifier() + "]");
					}

					readNormalizedMeasureTargetObjective = globalObjectives[j];
				}

				/*
				 * write satisfied target objectiveの設定
				 */
				node = mapInfo[i].selectSingleChildNode("@writeSatisfiedStatus");
				result =
					(node == null)
						? defaultWriteSatisfiedStatus
						: Boolean.valueOf(node.getNodeValue()).booleanValue();
				if (result) {
					writeSatisfied.add(globalObjectives[j]);
				}

				/*
				 * write normalizedMeasure target objectiveの設定
				 */
				node = mapInfo[i].selectSingleChildNode("@writeNormalizedMeasure");
				result =
					(node == null)
						? defaultWriteNormalizedMeasure
						: Boolean.valueOf(node.getNodeValue()).booleanValue();
				if (result) {
					writeNormalizedMeasure.add(globalObjectives[j]);
				}
			}

			GlobalObjective[] toArray = new GlobalObjective[0];

			if (writeSatisfied.size() > 0) {
				writeSatisfiedTargetObjectives = (GlobalObjective[])writeSatisfied.toArray(toArray);
			}

			if (writeNormalizedMeasure.size() > 0) {
				writeNormalizedMeasureTargetObjectives = (GlobalObjective[])writeNormalizedMeasure.toArray(toArray);
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"LocalObjective constractor failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * コンストラクタ<BR>
	 *
	 * @param activity
	 */
	public LocalObjective(Activity activity) {
		this.activity = activity;
	}

	/**
	 * 中断情報取得
	 */
	public void save(Document doc, Element parent, boolean traceLog) throws SystemException {
		try {
			boolean objectiveProgressStatus;
			boolean objectiveSatisfiedStatus = false;
			boolean objectiveMeasureStatus;
			BigDecimal objectiveNormalizedMeasure = zero;

			if (!traceLog) {
				objectiveProgressStatus = this.objectiveProgressStatus;
				if (objectiveProgressStatus) {
					objectiveSatisfiedStatus = this.objectiveSatisfiedStatus;
				}

				objectiveMeasureStatus = this.objectiveMeasureStatus;
				if (objectiveMeasureStatus) {
					objectiveNormalizedMeasure = this.objectiveNormalizedMeasure;
				}
			}
			else {
				objectiveProgressStatus = getObjectiveProgressStatus();
				if (objectiveProgressStatus) {
					objectiveSatisfiedStatus = getObjectiveSatisfiedStatus();
				}

				objectiveMeasureStatus = getObjectiveMeasureStatus();
				if (objectiveMeasureStatus) {
					objectiveNormalizedMeasure = getObjectiveNormalizedMeasure();
				}
			}

			XMLUtil.insertAttribute(
				doc,
				XMLUtil.append(
					doc,
					parent,
					"objective",
					new Element[] {
						XMLUtil.createElement(
							doc,
							"objectiveprogressstatus",
							Boolean.toString(objectiveProgressStatus)),
						XMLUtil.createElement(
							doc,
							"objectivesatisfiedstatus",
							(!objectiveProgressStatus) ? null : Boolean.toString(objectiveSatisfiedStatus)),
						XMLUtil.createElement(
							doc,
							"objectivemeasurestatus",
							Boolean.toString(objectiveMeasureStatus)),
						XMLUtil.createElement(
							doc,
							"objectivenormalizedmeasure",
							((!objectiveMeasureStatus) || (objectiveNormalizedMeasure == null))
								? null
								: objectiveNormalizedMeasure.toString()),
						XMLUtil.createElement(
							doc,
							"previous",
							new Element[] {
								XMLUtil.createElement(
									doc,
									"objectiveprogressstatus",
									Boolean.toString(previousObjectiveProgressStatus[0])),
								XMLUtil.createElement(
									doc,
									"objectivesatisfiedstatus",
									(!previousObjectiveProgressStatus[0])
										? null
										: Boolean.toString(previousObjectiveSatisfiedStatus[0])),
								XMLUtil.createElement(
									doc,
									"objectivemeasurestatus",
									Boolean.toString(previousObjectiveMeasureStatus[0])),
								XMLUtil.createElement(
									doc,
									"objectivenormalizedmeasure",
									((!previousObjectiveMeasureStatus[0])
										|| (previousObjectiveNormalizedMeasure[0] == null))
										? null
										: previousObjectiveNormalizedMeasure[0].toString()),
								}),
						XMLUtil.createElement(
							doc,
							"candidateprevious",
							new Element[] {
								XMLUtil.createElement(
									doc,
									"objectiveprogressstatus",
									Boolean.toString(previousObjectiveProgressStatus[1])),
								XMLUtil.createElement(
									doc,
									"objectivesatisfiedstatus",
									(!previousObjectiveProgressStatus[1])
										? null
										: Boolean.toString(previousObjectiveSatisfiedStatus[1])),
								XMLUtil.createElement(
									doc,
									"objectivemeasurestatus",
									Boolean.toString(previousObjectiveMeasureStatus[1])),
								XMLUtil.createElement(
									doc,
									"objectivenormalizedmeasure",
									((!previousObjectiveMeasureStatus[1])
										|| (previousObjectiveNormalizedMeasure[1] == null))
										? null
										: previousObjectiveNormalizedMeasure[1].toString()),
								}),
						}),
				"id",
				objectiveID);
		}
		catch (Exception ex) {
			throw new SystemException("save failed [ActivityID:" + activity.getIdentifier() + "]", ex);
		}
	}

	/*
	 * useCurrentAttemptの為の候補値を更新する
	 */
	public void setCandidatePreviousValue() throws SystemException {
		// 前回attempt情報の保存
		previousObjectiveProgressStatus[1] = getObjectiveProgressStatus();
		if (previousObjectiveProgressStatus[1]) {
			previousObjectiveSatisfiedStatus[1] = getObjectiveSatisfiedStatus();
		}

		previousObjectiveMeasureStatus[1] = getObjectiveMeasureStatus();
		if (previousObjectiveMeasureStatus[1]) {
			previousObjectiveNormalizedMeasure[1] = getObjectiveNormalizedMeasure();
		}
	}

	/**
	 * Local Objectiveの初期化<BR>
	 *
	 * target objective を持つ場合、write 権限が true であれば、
	 * target objective の情報も初期化する<BR>
	 */
	public void initializeLocalObjectiveInformation(CachedNode parent) throws SystemException {
		// 前回attempt情報の更新
		previousObjectiveProgressStatus[0] = previousObjectiveProgressStatus[1];
		if (previousObjectiveProgressStatus[0]) {
			previousObjectiveSatisfiedStatus[0] = previousObjectiveSatisfiedStatus[1];
		}

		previousObjectiveMeasureStatus[0] = previousObjectiveMeasureStatus[1];
		if (previousObjectiveMeasureStatus[0]) {
			previousObjectiveNormalizedMeasure[0] = previousObjectiveNormalizedMeasure[1];
		}

		// Objectiveの初期化
		//20040801 DEL NTTR
		initializeObjective();
/*
		// write satisfied target objective の初期化
		if (writeSatisfiedTargetObjectives != null) {
			for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
				writeSatisfiedTargetObjectives[i].setObjectiveProgressStatus(false);
				writeSatisfiedTargetObjectives[i].setObjectiveSatisfiedStatus(false);
			}
		}

		// write normalized measure target objective の初期化
		if (writeNormalizedMeasureTargetObjectives != null) {
			for (int i = 0; i < writeNormalizedMeasureTargetObjectives.length; i++) {
				writeNormalizedMeasureTargetObjectives[i].setObjectiveMeasureStatus(false);
				writeNormalizedMeasureTargetObjectives[i].setObjectiveNormalizedMeasure(zero);
			}
		}
*/
		if (parent == null) {
			return;
		}

		try {
			Node objectiveNode = parent.selectSingleNodeWithNodeTest("objective", "@id", objectiveID).getNode();

			objectiveProgressStatus =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(objectiveNode, "objectiveprogressstatus/text()")
							.getNodeValue())
					.booleanValue();

			if (objectiveProgressStatus) {
				objectiveSatisfiedStatus =
					Boolean
						.valueOf(
							XPathUtil
								.selectSimpleSingleNode(objectiveNode, "objectivesatisfiedstatus/text()")
								.getNodeValue())
						.booleanValue();
			}

			objectiveMeasureStatus =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(objectiveNode, "objectivemeasurestatus/text()")
							.getNodeValue())
					.booleanValue();

			if (objectiveMeasureStatus) {
				Node node = XPathUtil.selectSimpleSingleNode(objectiveNode, "objectivenormalizedmeasure/text()");

				if ((node != null) && (node.getNodeValue().length() > 0)) {
					objectiveNormalizedMeasure = new BigDecimal(node.getNodeValue());
				}
			}

			Node previousNode = XPathUtil.selectSingleChildNode(objectiveNode, "previous");

			previousObjectiveProgressStatus[0] =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(previousNode, "objectiveprogressstatus/text()")
							.getNodeValue())
					.booleanValue();

			if (previousObjectiveProgressStatus[0]) {
				previousObjectiveSatisfiedStatus[0] =
					Boolean
						.valueOf(
							XPathUtil
								.selectSimpleSingleNode(previousNode, "objectivesatisfiedstatus/text()")
								.getNodeValue())
						.booleanValue();
			}

			previousObjectiveMeasureStatus[0] =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(previousNode, "objectivemeasurestatus/text()")
							.getNodeValue())
					.booleanValue();

			if (previousObjectiveMeasureStatus[0]) {
				Node node = XPathUtil.selectSimpleSingleNode(previousNode, "objectivenormalizedmeasure/text()");

				if ((node != null) && (node.getNodeValue().length() > 0)) {
					previousObjectiveNormalizedMeasure[0] = new BigDecimal(node.getNodeValue());
				}
			}

			Node candidatePreviousNode = XPathUtil.selectSingleChildNode(objectiveNode, "candidateprevious");

			previousObjectiveProgressStatus[1] =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(candidatePreviousNode, "objectiveprogressstatus/text()")
							.getNodeValue())
					.booleanValue();

			if (previousObjectiveProgressStatus[1]) {
				previousObjectiveSatisfiedStatus[1] =
					Boolean
						.valueOf(
							XPathUtil
								.selectSimpleSingleNode(candidatePreviousNode, "objectivesatisfiedstatus/text()")
								.getNodeValue())
						.booleanValue();
			}

			previousObjectiveMeasureStatus[1] =
				Boolean
					.valueOf(
						XPathUtil
							.selectSimpleSingleNode(candidatePreviousNode, "objectivemeasurestatus/text()")
							.getNodeValue())
					.booleanValue();

			if (previousObjectiveMeasureStatus[1]) {
				Node node =
					XPathUtil.selectSimpleSingleNode(candidatePreviousNode, "objectivenormalizedmeasure/text()");

				if ((node != null) && (node.getNodeValue().length() > 0)) {
					previousObjectiveNormalizedMeasure[1] = new BigDecimal(node.getNodeValue());
				}
			}
		}
		catch (Exception ex) {
			throw new SystemException(
				"initializeLocalObjectiveInformation failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * 終期化<BR>
	 */
	public void terminate() throws SystemException {
		// Objectiveの終期化
		super.terminate();

		if (readSatisfiedTargetObjective != null) {
			readSatisfiedTargetObjective.terminate();
			readSatisfiedTargetObjective = null;
		}

		if (readNormalizedMeasureTargetObjective != null) {
			readNormalizedMeasureTargetObjective.terminate();
			readNormalizedMeasureTargetObjective = null;
		}

		if (writeSatisfiedTargetObjectives != null) {
			for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
				writeSatisfiedTargetObjectives[i].terminate();
				writeSatisfiedTargetObjectives[i] = null;
			}
			writeSatisfiedTargetObjectives = null;
		}

		if (writeNormalizedMeasureTargetObjectives != null) {
			for (int i = 0; i < writeNormalizedMeasureTargetObjectives.length; i++) {
				writeNormalizedMeasureTargetObjectives[i].terminate();
				writeNormalizedMeasureTargetObjectives[i] = null;
			}
			writeNormalizedMeasureTargetObjectives = null;
		}

		activity = null;
	}

	/**
	 * minimum normalized measure を返す<BR>
	 *
	 * @param returnDefault	minimum normalized measureが教材構造に定義されていない場合、
	 *						デフォルト値を返却するかどうかを指定する。trueを指定した場合
	 *						はデフォルト値を返却する。falseを指定した場合、省略されている
	 *						場合はnullが返却される。<br>
	 * @return minimum normalized measureを返す<BR>
	 */
	public BigDecimal getMinNormalizedMeasure(boolean returnDefault) throws SystemException {
		try {
			/*
			 * minimum normalized measure が null ならデフォルトを取得して返す 
			 * 設定されている場合はその値を返す
			 * 設定されている場合は 4桁に丸められているのでそのまま返す
			 * 
			 */
			if (this.minNormalizedMeasure == null) {
				if (returnDefault) {
					return new BigDecimal(
						Default.getValue("objectives/primaryObjective/minNormalizedMeasure/text()")).setScale(
						4,
						BigDecimal.ROUND_HALF_UP);
				}

				return null;
			}

			return minNormalizedMeasure;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getMinNormalizedMeasure failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * satisfied by measure を返す
	 *
	 * @return true     satisfied by measure が有効<BR>
	 *                  minimum normalized measure が有効になる<BR>
	 *         false    satisifed by measure が無効<BR>
	 */
	public boolean getSatisfiedByMeasure() throws SystemException {
		try {
			/*
			 *  satisfied by measure が null なら デフォルトを取得する
			 *  ある場合、その値を返す
			 */
			if (this.satisfiedByMeasure == null) {
				return Boolean
					.valueOf(Default.getValue("objectives/primaryObjective/@satisfiedByMeasure"))
					.booleanValue();
			}

			return satisfiedByMeasure.booleanValue();
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getSatisfiedByMeasure failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * Objective Progress Status のセット<BR>
	 *
	 * @param result objective satisfied status が有効か否かのフラグを設定<BR>
	 *        true  有効<BR>
	 *        false 無効<BR>
	 */
	public void setObjectiveProgressStatus(boolean result) throws SystemException {
		try {
			objectiveProgressStatus = result;

			if(satisfiedByMeasure != null){
				if(satisfiedByMeasure.booleanValue()){
					if(getObjectiveMeasureStatus()){
						if (writeSatisfiedTargetObjectives != null) {
							for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
								writeSatisfiedTargetObjectives[i].setObjectiveProgressStatus(result);
							}
						}		
					}
				}
			}else{
				if (writeSatisfiedTargetObjectives != null) {
					for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
						writeSatisfiedTargetObjectives[i].setObjectiveProgressStatus(result);
					}
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"setObjectiveProgressStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * Objective satisfied status のセット<BR>
	 *
	 * @param result true/false
	 */
	public void setObjectiveSatisfiedStatus(boolean result) throws SystemException {
		try {
			objectiveSatisfiedStatus = result;

			if (writeSatisfiedTargetObjectives != null) {
				for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
					writeSatisfiedTargetObjectives[i].setObjectiveSatisfiedStatus(result);
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"setObjectiveSatisfiedStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * Objective Measure status のセット<BR>
	 *
	 * @param result true/false<BR>
	 */
	public void setObjectiveMeasureStatus(boolean result) throws SystemException {
		try {
			objectiveMeasureStatus = result;

			if (writeNormalizedMeasureTargetObjectives != null) {
				for (int i = 0; i < writeNormalizedMeasureTargetObjectives.length; i++) {
					writeNormalizedMeasureTargetObjectives[i].setObjectiveMeasureStatus(result);
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"setObjectiveMeasureStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * objective normalized measureのセット
	 *
	 * @param measure
	 */
	public void setObjectiveNormalizedMeasure(BigDecimal measure) throws SystemException {
		try {
			objectiveNormalizedMeasure = measure;

			if (writeNormalizedMeasureTargetObjectives != null) {
				for (int i = 0; i < writeNormalizedMeasureTargetObjectives.length; i++) {
					writeNormalizedMeasureTargetObjectives[i].setObjectiveNormalizedMeasure(measure);
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"setObjectiveNormalizedMeasure failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * Objective progress Statusの取得
	 *
	 * @return boolean true/false
	 */
	public boolean getObjectiveProgressStatusForEvaluation() throws SystemException {
		try {
			if (!activity.isRoot()
				&& !activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return previousObjectiveProgressStatus[0];
			}

			return getObjectiveProgressStatus();
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveProgressStatusForEvaluation failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * Objective progress Statusの取得
	 *
	 * @return boolean true/false
	 */
	public boolean getObjectiveProgressStatus(boolean isCurrent) throws SystemException {
		try {
			if (activity.isRoot()){
				return getObjectiveProgressStatus();
			}
				
			if(!activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return getObjectiveProgressStatus();	
			}else{
				if(isCurrent){
					return getObjectiveProgressStatus();	
				}else{
//					 localがfalseのときだけ別物
					if(satisfiedByMeasure != null){
						if(satisfiedByMeasure.booleanValue()){
							if(!objectiveMeasureStatus){
								return false;
							}
						}
					}
	
					
					if(objectiveProgressStatus){
						return true;
					}else{
						if (readSatisfiedTargetObjective != null) {
							return readSatisfiedTargetObjective.getObjectiveProgressStatus();
						}else{
							return false;
						}
					}
					
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveProgressStatusForEvaluation failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 *  objective progress status の取得<BR>
	 * ( use current attempt objective status によらない) <BR>
	 *
	 * @return boolean  true objective progress status が有効<BR>
	 */
	public boolean getObjectiveProgressStatus() throws SystemException {
		try {
			if (!activity.getSequencing().getDeliveryControlFlag("tracked")) {
				return false;
			}


			boolean result = false;
			if ((!activity.hasChildren()) && (!activity.hasAvailableChildren())) {
				result = activity.getCommunicationModule().getObjectiveProgressStatus(objectiveID).booleanValue();
				if (result) {
					return true;
				}
			}

			result = objectiveProgressStatus;

			if (!result) {
				if (readSatisfiedTargetObjective != null) {
					if(satisfiedByMeasure != null){
						if(satisfiedByMeasure.booleanValue()){//
							if(!getObjectiveMeasureStatus()){
								return false;
							}
						}
					}
					result = readSatisfiedTargetObjective.getObjectiveProgressStatus();
				}
			}

			return result;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveProgressStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	public boolean getObjectiveLocalProgressStatus() throws SystemException {
		try {
			if (!activity.getSequencing().getDeliveryControlFlag("tracked")) {
				return false;
			}
			
			boolean result = false;
			if ((!activity.hasChildren()) && (!activity.hasAvailableChildren())) {
				result = activity.getCommunicationModule().getObjectiveProgressStatus(objectiveID).booleanValue();
				if (result) {
					return true;
				}
			}

			return objectiveProgressStatus;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveProgressStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}
	/**
	 * objective satisfied status の取得
	 *
	 * @return boolean true/false
	 */
	public boolean getObjectiveSatisfiedStatusForEvaluation() throws SystemException {
		try {
			if (!activity.isRoot()
				&& !activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return previousObjectiveSatisfiedStatus[0];
			}

			return getObjectiveSatisfiedStatus();
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveSatisfiedStatusForEvaluation failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * objective satisfied status の取得
	 *
	 * @return boolean true/false
	 */
	public boolean getObjectiveSatisfiedStatus(boolean isCurrent) throws SystemException {
		try {
			if (activity.isRoot()){
				return getObjectiveSatisfiedStatus();
			}
			if(!activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return getObjectiveSatisfiedStatus();
			}else{
				if(isCurrent){
					return getObjectiveSatisfiedStatus();	
				}
				else
				{
					// localがfalseのときだけ別物
					if(objectiveSatisfiedStatus){
						return false;
					}else{// mappingをしらべてから
						if (readSatisfiedTargetObjective != null) {
							return readSatisfiedTargetObjective.getObjectiveSatisfiedStatus();
						}else{
							return false;
						}
						
					}
				}
			}
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveSatisfiedStatusForEvaluation failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}
	
	/**
	 *  objective satisfied status の取得<BR>
	 * （ use current attempt satisfied status によらない )
	 *
	 *  @return    boolean true   satisfied<BR>
	 *                            false  not satisfied <BR>
	 */
	public boolean getObjectiveSatisfiedStatus() throws SystemException {
		try {
			if ((!activity.hasChildren()) && (!activity.hasAvailableChildren())) {
				Boolean result = activity.getCommunicationModule().getObjectiveSatisfiedStatus(objectiveID);

				if (result != null) {
					if(result.booleanValue()){
						return true;
					}
				}
			}

			boolean result = false;
			boolean rscore = false;
			if (objectiveProgressStatus) {// ここ
				result = objectiveSatisfiedStatus;
			}
			else {
				if (readSatisfiedTargetObjective != null) {
					result = readSatisfiedTargetObjective.getObjectiveSatisfiedStatus();
					rscore = readSatisfiedTargetObjective.getObjectiveMeasureStatus();
				}
			}

			if(satisfiedByMeasure != null){ 
				if (satisfiedByMeasure.booleanValue()) {//SatisfiedByMeasureのチェック
					// ローカルにはかならず数値がはいっているのobjectiveProgressStatusを見る
					double gResult;
					if (objectiveProgressStatus) {// ここ
						gResult = objectiveNormalizedMeasure.doubleValue();
					} else {
						if (readSatisfiedTargetObjective != null) {
							gResult = readSatisfiedTargetObjective.getObjectiveNormalizedMeasure().doubleValue();	
						}else{
							gResult = 0.0;
						}
						
					}
					// そして比較
					double defMesasure;
					if(minNormalizedMeasure!=null){
						defMesasure =minNormalizedMeasure.doubleValue();
					}else{
						defMesasure = 1.0;
					}
					
					if(defMesasure <= gResult){
						result = true;
					}
				}
			}else{
				// 合格値のフラグがはいってないにのに値がある
				if(minNormalizedMeasure != null){
					// さらに数値が入力されている
					if(rscore){
						result = false;	
					}
				}
			}
			return result;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveSatisfiedStatus failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * objective measure statusの取得
	 *
	 * @return boolean true/false
	 */
	public boolean getObjectiveMeasureStatusForEvaluation() throws SystemException {
		try {
			if (!activity.isRoot()
				&& !activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return previousObjectiveMeasureStatus[0];
			}

			return getObjectiveMeasureStatus();
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveMeasureStatusForEvaluation failed[ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 *  objective measure statsu の取得<BR>
	 *  ( use current attempt objective info によらない）
	 *
	 *  @return boolean   true    objective normalized measure が有効<BR>
	 *                           false   objective normalized measure が無効<BR>
	 */
	public boolean getObjectiveMeasureStatus() throws SystemException {
		try {
			if (!activity.getSequencing().getDeliveryControlFlag("tracked")) {
				return false;
			}

			boolean result;

			if ((!activity.hasChildren()) && (!activity.hasAvailableChildren())) { 
				result = activity.getCommunicationModule().getObjectiveMeasureStatus(objectiveID).booleanValue();

				if (result) {
					return true;
				}
			}

			result = objectiveMeasureStatus;

			if (!result) {
				if (readNormalizedMeasureTargetObjective != null) {
					result = readNormalizedMeasureTargetObjective.getObjectiveMeasureStatus();
				}
			}

			return result;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveMeasureStatus failed[ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * objective normalized meadsureの取得
	 *
	 * @return BigDecimal normalized measureの取得
	 */
	public BigDecimal getObjectiveNormalizedMeasureForEvaluation() throws SystemException {
		try {
			if (!activity.isRoot()
				&& !activity.getParent().getSequencing().getControlModeFlag("useCurrentAttemptObjectiveInfo")) {
				return previousObjectiveNormalizedMeasure[0];
			}

			return getObjectiveNormalizedMeasure();
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveNormalizedMeasureForEvaluation failed[ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 *  objective normalized measure の取得<BR>
	 * ( use current attempt objective infoによらない ) <BR>
	 *
	 *  @return    objective normalized measure<BR>
	 */
	public BigDecimal getObjectiveNormalizedMeasure() throws SystemException {
		try {
			if ((!activity.hasChildren()) && (!activity.hasAvailableChildren())) {
				BigDecimal result = activity.getCommunicationModule().getObjectiveNormalizedMeasure(objectiveID);

				if (result != null) {
					return result;
				}
			}

			BigDecimal result;

			if (objectiveMeasureStatus) {
				result = objectiveNormalizedMeasure;
			}
			else {
				result = readNormalizedMeasureTargetObjective.getObjectiveNormalizedMeasure();
			}

			return result;
		}
		catch (SystemException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new SystemException(
				"getObjectiveNormalizedMeasure failed [ActivityID:" + activity.getIdentifier() + "]",
				ex);
		}
	}

	/**
	 * トラッキング情報の同期
	 */
	public void synchronizeTrackingModel() throws CommunicationModuleWrapperException, SystemException {
		if (activity.hasAvailableChildren()) {
			return;
		}

		boolean calFlag = false;
		if(satisfiedByMeasure != null){
			if(satisfiedByMeasure.booleanValue()){
				if(getObjectiveMeasureStatus()){
					calFlag = true;
				}
			}
		}else{
			calFlag = true;
		}
		
		if(calFlag){
		
		if (writeSatisfiedTargetObjectives != null) {
			boolean result = activity.getCommunicationModule().getObjectiveProgressStatus(objectiveID).booleanValue();

			for (int i = 0; i < writeSatisfiedTargetObjectives.length; i++) {
				writeSatisfiedTargetObjectives[i].setObjectiveProgressStatus(result);

				if (result) {
					writeSatisfiedTargetObjectives[i].setObjectiveSatisfiedStatus(
						activity.getCommunicationModule().getObjectiveSatisfiedStatus(objectiveID).booleanValue());
				}
			}
		}

		if (writeNormalizedMeasureTargetObjectives != null) {
			boolean result = activity.getCommunicationModule().getObjectiveMeasureStatus(objectiveID).booleanValue();

			for (int i = 0; i < writeNormalizedMeasureTargetObjectives.length; i++) {
				writeNormalizedMeasureTargetObjectives[i].setObjectiveMeasureStatus(result);

				if (result) {
					writeNormalizedMeasureTargetObjectives[i].setObjectiveNormalizedMeasure(
						activity.getCommunicationModule().getObjectiveNormalizedMeasure(objectiveID));
				}
			}
		}
		}
	}
}
