//
// CopyRight (C) 2002, IPA, eLC, NTT Resonant Inc. All rights reserved.
//
//	Kernel
//
//	変更履歴
//		2002.12.25  新規作成
//		2006.11.27  変更　T.Kiyokawa
//					saveメソッドの親エレメントのないバージョンを作成。既存のsaveメソッドをコメントアウト
//

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

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;
import java.io.*;

import jp.co.ntt.lms.lo.util.UserIDFolder;
import jp.co.ntt.lms.lo.scorm.kernel.exception.IllegalManifestException;
import jp.co.ntt.lms.lo.scorm.kernel.exception.SequencingException;
import jp.co.ntt.lms.lo.scorm.kernel.exception.SystemException;
import jp.co.ntt.lms.lo.scorm.kernel.trace.Trace;
import jp.co.ntt.lms.lo.scorm.kernel.trace.TraceItem;
import jp.co.ntt.lms.lo.scorm.util.CachedNode;
import jp.co.ntt.lms.lo.scorm.util.SG;
import jp.co.ntt.lms.lo.scorm.util.XMLUtil;

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

/**
*  Kernel クラス<BR>
*  シーケンシングルール制御クラス<BR>
*/
public class Kernel {

	/** トレースログクラス */
	private Trace trace = new Trace();

	/** DateFormatter */
	private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");

	/** Organization Node */
	private CachedNode organization;

	/** Global Objectives */
	private GlobalObjective[] globalObjectives;

	/** Root Activity */
	private Activity rootActivity;

	/** User ID */
	private String userID;

	/** User Name */
	private String userName;

	/** AICC URL */
	private String aiccURL;

	/** API Adapter encoding */
	private String APIAdapterEncoding;

	/** Current Activity */
	private Activity currentActivity;

	/** Suspended Activity */
	private Activity suspendedActivity;

	/** Termination Request */
	private String terminationRequest;

	/** Sequencing Request */
	private String sequencingRequest;

	/** Delivery Request */
	private boolean deliveryRequest;

	/** targetActivity */
	private Activity targetActivity;

	/** identifiedActivity */
	private Activity identifiedActivity;

	/** navigateTime */
	private Calendar now;

	/** endSequencingSession */
	private boolean endSequencingSession;

	/** ログフォルダ */
	private String BaseDir;

	/**
	 * 教材構造定義からアクティビティツリーの作成<BR>
	 *
	 * @param manifestNode 教材構造manifestキャッシュノード
	 * @return rootActivity
	 */
	public Activity makeTree(CachedNode manifestNode, String tmpID) throws SystemException {

		try {
			// rootActivityノードを生成
			organization = manifestNode.selectSingleNode("organizations/organization[@identifier=../@default]");

			// submanifest用
			
			if (organization == null) {
				throw new IllegalManifestException("Manifest is Illegal. [organizations/organization[@identifier=../@default]=null]");
			}

			// GlobalObjectives を作成
			CachedNode[] targetObjejectiveNodes = organization.selectNodeList("descendant-or-self::mapInfo/@targetObjectiveID");
			if (targetObjejectiveNodes != null || targetObjejectiveNodes.length > 0) {
				Hashtable hash = new Hashtable();
				for (int i = 0; i < targetObjejectiveNodes.length; i++) {
					hash.put(targetObjejectiveNodes[i].getNodeValue(), targetObjejectiveNodes[i].getNodeValue());
				}
				Enumeration idList = hash.keys();
				globalObjectives = new GlobalObjective[hash.size()];
				for (int i = 0; i < hash.size(); i++) {
					if (idList.hasMoreElements()) {
						globalObjectives[i] = new GlobalObjective((String)idList.nextElement());
					}
				}
			}

			// GrobalObjectiveのコース間のマッピングを確認
			boolean refObj = true; // デフォルトはTrue
			CachedNode gObject = organization.selectSimpleSingleNode("@objectivesGlobalToSystem");
			if(gObject == null)
			{
				// なにもしない？
			}
			else
			{
				refObj = Boolean.valueOf(gObject.getNodeValue()).booleanValue();
			}
			
			BaseDir = userIDPath(SG.get("LearningLogBaseURL"), tmpID) + "\\GlobalObjectives\\";
			// コース間で共有するかどうかの確認
			if(refObj)
			{
				for(int i=0;i< globalObjectives.length;i++)
				{
					String tmpPath = BaseDir + globalObjectives[i].objectiveID;
					 
					// ファイル検索
					File tmpFile = new File(tmpPath);
					String lineData[] = {"false","false",""};
					if(tmpFile.exists())// ファイルが存在する場合のみ
					{
						// ファイル読み込み
						
						FileReader fReader = new FileReader(tmpPath);
						BufferedReader bReader = new BufferedReader(fReader);
						String inStr;
						int k = 0;
						while((inStr = bReader.readLine()) != null)
						{
							lineData[k] = inStr;
							k++;
						}
						fReader.close();
					}
					
					if(lineData[0].equals("true"))
					{
						globalObjectives[i].setObjectiveProgressStatus(true);
					}
					
					if(lineData[1].equals("true"))
					{
						globalObjectives[i].setObjectiveSatisfiedStatus(true);
					}
					
					if(!lineData[2].equals(""))
					{
						globalObjectives[i].setObjectiveNormalizedMeasure(
                                new BigDecimal(lineData[2]).setScale(4, BigDecimal.ROUND_HALF_UP)
								);
					}
					
				}

			}

			// CourceIDを取得
			CachedNode courseID = organization.selectSingleChildNode("@identifier");
			if (courseID == null) {
				throw new IllegalManifestException("Manifest is Illegal. [(organization/)@identifier=null]");
			}

			// Activityツリーを生成
			rootActivity = new Activity(manifestNode, organization, globalObjectives, courseID.getNodeValue());
			rootActivity.setParent(null);
			return rootActivity;

		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("教材構造の解析に失敗しました。(makeTree failed)", e);
		}
	}

	/**
	 * 教材情報初期化
	 * @param userID ユーザIDを設定
	 * @param userName ユーザ名を設定
	 * @param aiccURL aiccURLを設定
	 * @param resume 中断情報ドキュメントを設定・新規学習開始の場合はnullを設定
	 */
	public void initialize(String userID, String userName, String aiccURL, String APIAdapterEncoding, CachedNode resume) throws SystemException {

		try {
			// パラメータ保存
			this.userID = userID;
			this.userName = userName;
			this.aiccURL = aiccURL;
			this.APIAdapterEncoding = APIAdapterEncoding;

			// CBTCOM再開情報
			CachedNode communicationmoduleNode = null;
			// トラッキング情報再開情報
			CachedNode trackinginformationNode = null;
			// グローバルオブジェクティブ再開情報
			CachedNode globalobjectivesNode = null;

			// 中断情報が存在する場合には各情報を中断情報から取得
			if (resume != null) {
				// 中断アクティビティ設定
				CachedNode suspendedActivityNode = resume.selectSimpleSingleNode("trackinginformation/suspendedactivity/text()");

				if (suspendedActivityNode != null) {
					suspendedActivity = rootActivity.getActivity(suspendedActivityNode.getNodeValue());
				}
				// コミュニケーションモジュール中断情報設定
				communicationmoduleNode = resume.selectSingleChildNode("communicationmodule");
				// トラッキングモデル中断情報設定
				trackinginformationNode = resume.selectSingleChildNode("trackinginformation");
				// グローバルオブジェクティブ中断情報設定
				globalobjectivesNode = resume.selectSingleChildNode("globalobjectives");
			}

			// CBTCOM初期化
			rootActivity.initializeAPIAdapter(userID, userName, aiccURL, APIAdapterEncoding, communicationmoduleNode, true);

			// アクティビティ情報初期化
			rootActivity.initializeActivityInformation(trackinginformationNode);

			// グローバルオブジェクティブ情報初期化
			for (int i = 0; i < globalObjectives.length; i++) {
				globalObjectives[i].initializeObjectiveInformation(globalobjectivesNode);
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("教材構造の初期化に失敗しました。(initialize failed)", e);
		}
	}

	/**
	 * RootActivity取得
	 * @return ルートアクティビティ
	 */
	public Activity getRootActivity() {
		return rootActivity;
	}

	/**
	 * CurrentActivity取得
	 * @return カレントアクティビティ
	 */
	public Activity getCurrentActivity() {
		return currentActivity;
	}

	/**
	 * CourseID取得
	 * @return CourseID
	 */
	public String getCourseID() throws SystemException {
		try {
			CachedNode courseID = organization.selectSingleChildNode("@identifier");
			if (courseID == null) {
				throw new IllegalManifestException("Manifest is Illegal. [(organization/)@identifier=null]");
			}
			return courseID.getNodeValue();
		}
		catch (Exception e) {
			throw new SystemException("教材IDの取得に失敗しました。(getCourseID failed)", e);
		}
	}

	/**
	 * CourseTitle取得
	 * @return Course Title
	 */
	public String getTitle() throws SystemException {
		try {
			CachedNode courseTitle = organization.selectSimpleSingleNode("title/text()");
			if (courseTitle == null) {
				throw new IllegalManifestException("Manifest is Illegal. [(organization)title/text()=null]");
			}
			return courseTitle.getNodeValue();
		}
		catch (Exception e) {
			throw new SystemException("教材タイトルの取得に失敗しました。(getTitle failed)", e);
		}
	}

	//　CommentOut Start 2006.11.27 T.Kiyokawa 中断情報はそのままlog.xmlにまとめず、それぞれ送信する
//	/**
//	 * 中断情報取得
//	 * @param doc		中断情報を設定するXMLのDOM Documentを指定する
//	 * @param parent	<resume>タグを追加する(親の)Elementを指定する
//	 */
//	public void save(Document doc, Element parent) throws SystemException {
//		try {
//			// ルートエレメント作成
//			Element resume = XMLUtil.append(doc, parent, "resume");
//			// GlobalObjecitive中断情報生成
//			Element globalobjectivesNode = XMLUtil.append(doc, resume, "globalobjectives");
//			for (int i = 0; i < globalObjectives.length; i++) {
//				globalObjectives[i].save(doc, globalobjectivesNode, false);
//			}
//			// TrackingModel中断情報生成
//			Element trackinginformationNode = XMLUtil.append(doc, resume, "trackinginformation");
//			// SuspendedActivity情報生成
//			if (suspendedActivity != null) {
//				XMLUtil.append(doc, trackinginformationNode, XMLUtil.createElement(doc, "suspendedactivity", suspendedActivity.getIdentifier()));
//			}
//			rootActivity.save(doc, trackinginformationNode, true, false);
//			// CBTCOM中断情報生成
//			Element communicationmoduleNode = XMLUtil.append(doc, resume, "communicationmodule");
//			rootActivity.saveAPIAdapter(doc, communicationmoduleNode);
//		}
//		catch (SystemException e) {
//			throw e;
//		}
//		catch (Exception e) {
//			throw new SystemException("中断情報の生成に失敗しました。(save failed)", e);
//		}
//	}
	//　CommentOut End

	// Add Start 2006.11.27 T.Kiyokawa
	/**
	 * 中断情報取得
	 * @param doc		中断情報を設定するXMLのDOM Documentを指定する
	 * @param parent	<resume>タグを追加する(親の)Elementを指定する
	 */
	public void save(Document doc) throws SystemException {
		try {
			// ルートエレメント作成
			Element resume = doc.getDocumentElement() ;
			// GlobalObjecitive中断情報生成
			Element globalobjectivesNode = XMLUtil.append(doc, resume, "globalobjectives");
			for (int i = 0; i < globalObjectives.length; i++) {
				globalObjectives[i].save(doc, globalobjectivesNode, false);
			}
			// TrackingModel中断情報生成
			Element trackinginformationNode = XMLUtil.append(doc, resume, "trackinginformation");
			// SuspendedActivity情報生成
			if (suspendedActivity != null) {
				XMLUtil.append(doc, trackinginformationNode, XMLUtil.createElement(doc, "suspendedactivity", suspendedActivity.getIdentifier()));
			}
			rootActivity.save(doc, trackinginformationNode, true, false);
			// CBTCOM中断情報生成
			Element communicationmoduleNode = XMLUtil.append(doc, resume, "communicationmodule");
			rootActivity.saveAPIAdapter(doc, communicationmoduleNode);
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("中断情報の生成に失敗しました。(save failed)", e);
		}
	}
	// Add End
	
	/**
	 * トレースログ取得
	 * @return トレース結果返却
	 */
	public Document getTraceLog() throws SystemException {

		try {
			return trace.getTraceLog();
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * 終期化
	 */
	public void terminate() throws SystemException {

		try {
			// アクティビティ終期化
			currentActivity = null;
			rootActivity.terminate();
			rootActivity = null;
			// フォルダのチェックとなければ作成
			
			new File(BaseDir).mkdirs();
			// グローバルオブジェクティブ終期化
			for (int i = 0; i < globalObjectives.length; i++) {
				String tmpPath = BaseDir + globalObjectives[i].objectiveID;
				
				String writeStr = "";
				FileWriter fWriter = new FileWriter(tmpPath);
				BufferedWriter oWriter = new BufferedWriter(fWriter);
				
				writeStr = Boolean.toString(globalObjectives[i].getObjectiveProgressStatus());
				writeStr += "\n";
				writeStr += Boolean.toString(globalObjectives[i].getObjectiveSatisfiedStatus());
				writeStr += "\n";
				writeStr += globalObjectives[i].getObjectiveNormalizedMeasure().toString();
				writeStr += "\n";
				
				oWriter.write(writeStr,0,writeStr.length());
				oWriter.flush();
				oWriter.close();

				globalObjectives[i].terminate();
			}
			// キャッシュノード終期化
			organization = null;

		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("教材終了に失敗しました", e);
		}
	}

	/**
	 * 学習継続フラグ
	 * true  学習を継続しない（中断または終了）
	 * false 学習を継続する
	 * @return navigate実行後、学習状態を継続しないかどうかの判定結果
	 */
	public boolean isEndSequencingSession() {
		return endSequencingSession;
	}

	/**
	 * Overall Sequencing Process
	 * ナビゲート処理
	 * @param command
	 * @param targetActivityID
	 * @return CurrentActivity
	 */
	public Activity navigate(String command, String targetActivityID) throws SequencingException, SystemException {

		try {
			// トレース情報初期化
			trace.clearTrace();
			// Trace Start <navigate>
			TraceItem navigateTraceItem = trace.startTrace("navigate");
			try {

				// Trace <request>
				navigateTraceItem.appendChild("request", command);
				// Trace <targetactivity>
				navigateTraceItem.appendChild("targetactivity", targetActivityID);

				now = Calendar.getInstance();
				// Trace <datetime>
				navigateTraceItem.appendChild("datetime", formatter.format(now.getTime()));

				// NGExceptionCatch
				try {
					// ナビゲーションプロセス前処理
					if (currentActivity != null) {

						if (currentActivity.isActive()) {
							// 試行中断時間設定
							ActivityPath path = new ActivityPath(currentActivity, rootActivity);
							if (!path.isEmpty()) {
								while (true) {
									Activity eachActivity = path.getNext();
									eachActivity.getStatus().setAttemptSuspendedTime(now);
									if (path.isLast()) {
										break;
									}
								}
							}
							// CBTCOM・カレントアクティビティ状態同期処理
							currentActivity.synchronizeTrackingModel();
						}

						// Trace Start <studiedactivityinformation>
						trace.startTrace("studiedactivityinformation");
						try {
							// アクティビティ情報トレース
							traceActivityInformation();
						}
						finally {
							// Trace End <studiedactivityinformation>
							trace.endTrace();
						}
					}

					// 全Activityに対しDuration計算処理
					setDuration(rootActivity);

					// Trace Start <behavior>
					trace.startTrace("behavior");
					try {
						// TerminationRequest初期化
						terminationRequest = null;
						// SequencingRequest初期化
						sequencingRequest = null;
						// DeliveryRequest初期化
						deliveryRequest = false;
						// endSequencingSession初期化
						endSequencingSession = false;

						try {
							// Apply the Navigation Request Process to the navigation request
							doNavigationRequestProcess(command, targetActivityID);
						}
						// If the Navigation Request Process returned navigation request Not Valid Then
						catch (SequencingException e) {
							throw e;
						}

						if (terminationRequest != null) {
							try {
								// Apply the Termination Request Process to the termination request
								doTerminationRequestProcess();
							}
							// If the Termination Request Process returned termination request Not Valid Then
							catch (SequencingException e) {
								throw e;
							}
						}

						if (sequencingRequest != null) {

							// * add pseudo code
							// Apply Select Children Process
							doSelectChildrenProcess(rootActivity);

							// * add pseudo code
							// Apply Randomize Children Process
							doRandomizeChildrenProces(rootActivity, false);

							try {
								// Apply the Sequencing Request Process to the sequencing request
								endSequencingSession = doSequencingRequestProcess();
							}
							// If the Sequencing Request Process returned seuencing request Not Valid Then
							catch (SequencingException e) {
								throw e;
							}
							if (endSequencingSession) {
								return rootActivity;
							}
							if (identifiedActivity == null) {
								return currentActivity;
							}
						}

						if (deliveryRequest == true) {
							// Trace Start <deliveryrequest>
							trace.startTrace("deliveryrequest");
							try {
								try {
									// Apply the Delivery Request Process to the delivery request
									doDeliveryRequestProcess();
								}
								// If the Delivery Request Process returned delivery request Not Valid Then
								catch (SequencingException e) {
									throw e;
								}
								try {
									// Apply the Content Delivery Environment Process to the delivery request
									doContentDeliveryEnvironmentProcess();
								}
								// * add pseudo Code**
								catch (SequencingException e) {
									throw e;
								}
							}
							finally {
								// Trace End <deliveryrequest>
								trace.endTrace();
							}
						}
					}
					finally {
						// Trace End <behavior>
						trace.endTrace();
					}

					// ナビゲーションプロセス後処理
					if (currentActivity != null) {

						// Trace Start <deliveryactivityinformation>
						trace.startTrace("deliveryactivityinformation");
						try {
							// アクティビティ情報トレース
							traceActivityInformation();
						}
						finally {
							// Trace End <deliveryactivityinformation>
							trace.endTrace();
						}
					}
				}
				catch (SequencingException e) {
					// Trace <exception>
					navigateTraceItem.appendChild("exception", e.getMessage() + "[" + e.getStackTrace()[1].toString() + "]");
					throw e;
				}
				return currentActivity;
			}
			finally {
				// Trace End <navigate>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (SequencingException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("ナビゲートに失敗しました。(navigate failed) [NavigationRequest:" + command + "]", e);
		}
	}

	/**
	 * アクティビティのDurtionを再計算する
	 * @param activity
	 */
	private void setDuration(Activity activity) throws SystemException {

		try {
			// リーフでない場合の子ActivityのDurationの計算
			if (activity.hasChildren() == true) {
				for (int i = 0; i < activity.getChildren().length; i++) {
					setDuration(activity.getChildren()[i]);
				}
			}

			// 学習回毎の経過時間は学習中断中または実施中のもののみ再計算
			if (activity.isSuspended() || activity.isActive()) {
				// 学習回毎の経過時間はAttempt開始時間からの経過時間
				activity.getProgress().setAttemptAbsoluteDuration(activity.getStatus().getAtemptAbsoluteDuration(now));
			}

			// 学習回毎の実績時間はカレントアクティビティが実施中のみ再計算
			if (currentActivity != null && currentActivity.isActive() && activity.isActive()) {
				// 学習回毎の実績時間はAttempt開始中断時間から再計算
				activity.getProgress().setAttemptExperiencedDuration(activity.getStatus().getAttemptExperiencedDuration(now));
			}

			// 総経過時間は実施経歴があるものまたはTrackedがfalseのものを計算
			if (activity.getActivityProgressStatus() || !activity.getSequencing().getDeliveryControlFlag("tracked")) {
				// 総経過時間は初回Attemptの開始時間からの経過時間
				activity.getProgress().setActivityAbsoluteDuration(activity.getStatus().getActivityAbsoluteDuration(now));
			}

			// 総実績時間はカレントアクティビティが実施中のみ合算
			if (currentActivity != null && currentActivity.isActive() && activity.isActive()) {
				// 総実績時間は直近の実績時間を合算
				activity.getProgress().setActivityExperiencedDuration(activity.getProgress().getActivityExperiencedDuration().add(activity.getStatus().getLastExperiencedDuration(now)));
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * アクティビティ情報トレース
	 */
	private void traceActivityInformation() throws SystemException {

		// ActivityTraceLevel1
		int ACTIVITY_TRACE_LEVEL_1 = 1;

		// ActivityTraceLevel2
		int ACTIVITY_TRACE_LEVEL_2 = 2;

		// ActivityTraceLevel3
		int ACTIVITY_TRACE_LEVEL_3 = 3;

		// ActivityTraceLevel
		String ACTIVITY_TRACE_LEVEL = "ActivityTraceLevel";

		try {
			TraceItem activityinformationTraceItem = trace.getCurrentTraceItem();
			// Trace <currentactivityid>
			activityinformationTraceItem.appendChild("currentactivityid", currentActivity.getIdentifier());
			// Trace <title>
			activityinformationTraceItem.appendChild("title", currentActivity.getTitle());

			String activityTraceLevel = SG.get(ACTIVITY_TRACE_LEVEL);
			// アクティビティトレースレベルが1ならカレントアクティビティ中断情報取得
			if (Integer.parseInt(activityTraceLevel) == ACTIVITY_TRACE_LEVEL_1) {
				Element parent = trace.getTraceDocument().createElement("parent");
				currentActivity.save(trace.getTraceDocument(), parent, false, true);
				// Trace <activity>
				activityinformationTraceItem.appendChild((Element)parent.getFirstChild());
			}

			// アクティビティトレースレベルが2ならルートからカレントアクティビティまでの中断情報取得
			if (Integer.parseInt(activityTraceLevel) == ACTIVITY_TRACE_LEVEL_2) {
				ActivityPath path = new ActivityPath(rootActivity, currentActivity);
				Activity root = path.getNext();
				Element parent = trace.getTraceDocument().createElement("parent");
				root.save(trace.getTraceDocument(), parent, false, true);
				Element currentElement = (Element)parent.getFirstChild();
				while (!path.isLast()) {
					Activity current = path.getNext();
					current.save(trace.getTraceDocument(), currentElement, false, true);
					currentElement = (Element)currentElement.getLastChild();
				}
				// Trace <activity>
				activityinformationTraceItem.appendChild((Element)parent.getFirstChild());
			}

			// アクティビティトレースレベルが3ならルートアクティビティから全ての中断情報取得
			if (Integer.parseInt(activityTraceLevel) == ACTIVITY_TRACE_LEVEL_3) {
				Element parent = trace.getTraceDocument().createElement("parent");
				rootActivity.save(trace.getTraceDocument(), parent, true, true);
				// Trace <activity>
				activityinformationTraceItem.appendChild((Element)parent.getFirstChild());
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("アクティビティ情報のトレースに失敗しました。(traceActivityInformation failed)", e);
		}
	}

	/**
	 * コントロールモード判定結果トレース
	 * @param activity 対象アクティビティ
	 * @param controlmode 判定するコントロールモードルール
	 */
	private void traceControlMode(Activity activity, String controlmode) throws SystemException {

		try {
			// Trace Start <evaluatecontrolmode>
			TraceItem controlmodeTraceItem = trace.startTrace("evaluatecontrolmode");
			try {
				// Trace <activityid>
				controlmodeTraceItem.appendChild("activityid", activity.getIdentifier());
				// Trace <controlmode>
				controlmodeTraceItem.appendChild("controlmode", controlmode);
				if (controlmode.equals("choice")) {
					// Trace <applied>
					controlmodeTraceItem.appendChild("applied", Boolean.toString(activity.getChoiceFlag()));
				}
				if (controlmode.equals("choiceExit")) {
					// Trace <applied>
					controlmodeTraceItem.appendChild("applied", Boolean.toString(activity.getChoiceExitFlag()));
				}
				if (controlmode.equals("flow")) {
					// Trace <applied>
					controlmodeTraceItem.appendChild("applied", Boolean.toString(activity.getFlowFlag()));
				}
				if (controlmode.equals("forwardOnly")) {
					// Trace <applied>
					controlmodeTraceItem.appendChild("applied", Boolean.toString(activity.getForwardOnlyFlag()));
				}
			}
			finally {
				// Trace End <controlmode>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Navigation Request Process
	 * ナビゲーションリクエストプロセス
	 * @param navigationRequest
	 */
	private void doNavigationRequestProcess(String navigationRequest, String targetActivityID) throws SequencingException, SystemException {

		try {
			// Trace Start <navigationrequest>
			TraceItem navigationRequestTraceItem = trace.startTrace("navigationrequest");
			try {
				// Trace <request>
				navigationRequestTraceItem.appendChild("request", navigationRequest);

				// Case:navigation request is Start
				if (navigationRequest.equalsIgnoreCase("start")) {
					if (currentActivity == null) {
						terminationRequest = null;
						sequencingRequest = "start";
						targetActivity = null;
						return;
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-1", "[CurrentActivityID:" + currentActivity.getIdentifier() + "]", null);
					}
				}

				// Case:navigation request is Resume All
				else if (navigationRequest.equalsIgnoreCase("resumeAll")) {
					if (currentActivity == null) {
						if (suspendedActivity != null) {
							terminationRequest = null;
							sequencingRequest = "resumeAll";
							targetActivity = null;
							return;
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-3", null, null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-1", "[CurrentActivityID:" + currentActivity.getIdentifier() + "]", null);
					}
				}

				// Case:navigation request is Continue
				else if (navigationRequest.equalsIgnoreCase("continue")) {

					if (currentActivity == null) {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}

					if (!currentActivity.isRoot()) {
						// Trace <evaluatecontrolmode>
						traceControlMode(currentActivity.getParent(), "flow");
						if (currentActivity.getParent().getFlowFlag()) {
							if (currentActivity.isActive()) {
								terminationRequest = "exit";
								sequencingRequest = "continue";
								targetActivity = null;
								return;
							}
							else {
								terminationRequest = null;
								sequencingRequest = "continue";
								targetActivity = null;
								return;
							}
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-4", "[ActivityID:" + currentActivity.getParent().getIdentifier() + "]", null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-4", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
					}
				}

				// Case:navigation request is Previous
				else if (navigationRequest.equalsIgnoreCase("previous")) {

					if (currentActivity == null) {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}

					if (!currentActivity.isRoot()) {
						// Trace <evaluatecontrolmode>
						traceControlMode(currentActivity.getParent(), "flow");
						// Trace <evaluatecontrolmode>
						traceControlMode(currentActivity.getParent(), "forwardOnly");

						if (currentActivity.getParent().getFlowFlag() && !currentActivity.getParent().getForwardOnlyFlag()) {

							if (currentActivity.isActive()) {
								terminationRequest = "exit";
								sequencingRequest = "previous";
								targetActivity = null;
								return;
							}
							else {
								terminationRequest = null;
								sequencingRequest = "previous";
								targetActivity = null;
								return;
							}
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-5", "[ActivityID:" + currentActivity.getParent().getIdentifier() + "]", null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-6", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
					}
				}

				// Case:navigation request is Forward
				else if (navigationRequest.equalsIgnoreCase("forward")) {
					terminationRequest = null;
					sequencingRequest = null;
					targetActivity = null;
					throw SequencingException.getInstance("NB.2.1-7", "[NavigationRequest:" + navigationRequest + "]", null);
				}

				// Case:navigation request is Backward
				else if (navigationRequest.equalsIgnoreCase("backward")) {
					terminationRequest = null;
					sequencingRequest = null;
					targetActivity = null;
					throw SequencingException.getInstance("NB.2.1-7", "[NavigationRequest:" + navigationRequest + "]", null);
				}

				// Case:navigation request is Choice
				else if (navigationRequest.equalsIgnoreCase("choice")) {

					Activity specifiedActivity = rootActivity.getActivity(targetActivityID);
					if (specifiedActivity != null) {

						if (!specifiedActivity.isRoot()) {
							// Trace <evaluatecontrolmode>
							traceControlMode(specifiedActivity.getParent(), "choice");
						}

						if (specifiedActivity.isRoot() || specifiedActivity.getParent().getChoiceFlag()) {
							if (currentActivity == null) {
								terminationRequest = null;
								sequencingRequest = "choice";
								targetActivity = specifiedActivity;
								return;
							}

							if (ActivityPath.checkTarget(currentActivity, specifiedActivity) != ActivityPath.SIBLING
								&& ActivityPath.checkTarget(currentActivity, specifiedActivity) != ActivityPath.SAME_ACTIVITY) {

								Activity commonAncestor = ActivityPath.getCommonParent(currentActivity, specifiedActivity);
								ActivityPath path = new ActivityPath(currentActivity, commonAncestor);
								path.removeLast();
								if (!path.isEmpty()) {

									while (true) {
										Activity eachActivity = path.getNext();
										// Trace <evaluatecontrolmode>
										traceControlMode(eachActivity.getParent(), "choiceExit");

										if (eachActivity.isActive() && !eachActivity.getChoiceExitFlag()) {
											terminationRequest = null;
											sequencingRequest = null;
											targetActivity = null;
											throw SequencingException.getInstance("NB.2.1-8", "[ActivityID:" + eachActivity.getParent().getIdentifier() + "]", null);
										}

										if (path.isLast()) {
											break;
										}
									}
								}
								// * edit pseudo code
								else if (ActivityPath.checkTarget(currentActivity, commonAncestor) == ActivityPath.SAME_ACTIVITY) {
									// nothing
								}
								else {
									terminationRequest = null;
									sequencingRequest = null;
									targetActivity = null;
									throw SequencingException.getInstance("NB.2.1-9", null, null);
								}
							}
							if (currentActivity.isActive()) {
								terminationRequest = "exit";
								sequencingRequest = "choice";
								targetActivity = specifiedActivity;
								return;
							}
							else {
								terminationRequest = null;
								sequencingRequest = "choice";
								targetActivity = specifiedActivity;
								return;
							}
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-10", "[ActivityID:" + specifiedActivity.getParent().getIdentifier() + "]", null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-11", "[TargetActivityID:" + targetActivityID + "]", null);
					}
				}

				// Case:navigation request is Exit
				else if (navigationRequest.equalsIgnoreCase("exit")) {
					if (currentActivity != null) {
						if (currentActivity.isActive()) {
							terminationRequest = "exit";
							sequencingRequest = "exit";
							targetActivity = null;
							return;
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-12", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}
				}

				// Case:navigation request is Exit All
				else if (navigationRequest.equalsIgnoreCase("exitAll")) {
					if (currentActivity != null) {
						terminationRequest = "exitAll";
						sequencingRequest = "exit";
						targetActivity = null;
						return;
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}
				}

				// Case:navigation request is Abandon
				else if (navigationRequest.equalsIgnoreCase("abandon")) {
					if (currentActivity != null) {
						if (currentActivity.isActive()) {
							terminationRequest = "abandon";
							sequencingRequest = "exit";
							targetActivity = null;
							return;
						}
						else {
							terminationRequest = null;
							sequencingRequest = null;
							targetActivity = null;
							throw SequencingException.getInstance("NB.2.1-12", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
						}
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}
				}

				// Case:navigation request is Abandon All
				else if (navigationRequest.equalsIgnoreCase("abandonAll")) {
					if (currentActivity != null) {
						terminationRequest = "abandonAll";
						sequencingRequest = "exit";
						targetActivity = null;
						return;
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}
				}

				// Case:navigation request is Suspend All
				else if (navigationRequest.equalsIgnoreCase("suspendAll")) {
					if (currentActivity != null) {
						terminationRequest = "suspendAll";
						sequencingRequest = "exit";
						targetActivity = null;
						return;
					}
					else {
						terminationRequest = null;
						sequencingRequest = null;
						targetActivity = null;
						throw SequencingException.getInstance("NB.2.1-2", null, null);
					}
				}
				terminationRequest = null;
				sequencingRequest = null;
				targetActivity = null;
				throw SequencingException.getInstance("NB.2.1-13", "[NavigationRequest:" + navigationRequest + "]", null);
			}
			finally {
				// Trace End <navigationrequest>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Sequencing Exit Action Rules Subprocess
	 * Exitアクションルール判定サブプロセス
	 */
	private void doSequencingExitActionRulesSubprocess() throws SystemException {

		try {
			ActivityPath path = new ActivityPath(rootActivity, currentActivity.getParent());
			Activity exitTargetActivity = null;

			if (!path.isEmpty()) {
				while (true) {
					Activity eachActivity = path.getNext();
					// Apply the Sequencing Rules Check Process to the activity and the set of Exit actions
					String[] action = { "exit" };
					String evaluation = doSequencingRulesCheckProcess(eachActivity, action, "exitConditionRule");
					if (evaluation != null && !evaluation.equalsIgnoreCase("")) {
						exitTargetActivity = eachActivity;
						break;
					}
					if (path.isLast()) {
						break;
					}
				}
			}
			if (exitTargetActivity != null) {
				// Apply the Terminate Descendent Attempts Process to the exit target
				doTerminateDescendentAttemptsProcess(exitTargetActivity);
				doEndAttemptProcess(exitTargetActivity);
				currentActivity = exitTargetActivity;
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Sequencing Post Condition Rules Subprocess
	 * Postコンディションルール判定サブプロセス
	 */
	private void doSequencingPostConditionRulesSubprocess() throws SystemException {

		try {
			if (currentActivity.isSuspended()) {
				return;
			}
			// Apply the Sequencing Rules Check Process to the Current Activity and the set of Post Condition actions
			String[] action = { "exitParent", "exitAll", "retry", "retryAll", "continue", "previous" };
			String evaluation = doSequencingRulesCheckProcess(currentActivity, action, "postConditionRule");
			if (evaluation != null && !evaluation.equalsIgnoreCase("")) {
				if (evaluation.equalsIgnoreCase("retry") || evaluation.equalsIgnoreCase("continue") || evaluation.equalsIgnoreCase("previous")) {
					sequencingRequest = evaluation;
					terminationRequest = null;
					return;
				}
				if (evaluation.equalsIgnoreCase("exitParent") || evaluation.equalsIgnoreCase("exitAll")) {
					sequencingRequest = null;
					terminationRequest = evaluation;
					return;
				}
				if (evaluation.equalsIgnoreCase("retryAll")) {
					terminationRequest = "exitAll";
					sequencingRequest = "retry";
					return;
				}
			}
			// * delete pseudo code
			//sequencingRequest = null;
			//terminationRequest = null;
			return;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Termination Request Process
	 * 終期化リクエストプロセス
	 */
	private void doTerminationRequestProcess() throws SequencingException, SystemException {

		try {
			// Trace Start <terminationrequest>
			TraceItem terminationRequestTraceItem = trace.startTrace("terminationrequest");

			try {
				// Trace <request>
				terminationRequestTraceItem.appendChild("request", terminationRequest);

				boolean existSequencingPostConditionRulesSubprocess = false;

				if (currentActivity == null) {
					sequencingRequest = null;
					throw SequencingException.getInstance("TB.2.3-1", null, null);
				}
				if ((terminationRequest.equalsIgnoreCase("exit") || terminationRequest.equalsIgnoreCase("abandon")) && !currentActivity.isActive()) {
					sequencingRequest = null;
					throw SequencingException.getInstance("TB.2.3-2", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
				}

				// Case:termination request is Exit
				if (terminationRequest.equalsIgnoreCase("exit")) {

					// Apply the End Attempt Process to the Current Activity
					doEndAttemptProcess(currentActivity);

					// Apply the Sequencing Exit Action Rules Subprocess to the Current Activity
					doSequencingExitActionRulesSubprocess();

					boolean processExit = false;
					// Repeat
					do {
						processExit = false;

						// Apply the Sequencing Post Action Rules Subprocess to the current Activity
						doSequencingPostConditionRulesSubprocess();
						existSequencingPostConditionRulesSubprocess = true;

						if ((terminationRequest != null) && (terminationRequest.equalsIgnoreCase("exitAll"))) {
							// Change the termination request to Exit All
							// Break to the next Case
							break;
						}
						if ((terminationRequest != null) && (terminationRequest.equalsIgnoreCase("exitParent"))) {
							if (!currentActivity.isRoot()) {
								currentActivity = currentActivity.getParent();
								// Trace <currentActivity>
								terminationRequestTraceItem.appendChild("currentactivityid", currentActivity.getIdentifier());

								// Apply the End Attempt Process to the Current Activity
								doEndAttemptProcess(currentActivity);
								processExit = true;
								// * add pseudo code
								terminationRequest = "exit";
							}
							else {
								throw SequencingException.getInstance("TB.2.3-4", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
							}
						}
					}
					while (processExit);

					// Break to the next Case
					if ((terminationRequest == null) || (!terminationRequest.equalsIgnoreCase("exitAll"))) {
						// SequencingRequest:is the sequencing request returned by the Sequencing Post Condition Rule Subprocess
						return;
					}
				}

				// Case:termination request is Exit All
				if (terminationRequest.equalsIgnoreCase("exitAll")) {

					if (currentActivity.isActive()) {
						// Apply the End Attempt Process to the Current Activity
						doEndAttemptProcess(currentActivity);
					}

					// Apply the Terminate Desendent Atempts Process to the root of he activity tree
					doTerminateDescendentAttemptsProcess(rootActivity);

					// Apply the End Attempt Process to the root of the activity tree
					doEndAttemptProcess(rootActivity);

					currentActivity = rootActivity;
					// Trace <currentactivityid>
					terminationRequestTraceItem.appendChild("currentactivityid", currentActivity.getIdentifier());

					if (!existSequencingPostConditionRulesSubprocess) {
						sequencingRequest = "exit";
					}
					return;
				}

				// Case:termination request is Suspend All
				if (terminationRequest.equalsIgnoreCase("suspendAll")) {

					// 20050728 
					if (currentActivity.isActive()) {
						// Apply the End Attempt Process to the Current Activity
						doEndAttemptProcessDummy(currentActivity);
					}
					
					if (currentActivity.isActive() || currentActivity.isSuspended()) {
						suspendedActivity = currentActivity;
						// Trace <suspendedactivityid>
						terminationRequestTraceItem.appendChild("suspendedactivityid", suspendedActivity.getIdentifier());

					}
					else {
						if (!currentActivity.isRoot()) {
							suspendedActivity = currentActivity.getParent();
							// Trace <suspendedactivityid>
							terminationRequestTraceItem.appendChild("suspendedactivityid", suspendedActivity.getIdentifier());
						}
						else {
							sequencingRequest = null;
							throw SequencingException.getInstance("TB.2.3-3", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
						}
					}
					ActivityPath path = new ActivityPath(suspendedActivity, rootActivity);

					if (path.isEmpty()) {
						sequencingRequest = null;
						throw SequencingException.getInstance("TB.2.3-5", null, null);
					}
					while (true) {

						// Trace Start <editActivityInformation>
						TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
						try {
							Activity eachActivity = path.getNext();
							// Trace <activityid>
							editActivityInformation.appendChild("activityid", eachActivity.getIdentifier());

							eachActivity.setActive(false);
							// Trace <activityisactive>
							editActivityInformation.appendChild("activityisactive", "false");

							eachActivity.setSuspended(true);
							// Trace <activityissuspended>
							editActivityInformation.appendChild("activityissuspended", "true");

						}
						finally {
							// Trace Start <editActivityInformation>
							trace.endTrace();
						}
						if (path.isLast()) {
							break;
						}
					}
					currentActivity = rootActivity;
					// Trace <currentActivity>
					terminationRequestTraceItem.appendChild("currentActivity", currentActivity.getIdentifier());

					sequencingRequest = "exit";
					return;
				}

				// Case:termination request is Abandon
				if (terminationRequest.equalsIgnoreCase("abandon")) {

					// Trace Start <editActivityInformation>
					TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
					try {
						// Trace <activityid>
						editActivityInformation.appendChild("activityid", currentActivity.getIdentifier());
						currentActivity.setActive(false);
						// Trace <activityisactive>
						editActivityInformation.appendChild("activityisactive", "false");
					}
					finally {
						// Trace Start <editActivityInformation>
						trace.endTrace();
					}
					sequencingRequest = null;
					return;
				}

				// Case:termination request is Abandon All
				if (terminationRequest.equalsIgnoreCase("abandonAll")) {
					ActivityPath path = new ActivityPath(currentActivity, rootActivity);
					if (path.isEmpty()) {
						sequencingRequest = null;
						throw SequencingException.getInstance("TB.2.3-6", null, null);
					}
					while (true) {
						Activity eachActivity = path.getNext();

						// Trace Start <editActivityInformation>
						TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
						try {
							// Trace <activityid>
							editActivityInformation.appendChild("activityid", eachActivity.getIdentifier());

							eachActivity.setActive(false);
							// Trace <activityisactive>
							editActivityInformation.appendChild("activityisactive", "false");

						}
						finally {
							// Trace Start <editActivityInformation>
							trace.endTrace();
						}
						if (path.isLast()) {
							break;
						}
					}
					currentActivity = rootActivity;
					// Trace <currentactivityid>
					terminationRequestTraceItem.appendChild("currentactivityid", currentActivity.getIdentifier());
					sequencingRequest = null;
					return;
				}

				sequencingRequest = null;
				throw SequencingException.getInstance("TB.2.3-7", "[TerminationRequest:" + terminationRequest + "]", null);
			}
			finally {
				// Trace End <terminationrequest>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Completion Amount Rollup Process
	 * 完了率ロールアッププロセス
	 * @param activity
	 */
	private void doCompletionAmountRollupProcess(Activity activity) throws SystemException {

		try {
			BigDecimal amount = new BigDecimal("0.0").setScale(4, BigDecimal.ROUND_HALF_UP);

			Activity[] availableChildren = activity.getAvailableChildren();

			for (int i = 0; i < availableChildren.length; i++) {
				if (availableChildren[i].getAttemptProgressStatus(activity.getUseCurrentAttempt())) {
					amount = amount.add(availableChildren[i].getAttemptCompletionAmount());
				}
			}

			activity.setAttemptCompletionAmount(amount.divide(new BigDecimal(Integer.toString(availableChildren.length)), 4, BigDecimal.ROUND_HALF_UP));
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Measure Rollup Process
	 * 合格率ロールアッププロセス
	 * @param activity
	 */
	private void doMeasureRollupProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <measurerollup>
			TraceItem measurerollupTraceItem = trace.startTrace("measurerollup");
			try {
				// Trace <activityid>
				measurerollupTraceItem.appendChild("activityid", activity.getIdentifier());

				BigDecimal totalWeightedMeasure = new BigDecimal("0.0");
				BigDecimal countedMeasure = new BigDecimal("0.0");
				LocalObjective targetObjective = activity.getObjectiveContributeToRollup();

				if (targetObjective != null) {
					// Trace <objectiveid>
					measurerollupTraceItem.appendChild("objectiveid", targetObjective.objectiveID);

					Activity[] availableChildren = activity.getAvailableChildren();

					for (int i = 0; i < availableChildren.length; i++) {

						if (availableChildren[i].getSequencing().getDeliveryControlFlag("tracked")) {

							LocalObjective rolledUpObjective = availableChildren[i].getObjectiveContributeToRollup();

							if (rolledUpObjective != null) {
								BigDecimal weight = availableChildren[i].getSequencing().getRollupObjectiveMeasureWeight();
								if (weight.compareTo(new BigDecimal("0")) >= 0) {
									countedMeasure = countedMeasure.add(weight);
									if (rolledUpObjective.getObjectiveMeasureStatusForEvaluation()) {
										totalWeightedMeasure = totalWeightedMeasure.add(rolledUpObjective.getObjectiveNormalizedMeasureForEvaluation().multiply(weight));
									}
								}
							}
							else {
								return;
							}
						}
					}

					// Trace Start <editActivityInformation>
					TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
					try {
						// Trace <activityid>
						editActivityInformation.appendChild("activityid", activity.getIdentifier());

						// Trace <objectiveid>
						editActivityInformation.appendChild("objectiveid", targetObjective.objectiveID);

						if (countedMeasure.compareTo(new BigDecimal("0")) == 0) {
							targetObjective.setObjectiveMeasureStatus(false);
							// Trace <objectivemesurestatus>
							measurerollupTraceItem.appendChild("objectivemeasurestatus", "false");
							return;
						}

						if (countedMeasure.compareTo(new BigDecimal("0")) == 1) {
							targetObjective.setObjectiveMeasureStatus(true);
							// Trace <objectivemesurestatus>
							editActivityInformation.appendChild("objectivemeasurestatus", "true");

							targetObjective.setObjectiveNormalizedMeasure(totalWeightedMeasure.divide(countedMeasure, 4, BigDecimal.ROUND_HALF_UP));
							// Trace <objectivenormalizemesure>
							editActivityInformation.appendChild("objectivenormalizemesure", totalWeightedMeasure.divide(countedMeasure, 4, BigDecimal.ROUND_HALF_UP).toString());
							return;
						}
					}
					finally {
						// Trace End <editActivityInformation>
						trace.endTrace();
					}
				}
			}

			finally {
				// Trace End <measurerollup>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Objective Rollup Using Measure Process
	 * Objectiveロールアッププロセス（合格率使用）
	 * @param activity
	 */
	private boolean doObjectiveRollupUsingMeasureProcess(Activity activity) throws SystemException {
		boolean ret = false;
		try {
			// Trace Start <objectiverollupbymeasure>
			TraceItem objectiverollupbymesureTraceItem = trace.startTrace("objectiverollupbymeasure");
			try {
				// Trace <activityid>
				objectiverollupbymesureTraceItem.appendChild("activityid", activity.getIdentifier());

				LocalObjective targetObjective = activity.getObjectiveContributeToRollup();

				if (targetObjective != null) {
					// Trace <objectiveid>
					objectiverollupbymesureTraceItem.appendChild("objectiveid", targetObjective.objectiveID);

					if (targetObjective.getSatisfiedByMeasure()) {

						// Trace Start <editActivityInformation>
						TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
						try {
							// Trace <activityid>
							editActivityInformation.appendChild("activityid", activity.getIdentifier());

							// Trace <objectiveid>
							editActivityInformation.appendChild("objectiveid", targetObjective.objectiveID);

							if (!targetObjective.getObjectiveMeasureStatusForEvaluation()) {

								targetObjective.setObjectiveProgressStatus(false);
								ret = true;
								// Trace <objectiveprogressstatus>
								editActivityInformation.appendChild("objectiveprogressstatus", "false");
							}
							else {
								if (!activity.isActive()
									|| (activity.isActive() && Boolean.valueOf(activity.getSequencing().getRollupConsiderationValue("measureSatisfactionIfActive")).booleanValue())) {
								
									if (targetObjective.getObjectiveNormalizedMeasureForEvaluation().compareTo(targetObjective.getMinNormalizedMeasure(true)) >= 0) {

										targetObjective.setObjectiveProgressStatus(true);
										// Trace <objectiveprogressstatus>
										editActivityInformation.appendChild("objectiveprogressstatus", "true");

										targetObjective.setObjectiveSatisfiedStatus(true);
										ret = true;
										// Trace <objectivesatisfiedstatus>
										editActivityInformation.appendChild("objectivesatisfiedstatus", "true");

									}
									else {
										targetObjective.setObjectiveProgressStatus(true);
										// Trace <objectiveprogressstatus>
										editActivityInformation.appendChild("objectiveprogressstatus", "true");

										targetObjective.setObjectiveSatisfiedStatus(false);
										ret = true;
										// Trace <objectivesatisfiedstatus>
										editActivityInformation.appendChild("objectivesatisfiedstatus", "false");
									}
								}
								else {
									targetObjective.setObjectiveProgressStatus(false);
									ret = true;
									// Trace <objectiveprogressstatus>
									editActivityInformation.appendChild("objectiveprogressstatus", "false");
								}

							}
						}
						finally {
							// Trace End <editActivityInformation>
							trace.endTrace();
						}
					}
				}
			}
			finally {
				// Trace End <objectiverollupbymeasure>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
		return ret;
	}

	/**
	 * Objective Rollup Using Rules Process
	 * Objectiveロールアッププロセス（ロールアップルール使用）
	 * @param activity
	 */
	private void doObjectiveRollupUsingRulesProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <objectiverollup>
			TraceItem objectiverollupTraceItem = trace.startTrace("objectiverollup");
			try {
				// Trace <activityid>
				objectiverollupTraceItem.appendChild("activityid", activity.getIdentifier());

				LocalObjective targetObjective = activity.getObjectiveContributeToRollup();

				if (targetObjective != null) {
					// Trace <objectiveid>
					objectiverollupTraceItem.appendChild("objectiveid", targetObjective.objectiveID);

					// Apply the Rollup Rule Check Subprocess to the activity and the Not Satisfied rollup action
					boolean evaluation = doRollupRuleCheckSubprocess(activity, "notSatisfied");

					// Trace Start <editActivityInformation>
					TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
					try {
						// Trace <activityid>
						editActivityInformation.appendChild("activityid", activity.getIdentifier());

						// Trace <objectiveid>
						editActivityInformation.appendChild("objectiveid", targetObjective.objectiveID);

						if (evaluation) {

							targetObjective.setObjectiveProgressStatus(true);
							// Trace <objectiveprogressstatus>
							editActivityInformation.appendChild("objectiveprogressstatus", "true");

							targetObjective.setObjectiveSatisfiedStatus(false);
							// Trace <objectivesatisfiedstatus>
							editActivityInformation.appendChild("objectivesatisfiedstatus", "false");
						}
					}
					finally {
						// Trace End <editActivityInformation>
						trace.endTrace();
					}

					// Apply the Rollup Rule Check Subprocess to the activity and the Satisfied rollup action
					evaluation = doRollupRuleCheckSubprocess(activity, "satisfied");

					// Trace Start <editActivityInformation>
					editActivityInformation = trace.startTrace("editActivityInformation");
					try {
						// Trace <activityid>
						editActivityInformation.appendChild("activityid", activity.getIdentifier());

						// Trace <objectiveid>
						editActivityInformation.appendChild("objectiveid", targetObjective.objectiveID);

						if (evaluation) {
							targetObjective.setObjectiveProgressStatus(true);
							// Trace <objectiveprogressstatus>
							editActivityInformation.appendChild("objectiveprogressstatus", "true");

							targetObjective.setObjectiveSatisfiedStatus(true);
							// Trace <objectivesatisfiedstatus>
							editActivityInformation.appendChild("objectivesatisfiedstatus", "true");

						}
					}
					finally {
						// Trace End <editActivityInformation>
						trace.endTrace();
					}
				}
			}
			finally {
				// Trace End <objectiverollup>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Activity Progress Rollup Process
	 * Progressロールアッププロセス
	 * @param activity
	 */
	private void doActivityProgressRollupProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <activityrollup>
			TraceItem activityrollupTraceItem = trace.startTrace("activityrollup");
			try {
				// Trace <activityid>
				activityrollupTraceItem.appendChild("activityid", activity.getIdentifier());

				// Apply the Rollup Rule Check Subprocess to the activity and the Not Satisfied rollup action
				boolean evaluation = doRollupRuleCheckSubprocess(activity, "incomplete");

				// Trace Start <editActivityInformation>
				TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
				try {
					// Trace <activityid>
					editActivityInformation.appendChild("activityid", activity.getIdentifier());

					if (evaluation) {

						activity.setAttemptProgressStatus(true);
						// Trace <attemptprogressstatus>
						editActivityInformation.appendChild("attemptprogressstatus", "true");

						activity.setAttemptCompletionStatus(false);
						// Trace <attemptcompletionstatus>
						editActivityInformation.appendChild("attemptcompletionstatus", "false");
					}
				}
				finally {
					// Trace End <editActivityInformation>
					trace.endTrace();
				}

				// Apply the Rollup Rule Check Subprocess to the activity and the Satisfied rollup action
				evaluation = doRollupRuleCheckSubprocess(activity, "completed");

				// Trace Start <editActivityInformation>
				editActivityInformation = trace.startTrace("editActivityInformation");
				try {
					if (evaluation) {
						activity.setAttemptProgressStatus(true);
						// Trace <attemptprogressstatus>
						editActivityInformation.appendChild("attemptprogressstatus", "true");

						activity.setAttemptCompletionStatus(true);
						// Trace <attemptcompletionstatus>
						editActivityInformation.appendChild("attemptcompletionstatus", "true");
					}
				}
				finally {
					// Trace End <editActivityInformation>
					trace.endTrace();
				}
			}
			finally {
				// Trace End <activityrollup>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Rollup Rule Check Subprocess
	 * ロールアップルールチェックサブプロセス
	 * @param activity
	 * @param rollupAction
	 * @return boolean evaluation
	 */
	private boolean doRollupRuleCheckSubprocess(Activity activity, String rollupAction) throws SystemException {

		try {
			// Trace Start <rolluprulecheck>
			TraceItem rolluprulecheckTraceItem = trace.startTrace("rolluprulecheck");
			try {
				// Trace <activityid>
				rolluprulecheckTraceItem.appendChild("activityid", activity.getIdentifier());
				CachedNode rollupRulesNode = activity.getSequencing().getRollupRules();
				if (rollupRulesNode == null) {
					// Trace <applied>
					rolluprulecheckTraceItem.appendChild("applied", "false");
// NTTR debug START デフォルトルール補完
					if(activity.hasChildren()){
						rollupRulesNode = Default.getNode("rollupRules");
					}
				}
				CachedNode[] rollupRuleNodes = rollupRulesNode.selectNodeList("rollupRule[rollupAction/@action='" + rollupAction + "']");

				// * add pseudo code
				if (rollupRuleNodes != null) {

					// Trace <action>
					rolluprulecheckTraceItem.appendChild("action", rollupAction);

					for (int i = 0; i < rollupRuleNodes.length; i++) {

						Activity[] availableChildren = activity.getAvailableChildren();
						String[] rollupBag = new String[availableChildren.length];

						CachedNode[] rollupConditionNodes = rollupRuleNodes[i].selectSimpleNodeList("rollupConditions/rollupCondition");

						String conditionCombination;
						CachedNode conditionCombinationNode = rollupRuleNodes[i].selectSimpleSingleNode("rollupConditions/@conditionCombination");
						if (conditionCombinationNode == null) {
							conditionCombination = Default.getValue("rollupRules/rollupRule/rollupConditions/@conditionCombination");
						}
						else {
							conditionCombination = conditionCombinationNode.getNodeValue();
						}

						for (int j = 0; j < availableChildren.length; j++) {
							// Trace Start <evaluationchildren>
							TraceItem evaluationchildrenTraceItem = trace.startTrace("evaluationchildren");
							try {
								// Trace <activityid>
								evaluationchildrenTraceItem.appendChild("activityid", availableChildren[j].getIdentifier());

								// * add pseudo code
								rollupBag[j] = "unknown";
								if (availableChildren[j].getSequencing().getDeliveryControlFlag("tracked")) {

									// Apply Check Child for Rollup Subprocess to the child and the Rollup Action
									boolean checkChildforRollupSubprocessFlag = doCheckChildforRollupSubprocess(availableChildren[j], rollupAction);
									if (checkChildforRollupSubprocessFlag) {
										// Apply the Evaluate Rollup Conditions Subprocess to the child and the Rollup Conditions for the rule
										String evaluation = doEvaluateRollupConditionsSubprocess(availableChildren[j], rollupConditionNodes, conditionCombination);
										rollupBag[j] = evaluation;
									}
								}
								// Trace <combinatedevaluation>
								evaluationchildrenTraceItem.appendChild("combinatedevaluation", rollupBag[j]);
							}
							finally {
								// Trace End <evaluationchildren>
								trace.endTrace();
							}
						}
						boolean statusChange = false;
						String childActivitySet;
						CachedNode childActivitySetNode = rollupRuleNodes[i].selectSingleChildNode("@childActivitySet");
						if (childActivitySetNode == null) {
							childActivitySet = Default.getValue("rollupRules/rollupRule/@childActivitySet");
						}
						else {
							childActivitySet = childActivitySetNode.getNodeValue();
						}

						// Case:the Rollup Child Activity Set is All
						if (childActivitySet.equalsIgnoreCase("all")) {
							for (int j = 0; j < rollupBag.length; j++) {
								if (rollupBag[j].equalsIgnoreCase("true")) {
									statusChange = true;
								}
								else {
									statusChange = false;
									break;
								}
							}
						}

						// Case:the Rollup Child Activity Set is Any
						else if (childActivitySet.equalsIgnoreCase("any")) {
							for (int j = 0; j < rollupBag.length; j++) {
								if (rollupBag[j].equalsIgnoreCase("true")) {
									statusChange = true;
									break;
								}
								else {
									statusChange = false;
								}
							}
						}

						// Case:the Rollup Child Activity Set is none
						else if (childActivitySet.equalsIgnoreCase("none")) {
							for (int j = 0; j < rollupBag.length; j++) {
								if (!rollupBag[j].equalsIgnoreCase("false")) {
									statusChange = false;
									break;
								}
								else {
									statusChange = true;
								}
							}
						}

						// Case:the Rollup Child Activity Set is At Least Count
						else if (childActivitySet.equalsIgnoreCase("atLeastCount")) {

							int rollupCount = 0;
							int minimamCount;
							CachedNode countNode = rollupRuleNodes[i].selectSingleChildNode("@minimumCount");
							if (countNode == null) {
								minimamCount = Integer.parseInt(Default.getValue("rollupRules/rollupRule/@minimumCount"));
							}
							else {
								minimamCount = Integer.parseInt(countNode.getNodeValue());
							}

							for (int j = 0; j < rollupBag.length; j++) {
								if (rollupBag[j].equalsIgnoreCase("true")) {
									rollupCount++;
								}
							}
							if (rollupCount >= minimamCount) {
								statusChange = true;
							}
							else {
								statusChange = false;
							}

						}

						// Case:the Rollup Child Activity Set is At Least Percent
						else if (childActivitySet.equalsIgnoreCase("atLeastPercent")) {

							int rollupCount = 0;
							BigDecimal minimamPercent;
							CachedNode countNode = rollupRuleNodes[i].selectSingleChildNode("@minimumPercent");
							if (countNode == null) {
								minimamPercent = new BigDecimal(Default.getValue("rollupRules/rollupRule/@minimumPercent"));
							}
							else {
								minimamPercent = new BigDecimal(countNode.getNodeValue());
							}

							for (int j = 0; j < rollupBag.length; j++) {
								if (rollupBag[j].equalsIgnoreCase("true")) {
									rollupCount++;
								}
							}
							if ((BigDecimal.valueOf(rollupCount).divide(BigDecimal.valueOf(rollupBag.length), 4, BigDecimal.ROUND_HALF_UP)).compareTo(minimamPercent) >= 0) {
								statusChange = true;
							}
							else {
								statusChange = false;
							}
						}

						if (statusChange) {
							// Trace <applied>
							rolluprulecheckTraceItem.appendChild("applied", "true");
							return true;
						}
					}
				}
				// Trace <applied>
				rolluprulecheckTraceItem.appendChild("applied", "false");
				return false;
			}
			finally {
				// Trace End <evaluaterule>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("ロールアップルールチェックに失敗しました。(RollupRuleCheckSubprocess failed)", e);
		}
	}

	/**
	 * Evaluate Rollup Condition Subprocess
	 * ロールアップ時の子アクティビティとして評価結果を返す<BR>
	 * @return true 評価値 真<BR>
	 *          false 評価値 偽<BR>
	 *          unknown 評価値 不明<BR>
	 */
	private String doEvaluateRollupConditionsSubprocess(Activity activity, CachedNode[] rollupConditionNodes, String conditionCombination) throws SystemException {

		try {
			String evaluation = "unknown";

			// conditionごとの判定
			String[] conditionBag = new String[rollupConditionNodes.length];

			for (int i = 0; i < rollupConditionNodes.length; i++) {
				// Trace Start <rollupconditions>
				TraceItem rollupconditionsTraceItem = trace.startTrace("rollupconditions");

				try {
					// conditionの取得
					String condition;

					CachedNode conditionNode = rollupConditionNodes[i].selectSingleChildNode("@condition");
					condition = conditionNode.getNodeValue();
					// Trace <condition>
					rollupconditionsTraceItem.appendChild("condition", condition);
					// Trace <activityid>
					rollupconditionsTraceItem.appendChild("activityid", activity.getIdentifier());
					// Trace <objectiveid>
					rollupconditionsTraceItem.appendChild("objectiveid", activity.getObjectiveContributeToRollup().getObjectiveID());

					// condition の評価
					if (condition.equalsIgnoreCase("satisfied")) {
						// Trace <objectiveprogressstatus>
						rollupconditionsTraceItem.appendChild("objectiveprogressstatus", Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveProgressStatus(activity.getUseCurrentAttempt())));
						if (activity.getObjectiveContributeToRollup().getObjectiveProgressStatus(activity.getUseCurrentAttempt())) {
							conditionBag[i] = Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveSatisfiedStatus(activity.getUseCurrentAttempt()));
							// Trace <objectivesatisfiedstatus>
							rollupconditionsTraceItem.appendChild("objectivesatisfiedstatus", Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveSatisfiedStatus(activity.getUseCurrentAttempt())));
						}
						else {
							conditionBag[i] = "unknown";
						}
					}
					else if (condition.equalsIgnoreCase("objectiveStatusKnown")) {
						// objective satisfied known の評価
						conditionBag[i] = Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveProgressStatus(activity.getUseCurrentAttempt()));
						// Trace <objectiveprogressstatus>
						rollupconditionsTraceItem.appendChild("objectiveprogressstatus", Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveProgressStatus(activity.getUseCurrentAttempt())));
					}
					else if (condition.equalsIgnoreCase("objectiveMeasureKnown")) {
						// objective satisfied known の評価
						conditionBag[i] = Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveMeasureStatusForEvaluation());
						// Trace <objectivemeasurestatus>
						rollupconditionsTraceItem.appendChild("objectivemeasurestatus", Boolean.toString(activity.getObjectiveContributeToRollup().getObjectiveMeasureStatusForEvaluation()));
					}
					else if (condition.equalsIgnoreCase("completed")) {
						// Trace <attemptprogressstatus>
						rollupconditionsTraceItem.appendChild("attemptprogressstatus", Boolean.toString(activity.getProgress().getAttemptProgressStatus(activity.getUseCurrentAttempt())));
						if (activity.getProgress().getAttemptProgressStatus(activity.getUseCurrentAttempt())) {
							// completed の評価
							conditionBag[i] = Boolean.toString(activity.getProgress().getAttemptCompletionStatus(activity.getUseCurrentAttempt()));
							// Trace <attemptcompletionstatus>
							rollupconditionsTraceItem.appendChild("attemptcompletionstatus", Boolean.toString(activity.getProgress().getAttemptCompletionStatus(activity.getUseCurrentAttempt())));
						}
						else {
							conditionBag[i] = "unknown";
						}
					}
					else if (condition.equalsIgnoreCase("activityProgressKnown")) {
						// activity progress known の評価
						conditionBag[i] = Boolean.toString(activity.getActivityProgressStatus());
						// Trace <attemptprogressstatus>
						rollupconditionsTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
					}
					else if (condition.equalsIgnoreCase("attempted")) {
						// attempted の評価
						if(activity.getActivityProgressStatus() && activity.getActivityAttemptCount() > 0){
							conditionBag[i] = "true";
						}
						else{
							conditionBag[i] = "false";
						}

						// Trace <activityprogressstatus>
						rollupconditionsTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
					}
					else if (condition.equalsIgnoreCase("attemptLimitExceeded")) {
						// attempt limit exceeded の評価
						if (doLimitConditionsCheckProcess(activity, "attemptLimit")) {
							conditionBag[i] = "true";
						}
						else {
							conditionBag[i] = "false";
						}
					}
					else if (condition.equalsIgnoreCase("timeLimitExceeded")) {
						// time limit exceeded の評価
						if (doLimitConditionsCheckProcess(activity, "attemptExperiencedDurationLimit")) {
							conditionBag[i] = "true";
						}
						else if (doLimitConditionsCheckProcess(activity, "attemptAbsoluteDurationLimit")) {
							conditionBag[i] = "true";
						}
						else if (doLimitConditionsCheckProcess(activity, "activityAbsoluteDurationLimit")) {
							conditionBag[i] = "true";
						}
						else if (doLimitConditionsCheckProcess(activity, "activityExperiencedDurationLimit")) {
							conditionBag[i] = "true";
						}
						else {
							conditionBag[i] = "false";
						}
					}
					else if (condition.equalsIgnoreCase("outsideAvailableTimeRange")) {
						// Outside Available Time Range の評価
						if (doLimitConditionsCheckProcess(activity, "beginTimeLimit")) {
							conditionBag[i] = "true";
						}
						else if (doLimitConditionsCheckProcess(activity, "endTimeLimit")) {
							conditionBag[i] = "true";
						}
						else {
							conditionBag[i] = "false";
						}
					}
					else {
						// それ以外はNG
						throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][rollupCondition/@condition=" + condition + "]");
					}
					// operator の取得
					String ope;
					CachedNode opeNode = rollupConditionNodes[i].selectSingleChildNode("@operator");
					if (opeNode == null) {
						ope = Default.getValue("rollupRules/rollupRule/rollupConditions/rollupCondition/@operator");
					}
					else {
						ope = opeNode.getNodeValue();
					}

					// operetor が "not" なら判定結果を反転する
					if (ope.equalsIgnoreCase("not")) {
						if (conditionBag[i] == "true"){
							conditionBag[i] = "false";
						}
						else if (conditionBag[i] == "false"){
							conditionBag[i] = "true";
						}						
					}
					else if (!ope.equalsIgnoreCase("noOp")) {
						throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][rollupCondition/@operator=" + ope + "]");
					}
					// Trace <operatedevaluation>
					rollupconditionsTraceItem.appendChild("operatedevaluation", conditionBag[i]);
				}
				finally {
					// Trace End <rollupcondition>
					trace.endTrace();
				}
			}

			if (conditionBag.length == 0) {
				return evaluation;
			}

			// condition combination による評価結果の比較
			if (conditionCombination.equalsIgnoreCase("all")) {
				// condition combination = "all" の場合
				for (int i = 0; i < conditionBag.length; i++) {
					if (conditionBag[i]=="false") {
						return "false";
					}
					else if(conditionBag[i]=="unknown"){
						return "unknown";
					}
				}
				return "true";
			}
			else if (conditionCombination.equalsIgnoreCase("any")) {
				// condition combination = "any" の場合
				for (int i = 0; i < conditionBag.length; i++) {
					if (conditionBag[i]=="true") {
						return "true";
					}
					else if(conditionBag[i]=="unknown"){
						return "unknown";
					}
				}
				return "false";
			}
			else {
				throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][rollupConditions/@conditionCombination=" + conditionCombination + "]");
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("ロールアップルールの評価に失敗しました。(EvaluateRollupConditionsSubprocess failed)", e);
		}
	}

	/**
	 * Check Childe for Rollup Subprocess
	 * 子Activity情報判定サブプロセス
	 * @param activity
	 * @param rollupAction
	 * @return boolean child is Included in Rollup
	 */
	private boolean doCheckChildforRollupSubprocess(Activity activity, String rollupAction) throws SystemException {

		try {
			boolean included = false;
			if (rollupAction.equalsIgnoreCase("satisfied") || rollupAction.equalsIgnoreCase("notSatisfied")) {

				if (activity.getSequencing().getRollupObjectiveSatisfiedFlag()) {
					included = true;
					if ((rollupAction.equalsIgnoreCase("satisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForSatisfied").equalsIgnoreCase("ifNotSuspended"))
						|| (rollupAction.equalsIgnoreCase("notSatisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForNotSatisfied").equalsIgnoreCase("ifNotSuspended"))) {

					    if (activity.getActivityAttemptCount() > 0 && activity.isSuspended()) {
							included = false;
						}
					}
					else {
						if ((rollupAction.equalsIgnoreCase("satisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForSatisfied").equalsIgnoreCase("ifAttempted"))
							|| (rollupAction.equalsIgnoreCase("notSatisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForNotSatisfied").equalsIgnoreCase("ifAttempted"))) {

						    if (activity.getActivityAttemptCount() == 0){
								included = false;
							}
						}
						else {
							if ((rollupAction.equalsIgnoreCase("satisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForSatisfied").equalsIgnoreCase("ifNotSkipped"))
								|| (rollupAction.equalsIgnoreCase("notSatisfied") && activity.getSequencing().getRollupConsiderationValue("requiredForNotSatisfied").equalsIgnoreCase("ifNotSkipped"))) {

								// Apply the Sequencing Rules Check Process to the activity and its Skiped sequencing rules
								String[] actions = { "skip" };
								String apply = doSequencingRulesCheckProcess(activity, actions, "preConditionRule");
								if (apply != null && !apply.equalsIgnoreCase("")) {
									included = false;
								}
							}
						}
					}
				}
			}

			if (rollupAction.equalsIgnoreCase("completed") || rollupAction.equalsIgnoreCase("incomplete")) {

				if (activity.getSequencing().getRollupProgressCompletionFlag()) {
					included = true;
					if ((rollupAction.equalsIgnoreCase("completed") && activity.getSequencing().getRollupConsiderationValue("requiredForCompleted").equalsIgnoreCase("ifNotSuspended"))
						|| (rollupAction.equalsIgnoreCase("incomplete") && activity.getSequencing().getRollupConsiderationValue("requiredForIncomplete").equalsIgnoreCase("ifNotSuspended"))) {

						if (activity.getActivityProgressStatus() == true && activity.isSuspended()) {
							included = false;
						}
					}
					else {
						if ((rollupAction.equalsIgnoreCase("completed") && activity.getSequencing().getRollupConsiderationValue("requiredForCompleted").equalsIgnoreCase("ifAttempted"))
							|| (rollupAction.equalsIgnoreCase("incomplete") && activity.getSequencing().getRollupConsiderationValue("requiredForIncomplete").equalsIgnoreCase("ifAttempted"))) {

							if (activity.getActivityProgressStatus() == false) {
								included = false;
							}
						}
						else {
							if ((rollupAction.equalsIgnoreCase("completed") && activity.getSequencing().getRollupConsiderationValue("requiredForCompleted").equalsIgnoreCase("ifNotSkipped"))
								|| (rollupAction.equalsIgnoreCase("incomplete") && activity.getSequencing().getRollupConsiderationValue("requiredForIncomplete").equalsIgnoreCase("ifNotSkipped"))) {

								// Apply the Sequencing Rules Check Process to the activity and its Skiped sequencing rules
								String[] actions = { "skip" };
								String apply = doSequencingRulesCheckProcess(activity, actions, "preConditionRule");
								if (apply != null && !apply.equalsIgnoreCase("")) {
									included = false;
								}
							}
						}
					}
				}
			}
			return included;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Overall Rollup Process
	 * ロールアッププロセス
	 * @param activity
	 */
	private void doOverallRollupProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <rollup>
			trace.startTrace("rollup");
			try {
				ActivityPath path = new ActivityPath(rootActivity, activity);
				path.reverseList();

				if (path.isEmpty()) {
					return;
				}
				boolean chkresult;
				while (true) {
					Activity eachActivity = path.getNext();

					// * add pseudo code
					if (eachActivity.hasAvailableChildren()) {
						// * add pseudo code
						// Apply the CompletionAmountRollup Process
						doCompletionAmountRollupProcess(eachActivity);

						// Apply the Measure Rollup Process to the activity
						doMeasureRollupProcess(eachActivity);

						// Apply the apporpriate Objective Rollup Process to the activity
						chkresult = doObjectiveRollupUsingMeasureProcess(eachActivity);
						if(!chkresult){
							doObjectiveRollupUsingRulesProcess(eachActivity);
						}

						// Apply the Activity Progress Rollup Process to the activity
						doActivityProgressRollupProcess(eachActivity);
					}

					if (path.isLast()) {
						break;
					}
				}
			}
			finally {
				// Trace End <rollup>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Select Childeren Process
	 * セレクトルール実行プロセス
	 * @param activity
	 */
	private void doSelectChildrenProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <selectchildren>
			TraceItem selectchildrenTraceItem = trace.startTrace("selectchildren");

			try {
				// Trace <activityid>
				selectchildrenTraceItem.appendChild("activityid", activity.getIdentifier());

				if (!activity.hasChildren()) {
					return;
				}
				if (activity.isSuspended() || activity.isActive()) {
					// * delete pseudo code
				}
				else {
					String timing = activity.getSequencing().getSelectionTiming();
					// Case:the Selection Timing for the activity is Never
					if (timing.equalsIgnoreCase("never")) {

					}
					// Case:the Selection Timing for the activity is Once
					else if (timing.equalsIgnoreCase("once")) {

						// onceなのでAttemptCountが0なら以下をする
						if (!activity.getActivityProgressStatus() && !activity.getStatus().getSelectionStatus()) {

							// Trace <timing>
							selectchildrenTraceItem.appendChild("timing", timing);

							Integer count = activity.getSequencing().getSelectCount();

							if (count != null) {
								//カウントが0以下もしくは子アクティビティの数より大きい場合はすべてとする
								if ((count.intValue() <= 0) || (count.intValue() >= activity.getChildren().length)) {
									activity.setAvailableChildren(activity.getChildren());
								}
								else {
									//available children をリセットする
									activity.setAvailableChildren(null);

									Activity[] children = activity.getChildren();
									//乱数でアクティビティを選択する
									Random generator = new Random();

									int[] reorder = new int[children.length];

									for (int i = 0; i < reorder.length; i++) {
										reorder[i] = i;
									}

									for (int i = 0; i < reorder.length - 1; i++) {
										int reorderTarget = generator.nextInt(reorder.length);

										int save = reorder[reorderTarget];
										reorder[reorderTarget] = reorder[i];
										reorder[i] = save;
									}
									// * add pseudo code
									Activity[] availableChildren = new Activity[count.intValue()];

									Arrays.sort(reorder, 0, availableChildren.length);

									for (int i = 0; i < availableChildren.length; i++) {
										availableChildren[i] = children[reorder[i]];
										selectchildrenTraceItem.appendChild("availablechildren", availableChildren[i].getIdentifier());
									}

									for (int i = availableChildren.length; i < children.length; i++) {
										children[reorder[i]].removeAvailableChildren();
									}

									// 作成した available children をセット
									activity.setAvailableChildren(availableChildren);
									// セレクト済みフラグ設定
									activity.getStatus().setSelectionStatus(true);
								}
							}
						}
					}
				}
			}
			finally {
				// Trace End <selectchildren>
				trace.endTrace();
			}

			// 子アクティビティも実行
			// * add pseudo code
			Activity[] available = activity.getAvailableChildren();
			for (int i = 0; i < available.length; i++) {
				doSelectChildrenProcess(available[i]);
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Randomaize Children Process
	 * ランダマイズルール実行プロセス
	 * @param activity
	 */
	private void doRandomizeChildrenProces(Activity activity, boolean reorderChildrenFlag) throws SystemException {

		try {
			// Trace Start <randomizechildren>
			TraceItem randomizechildrenTraceItem = trace.startTrace("randomizechildren");

			try {
				// Trace <activityid>
				randomizechildrenTraceItem.appendChild("activityid", activity.getIdentifier());

				// 子アクティビティがなければ抜ける
				if (!activity.hasChildren()) {
					return;
				}

				// 有効な子供が存在しない場合は何もしない
				if (!activity.hasAvailableChildren()) {
					return;
				}

				// activity is suspended が true もしくは activity is active が true の場合は何もしない
				if ((activity.isSuspended()) || (activity.isActive())) {
					// * delete pseudo code
				}
				else {
					// 伝播の場合は常に実行
					if (reorderChildrenFlag) {
						randomelyAvailableChildren(activity);
					}
					else {
						String timing = activity.getSequencing().getRandomizationTiming();

						// Case:the Randomization Timing for the activity is Never
						if (timing.equalsIgnoreCase("never")) {
						}

						// Case:the Randomization Timing for the activity is Once
						else if (timing.equalsIgnoreCase("once")) {
							// onceなのでAttemptCountが0なら以下をする
							if (!activity.getActivityProgressStatus() && !activity.getStatus().getRandomizeStatus()) {
								// Trace <timing>
								randomizechildrenTraceItem.appendChild("timing", timing);
								randomelyAvailableChildren(activity);
								// ランダマイズフラグ設定
								activity.getStatus().setRandomizeStatus(true);
								reorderChildrenFlag = activity.getSequencing().getReorderChildren();
							}
						}

						// Case:the Randomization Timing for the activity is On Each New Attempt
						else if (timing.equalsIgnoreCase("onEachNewAttempt") && !activity.getStatus().getRandomizeStatus()) {
							// Trace <timing>
							randomizechildrenTraceItem.appendChild("timing", timing);
							randomelyAvailableChildren(activity);
							activity.getStatus().setRandomizeStatus(true);
							reorderChildrenFlag = activity.getSequencing().getReorderChildren();
						}
					}
				}
			}
			finally {
				// Trace End <randomizechildren>
				trace.endTrace();
			}

			// 伝播フラグが立っている場合は子供も実行
			if (reorderChildrenFlag) {
				Activity[] availableChildren = activity.getAvailableChildren();
				for (int i = 0; i < availableChildren.length; i++) {
					doRandomizeChildrenProces(availableChildren[i], reorderChildrenFlag);
				}
			}
			// 子アクティビティもランダマイズ実施
			else {
				// * add pseudo code
				Activity[] availableChildren = activity.getAvailableChildren();
				for (int i = 0; i < availableChildren.length; i++) {
					doRandomizeChildrenProces(availableChildren[i], false);
				}
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * 乱数を元に Available Children の順番を入れ替える<BR>
	 */
	private void randomelyAvailableChildren(Activity activity) {

		// トレースアイテム取得
		TraceItem randomizechildrenTraceItem = trace.getCurrentTraceItem();

		// 現在の available children を取得
		Activity[] availableChildren = activity.getAvailableChildren();
		if (availableChildren == null) {
			return;
		}

		//乱数でアクティビティを選択する
		Random generator = new Random();

		for (int i = 0; i < availableChildren.length - 1; i++) {
			int reorderTarget = generator.nextInt(availableChildren.length);

			Activity save = availableChildren[reorderTarget];
			availableChildren[reorderTarget] = availableChildren[i];
			availableChildren[i] = save;
		}

		// Trace <availablechildren>
		for (int i = 0; i < availableChildren.length; i++) {
			randomizechildrenTraceItem.appendChild("availablechildren", availableChildren[i].getIdentifier());
		}

		// 並び変えた available children を再セット
		activity.setAvailableChildren(availableChildren);

	}

	/**
	 * Flow Tree Traversal Subprocess
	 * トラバースサブプロセス
	 * @param activity
	 * @param traversalDirection
	 * @param considerChildrenFlag
	 * @param previousTraversalDirection
	 * @return nextActivity
	 */
	private FlowTreeReturnItem doFlowTreeTraversalSubprocess(Activity activity, String traversalDirection, boolean considerChildrenFlag, String previousTraversalDirection)
		throws SequencingException, SystemException {

		try {

			boolean reversedDirection = false;
			if (previousTraversalDirection != null && previousTraversalDirection.equalsIgnoreCase("backward") && activity.isAvailableLast()) {
				traversalDirection = "backward";
				activity = activity.getParent().getAvailableChildren()[0];
				reversedDirection = true;
			}
			if (traversalDirection.equalsIgnoreCase("forward")) {
				if (!activity.canAvailableForward()) {
					throw SequencingException.getInstance("SB.2.1-1", "[ActivityID:" + activity.getIdentifier() + "]", null);
				}
				// * edit pseudo code
				if (!activity.hasAvailableChildren() || !considerChildrenFlag) {
					
					if (activity.isAvailableLast()) {
						try {
							// * add pseudo code
							if(activity.isRoot()){
								throw SequencingException.getInstance("PseudoCodeException","PseudoCodeException。(FlowTreeTraversalSubprocess failed) [ActivityID:" + activity.getIdentifier() + "][traversalDirection:" + traversalDirection + "]",null);
							}
							// Apply the Flow Tree Traversal Subprocess to the activity's parent
							return doFlowTreeTraversalSubprocess(activity.getParent(), "forward", false, null);
						}
						catch (SequencingException e) {
							throw e;
						}

					}
					else {
						Activity[] availableChildrens = activity.getParent().getAvailableChildren();
						int order = activity.getAvailableOrder();
						FlowTreeReturnItem returnItem = new FlowTreeReturnItem();
						returnItem.setReturnActivity(availableChildrens[order + 1]);
						returnItem.setTraversalDirection(traversalDirection);
						return returnItem;
					}
				}
				else {

					if (activity.hasAvailableChildren()) {
						FlowTreeReturnItem returnItem = new FlowTreeReturnItem();
						returnItem.setReturnActivity(activity.getAvailableChildren()[0]);
						returnItem.setTraversalDirection(traversalDirection);
						return returnItem;
					}
					else {
						throw SequencingException.getInstance("SB.2.1-2", "[ActivityID:" + activity.getIdentifier() + "]", null);
					}
				}
			}
			if (traversalDirection.equalsIgnoreCase("backward")) {

				if (activity.isRoot()) {
					throw SequencingException.getInstance("SB.2.1-3", "[ActivityID:" + activity.getIdentifier() + "]", null);
				}

				if (!activity.hasAvailableChildren() || !considerChildrenFlag) {
					if (!reversedDirection) {
						// Trace <evaluatecontrolmode>
						traceControlMode(activity.getParent(), "forwardOnly");

						if (activity.getParent().getForwardOnlyFlag()) {
							throw SequencingException.getInstance("SB.2.1-4", "[ActivityID:" + activity.getParent().getIdentifier() + "]", null);
						}
					}

					if (activity.isAvailableFirst()) {
						try {
							// Apply the Flow Tree Traversal Subprocess to the activity's parent
							return doFlowTreeTraversalSubprocess(activity.getParent(), "backward", false, null);
						}
						catch (SequencingException e) {
							throw e;
						}
					}
					else {
						Activity[] availableChildrens = activity.getParent().getAvailableChildren();
						int order = activity.getAvailableOrder();
						FlowTreeReturnItem returnItem = new FlowTreeReturnItem();
						returnItem.setReturnActivity(availableChildrens[order - 1]);
						returnItem.setTraversalDirection(traversalDirection);
						return returnItem;
					}
				}
				else {
					if (activity.hasAvailableChildren()) {

						// Trace <evaluatecontrolmode>
						traceControlMode(activity, "forwardOnly");
						if (activity.getForwardOnlyFlag() || activity.isRoot()) {
							FlowTreeReturnItem returnItem = new FlowTreeReturnItem();
							returnItem.setReturnActivity(activity.getAvailableChildren()[0]);
							returnItem.setTraversalDirection("forward");
							return returnItem;
						}
						else {
							FlowTreeReturnItem returnItem = new FlowTreeReturnItem();
							returnItem.setReturnActivity(activity.getAvailableChildren()[activity.getAvailableChildren().length - 1]);
							returnItem.setTraversalDirection("backward");
							return returnItem;
						}
					}
					else {
						throw SequencingException.getInstance("SB.2.1-2", "[ActivityID:" + activity.getIdentifier() + "]", null);
					}

				}
			}
			throw new SystemException("フローに失敗しました。(FlowTreeTraversalSubprocess failed) [ActivityID:" + activity.getIdentifier() + "][traversalDirection:" + traversalDirection + "]");
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * FlowTreeTraversalReturnItemクラス
	 * FlowTreeTraversalが返却するActivityとtraversal directionの値を保持するクラス
	 */
	private static class FlowTreeReturnItem {

		/**
		 * 返却されるActivity
		 */
		private Activity returnActivity;

		/**
		 * 返却されるtraversal direction
		 */
		private String traversalDirection;

		/**
		 * アクティビティを取得する
		 *
		 * @return アクティビティ
		 */
		public Activity getReturnActivity() {
			return returnActivity;
		}

		/**
		 * TraversalDirectionを取得する
		 *
		 * @return TraversalDirection
		 */
		public String getTraversalDirection() {
			return traversalDirection;
		}

		/**
		 * アクティビティを設定する
		 *
		 * @param activity アクティビティ
		 */
		public void setReturnActivity(Activity activity) {
			returnActivity = activity;
		}

		/**
		 * TraversalDirectionを設定する
		 *
		 * @param string TraversalDirection
		 */
		public void setTraversalDirection(String string) {
			traversalDirection = string;
		}
	}

	/**
	 * Flow Activity Traversal Subprocess
	 * Activityトラバースサブプロセス
	 * @param activity
	 * @param traversalDirection
	 * @param previousTraversalDirection
	 * @return nextActivity
	 */
	private Activity doFlowActivityTraversalSubprocess(Activity activity, String traversalDirection, String previousTraversalDirection) throws SequencingException, SystemException {

		try {
			// * add pseudo code
			if (!activity.isRoot()) {
				// Trace <evaluatecontrolmode>
				traceControlMode(activity.getParent(), "flow");
				if (!activity.getParent().getFlowFlag()) {
					throw SequencingException.getInstance("SB.2.2-1", "[ActivityID:" + activity.getParent().getIdentifier() + "]", null);
				}
			}

			// Apply the Flow Tree Traversal Subprocess to the activity
			String[] actions = { "skip" };
			String apply = doSequencingRulesCheckProcess(activity, actions, "preConditionRule");
			if (apply != null && !apply.equalsIgnoreCase("")) {
				FlowTreeReturnItem returnItem;
				// Apply the Flow Tree Traversal Subprocess to the activity
				try {
					returnItem = doFlowTreeTraversalSubprocess(activity, traversalDirection, false, previousTraversalDirection);

				}
				// If the Flow Tree Traversal Subprocess does not identify an activity Then
				catch (SequencingException e) {
					throw e;
				}
				// Else
				if (traversalDirection.equalsIgnoreCase("backward") && returnItem.getTraversalDirection().equalsIgnoreCase("backward")) {
					try {
						// Apply the Flow Activity Traversal Subprocess to the activity identified
						return doFlowActivityTraversalSubprocess(returnItem.getReturnActivity(), traversalDirection, null);
					}
					catch (SequencingException e) {
						throw e;
					}
				}
				else {
					try {
						// Apply the Flow Activity Traversal Subprocess to the activity identified
						return doFlowActivityTraversalSubprocess(returnItem.getReturnActivity(), traversalDirection, previousTraversalDirection);
					}
					catch (SequencingException e) {
						throw e;
					}
				}
			}

			// Apply the Check Activity Process to the activity
			boolean evaluate = doCheckActivityProcess(activity);

			if (evaluate) {
				throw SequencingException.getInstance("SB.2.2-2", "[ActivityID:" + activity.getIdentifier() + "]", null);
			}
			if (activity.hasAvailableChildren()) {
				FlowTreeReturnItem returnItem;
				try {
					returnItem = doFlowTreeTraversalSubprocess(activity, traversalDirection, true, null);
					// If the Flow Tree Traversal Subprocess does not identify an activity
				}
				catch (SequencingException e) {
					throw e;
				}
				// Else
				if (traversalDirection.equalsIgnoreCase("backward") && returnItem.getTraversalDirection().equalsIgnoreCase("forward")) {
					// Apply the Flow Activity Traversal Subprocess to the activity identified
					try {
						return doFlowActivityTraversalSubprocess(returnItem.getReturnActivity(), "forward", "backward");
					}
					catch (SequencingException e) {
						throw e;
					}
				}
				else {
					// Apply the Flow Activity Traversal Subprocess to the activity identified
					try {
						return doFlowActivityTraversalSubprocess(returnItem.getReturnActivity(), traversalDirection, null);
					}
					catch (SequencingException e) {
						throw e;
					}
				}

			}
			return activity;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Flow Subprocess
	 * フローサブプロセス
	 * @param activity
	 * @param traversalDirection
	 * @param considerChildrenFlag
	 * @return identialActivity
	 */
	private Activity doFlowSubprocess(Activity activity, String traversalDirection, boolean considerChildrenFlag) throws SequencingException, SystemException {
		try {

			Activity candidate = null;
			try {
				candidate = doFlowTreeTraversalSubprocess(activity, traversalDirection, considerChildrenFlag, null).getReturnActivity();
			}
			// If the Flow Tree Traversal Subprocess does not identify an activity Then
			catch (SequencingException e) {
				throw e;
			}
			// Else
			try {
				return doFlowActivityTraversalSubprocess(candidate, traversalDirection, null);
			}
			catch (SequencingException e) {
				throw e;
			}
		}
		catch (SystemException e) {
			throw e;
		}

	}

	/**
	 * Chice Activity Traversal Subprocess
	 * 子Activityトラバースサブプロセス
	 * @param activity
	 * @param traversalDirection
	 * @return Reachable
	 */
	private boolean doChoiceActivityTraversalSubprocess(Activity activity, String traversalDirection) throws SequencingException, SystemException {
		try {
			if (traversalDirection.equalsIgnoreCase("forward")) {
				String[] actions = { "stopForwardTraversal" };
				String apply = doSequencingRulesCheckProcess(activity, actions, "preConditionRule");
				if (apply != null && !apply.equalsIgnoreCase("")) {
					throw SequencingException.getInstance("SB.2.4-1", "[ActivityID:" + activity.getIdentifier() + "]", null);
				}
				return true;
			}

			if (traversalDirection.equalsIgnoreCase("backward")) {
				if (!activity.isRoot()) {
					// Trace <evaluatecontrolmode>
					traceControlMode(activity.getParent(), "forwardOnly");
					if (activity.getParent().getForwardOnlyFlag()) {
						throw SequencingException.getInstance("SB.2.4-2", "[ActivityID:" + activity.getParent().getIdentifier() + "]", null);
					}
				}
				else {
					throw SequencingException.getInstance("SB.2.4-3", "[ActivityID:" + activity.getIdentifier() + "]", null);
				}
				return true;
			}

			throw new SystemException("チョイスに失敗しました。(ChoiceActivityTraversalSubprocess failed) [ActivityID:" + activity.getIdentifier() + "][traversalDirection:" + traversalDirection + "]");
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Start Sequencing Request Process
	 * Startシーケンシングリクエストプロセス
	 */
	private void doStartSequencingRequestProcess() throws SequencingException, SystemException {

		try {

			if (currentActivity != null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.5-1", "[CurrentActivityID:" + currentActivity.getIdentifier() + "]", null);
			}
			if (!rootActivity.hasChildren()) {
				identifiedActivity = rootActivity;
				deliveryRequest = true;
			}
			else {
				try {
					// Apply the Flow Subprocess to the root of the activity tree
					identifiedActivity = doFlowSubprocess(rootActivity, "forward", true);
				}
				// If the Flow Subprocess returns False
				catch (SequencingException e) {
					deliveryRequest = false;
					throw e;
				}
				// Else
				deliveryRequest = true;
			}
		}
		catch (SystemException e) {
			throw e;
		}

	}

	/**
	 * Resume All Sequencing Request Process
	 * ResumeAllシーケンシングリクエストプロセス
	 */
	private void doResumeAllSequencingRequestProcess() throws SequencingException, SystemException {

		try {
			if (currentActivity != null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.6-1", "[CurrentActivityID:" + currentActivity.getIdentifier() + "]", null);
			}
			if (suspendedActivity == null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.6-2", null, null);
			}
			identifiedActivity = suspendedActivity;
			deliveryRequest = true;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Continue Sequencing Request Process
	 * Continueシーケンシングリクエストプロセス
	 */
	private void doContinueSequencingRequestProcess() throws SequencingException, SystemException {

		try {
			if (currentActivity == null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.7-1", null, null);
			}
			if (!currentActivity.isRoot()) {
				// Trace <evaluatecontrolmode>
				traceControlMode(currentActivity.getParent(), "flow");
				if (!currentActivity.getParent().getFlowFlag()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.7-2", "[ActivityID:" + currentActivity.getParent().getIdentifier() + "]", null);
				}
			}
			try {
				identifiedActivity = doFlowSubprocess(currentActivity, "forward", false);
			}
			// If the Flow Subprocess returns false
			catch (SequencingException e) {
				deliveryRequest = false;
				throw e;
			}
			deliveryRequest = true;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Previous Sequencing Request Process
	 * Previousシーケンシングリクエストプロセス
	 */
	private void doPreviousSequencingRequestProcess() throws SequencingException, SystemException {

		try {

			if (currentActivity == null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.8-1", null, null);
			}
			if (!currentActivity.isRoot()) {
				// Trace <evaluatecontrolmode>
				traceControlMode(currentActivity.getParent(), "flow");
				if (!currentActivity.getParent().getFlowFlag()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.8-2", "[ActivityID:" + currentActivity.getParent().getIdentifier() + "]", null);
				}
			}
			try {
				identifiedActivity = doFlowSubprocess(currentActivity, "backward", false);
			}
			// If the Flow Subprocess returns false
			catch (SequencingException e) {
				deliveryRequest = false;
				throw e;
			}
			deliveryRequest = true;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Choice Sequencing Request Process
	 * Choiceシーケンシングリクエストプロセス
	 */
	private void doChoiceSequencingRequestProcess() throws SequencingException, SystemException {

		try {
			if (targetActivity == null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.9-1", null, null);
			}
			if (!targetActivity.isRoot()) {
				if (!targetActivity.isAvailable()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-2", "[TargetActivityID:" + targetActivity.getIdentifier() + "]", null);
				}
			}

			ActivityPath path = new ActivityPath(rootActivity, targetActivity);

			while (true) {
				Activity eachActivity = path.getNext();

				// Apply the Sequencing Rules Check Process to the activity
				String[] actions = { "hiddenFromChoice" };
				String apply = doSequencingRulesCheckProcess(eachActivity, actions, "preConditionRule");
				if (apply != null && !apply.equalsIgnoreCase("")) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-3", "[TargetActivityID:" + eachActivity.getIdentifier() + "]", null);
				}

				if (path.isLast()) {
					break;
				}
			}
			if (!targetActivity.isRoot()) {

				// Trace <evaluatecontrolmode>
				traceControlMode(targetActivity.getParent(), "choice");
				if (!targetActivity.getParent().getChoiceFlag()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-4", "[ActivityID:" + targetActivity.getParent().getIdentifier() + "]", null);
				}
			}

			Activity commonAncestor;
			if (currentActivity != null) {
				commonAncestor = ActivityPath.getCommonParent(currentActivity, targetActivity);
				if (commonAncestor == null) {
					commonAncestor = rootActivity;
				}
			}
			else {
				commonAncestor = rootActivity;
			}

			// Case: CurrentActivity and target activity are identical
			if (ActivityPath.checkTarget(currentActivity, targetActivity) == ActivityPath.SAME_ACTIVITY) {
				// Break All Cases
			}

			// Case: Current Activity and the target activity are siblings
			else if (ActivityPath.checkTarget(currentActivity, targetActivity) == ActivityPath.SIBLING) {
				ActivityPath siblingPath = new ActivityPath(currentActivity, targetActivity);
				siblingPath.removeLast();
				if (siblingPath.isEmpty()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-5", null, null);
				}
				String travers = null;
				if (ActivityPath.isForward(targetActivity, currentActivity)) {
					travers = "forward";
				}
				else {
					travers = "backward";
				}
				while (true) {
					Activity eachActivity = siblingPath.getNext();

					// Apply the Choice Activity Traversal Subprocess to the activity
					try {
						doChoiceActivityTraversalSubprocess(eachActivity, travers);
					}
					// If the Choice Activity Traversal Subprocess returns False
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					if (siblingPath.isLast()) {
						break;
					}
				}
			}

			// Case: CurrentActivity and common ancestor are the same Or CurrentActivity is Not Difined
			else if (ActivityPath.checkTarget(currentActivity, commonAncestor) == ActivityPath.SAME_ACTIVITY || currentActivity == null) {
				ActivityPath treePath = new ActivityPath(commonAncestor, targetActivity);
				treePath.removeLast();
				if (treePath.isEmpty()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-5", null, null);
				}
				while (true) {
					Activity eachActivity = treePath.getNext();

					// Apply the Choice Activity Traversal Subprocess to the activity
					try {
						doChoiceActivityTraversalSubprocess(eachActivity, "forward");
					}
					// If the Choice Activity Traversal Subprocess returns False
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					boolean preventActivation = eachActivity.getSequencing().getConstrainedChoiceConsiderationFlag("preventActivation");
					if (!eachActivity.isActive() && (ActivityPath.checkTarget(commonAncestor, eachActivity) != ActivityPath.SAME_ACTIVITY) && preventActivation) {
						deliveryRequest = false;
						throw SequencingException.getInstance("SB.2.9-6", "[ActivityID:" + eachActivity.getIdentifier() + "]", null);
					}
					if (treePath.isLast()) {
						break;
					}
				}
			}

			// Case: Target activity is the common ancestor of the Current Activity
			else if (ActivityPath.checkTarget(targetActivity, currentActivity) == ActivityPath.ACT1_ACTIVITY_IS_COMMON_ANCESTOR) {

				ActivityPath treePath = new ActivityPath(currentActivity, targetActivity);
				if (treePath.isEmpty()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-5", null, null);
				}

				Activity constrained = null;
				while (true) {
					Activity eachActivity = treePath.getNext();

					if (!treePath.isLast()) {
						// Trace <evaluatecontrolmode>
						traceControlMode(eachActivity, "choiceExit");

						if (!eachActivity.getParent().getChoiceExitFlag()) {
							deliveryRequest = false;
							throw SequencingException.getInstance("SB.2.9-7", "[ActivityID:" + eachActivity.getParent().getIdentifier() + "]", null);
						}
					}
					if (constrained == null) {
						boolean constrainChoice = eachActivity.getSequencing().getConstrainedChoiceConsiderationFlag("constrainChoice");
						if (constrainChoice) {
							constrained = eachActivity;
						}
					}
					if (treePath.isLast()) {
						break;
					}
				}

				if (constrained != null) {
					String travers = null;
					if (ActivityPath.isForward(targetActivity, constrained)) {
						travers = "forward";
					}
					else {
						travers = "backward";
					}

					// Apply the Choice Activity Traversal Subprocess to the activity
					Activity consider = doChoiceFlowSubprocess(constrained, travers);
					if (ActivityPath.checkTarget(targetActivity, consider) != ActivityPath.ACT2_ACTIVITY_IS_COMMON_ANCESTOR
						&& (ActivityPath.checkTarget(targetActivity, constrained) != ActivityPath.SAME_ACTIVITY || ActivityPath.checkTarget(targetActivity, consider) != ActivityPath.SAME_ACTIVITY)) {
						deliveryRequest = false;
						throw SequencingException.getInstance("SB.2.9-8", "[ConstrainedActivityID:" + constrained.getIdentifier() + "]", null);
					}
				}
			}

			// Case: Target activity is forward from the common ancestor activity
			else if (ActivityPath.isForward(targetActivity, commonAncestor)) {

				ActivityPath treePath = new ActivityPath(currentActivity, commonAncestor);
				if (treePath.isEmpty()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-5", null, null);
				}

				Activity constrained = null;
				while (true) {
					Activity eachActivity = treePath.getNext();

					if (!treePath.isLast()) {
						// Trace <evaluatecontrolmode>
						traceControlMode(eachActivity, "choiceExit");
						if (!eachActivity.getChoiceExitFlag()) {
							deliveryRequest = false;
							throw SequencingException.getInstance("SB.2.9-7", "[ActivityID:" + eachActivity.getIdentifier() + "]", null);
						}
					}
					if (constrained == null) {
						boolean constrainChoice = eachActivity.getSequencing().getConstrainedChoiceConsiderationFlag("constrainChoice");

						if (constrainChoice) {
							constrained = eachActivity;
						}
					}
					if (treePath.isLast()) {
						break;
					}
				}

				if (constrained != null) {
					String travers = null;
					if (ActivityPath.isForward(targetActivity, constrained)) {
						travers = "forward";
					}
					else {
						travers = "backward";
					}

					// Apply the Choice Activity Traversal Subprocess to the activity
					Activity consider = doChoiceFlowSubprocess(constrained, travers);
					if (ActivityPath.checkTarget(targetActivity, consider) != ActivityPath.ACT2_ACTIVITY_IS_COMMON_ANCESTOR
						&& (ActivityPath.checkTarget(targetActivity, constrained) != ActivityPath.SAME_ACTIVITY || ActivityPath.checkTarget(targetActivity, consider) != ActivityPath.SAME_ACTIVITY)) {
						deliveryRequest = false;
						throw SequencingException.getInstance("SB.2.9-8", "[ConstrainedActivityID:" + constrained.getIdentifier() + "]", null);
					}
				}

				treePath = new ActivityPath(commonAncestor, targetActivity);
				treePath.removeLast();

				if (treePath.isEmpty()) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.9-5", null, null);
				}

				if (ActivityPath.isForward(targetActivity, currentActivity)) {

					while (true) {
						Activity eachActivity = treePath.getNext();
						// Apply the Choice activity Traversal Subprocess to the activity in the Forward
						try {
							doChoiceActivityTraversalSubprocess(eachActivity, "forward");
						}
						// If the Choice Activity Traversal Subprocess returns False Then
						catch (SequencingException e) {
							deliveryRequest = false;
							throw e;
						}
						boolean preventActivation = eachActivity.getSequencing().getConstrainedChoiceConsiderationFlag("preventActivation");
						if (!eachActivity.isActive() && (ActivityPath.checkTarget(eachActivity, commonAncestor) != ActivityPath.SAME_ACTIVITY && preventActivation)) {
							throw SequencingException.getInstance("SB.2.9-6", "[ActivityID:" + eachActivity.getIdentifier() + "]", null);
						}
						if (treePath.isLast()) {
							break;
						}
					}
				}
				else {
					while (true) {
						Activity eachActivity = treePath.getNext();
						boolean preventActivation = eachActivity.getSequencing().getConstrainedChoiceConsiderationFlag("preventActivation");
						if (!eachActivity.isActive() && (ActivityPath.checkTarget(eachActivity, commonAncestor) != ActivityPath.SAME_ACTIVITY && preventActivation)) {
							throw SequencingException.getInstance("SB.2.9-6", "[ActivityID:" + eachActivity.getIdentifier() + "]", null);
						}
						if (treePath.isLast()) {
							break;
						}
					}

				}
			}
			if (!targetActivity.hasAvailableChildren()) {
				identifiedActivity = targetActivity;
				deliveryRequest = true;
				return;
			}

			try {
				// Apply the Flow Subprocess to the target activity
				identifiedActivity = doFlowSubprocess(targetActivity, "forward", true);
			}
			// If the Flow Subprocess returns False
			catch (SequencingException e) {
				// Apply the Terminate Descendent Attempts Process to the common ancestor
				doTerminateDescendentAttemptsProcess(commonAncestor);
				doEndAttemptProcess(commonAncestor);
				currentActivity = targetActivity;
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.9-9", "[ActivityID:" + targetActivity.getIdentifier() + "]", e);
			}
			deliveryRequest = true;
			return;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Choice Flow Subprocess
	 * Choiceフローサブプロセス
	 * @param activity
	 * @return Idetified Activity
	 */
	private Activity doChoiceFlowSubprocess(Activity activity, String traversalDirection) throws SystemException {

		try {
			// Apply the Choice Flow Tree Traversal Subprocess to the activity
			Activity identified = doChoiceFlowTreeTraversalSubprocess(activity, traversalDirection);
			if (identified == null) {
				return activity;
			}
			else {
				return identified;
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Choice Flow Tree Traversal Subprocess
	 * Choiceトラバースサブプロセス
	 * @param activity
	 * @param traversalDirection
	 * @return next Activity
	 */
	private Activity doChoiceFlowTreeTraversalSubprocess(Activity activity, String traversalDirection) throws SystemException {
		try {
			if (traversalDirection.equalsIgnoreCase("forward")) {
				// * add pseudo code
				if (activity.isRoot()) {
					return null;
				}
				if (!activity.canAvailableForward()) {
					return null;
				}
				if (activity.isAvailableLast()) {
					Activity result = doChoiceFlowTreeTraversalSubprocess(activity.getParent(), "forward");
					return result;
				}
				else {
					Activity[] availableChildrens = activity.getParent().getAvailableChildren();
					int order = activity.getAvailableOrder();
					return availableChildrens[order + 1];
				}
			}
			if (traversalDirection.equalsIgnoreCase("backward")) {
				if (activity.isRoot()) {
					// * add pseudo code
					return null;
				}
				if (activity.isAvailableFirst()) {
					Activity result = doChoiceFlowTreeTraversalSubprocess(activity.getParent(), "backward");
					return result;
				}
				else {
					Activity[] availableChildrens = activity.getParent().getAvailableChildren();
					int order = activity.getAvailableOrder();
					return availableChildrens[order - 1];
				}
			}
			throw new SystemException("チョイスに失敗しました。(ChoiceFlowTreeTraversalSubprocess failed) [ActivityID:" + activity.getIdentifier() + "][traversalDirection:" + traversalDirection + "]");
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Retry Sequencing Request Process
	 * Retryシーケンシングリクエストプロセス
	 */
	private void doRetrySequencingRequestProcess() throws SequencingException, SystemException {

		try {
			if (currentActivity == null) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.10-1", null, null);
			}
			if (currentActivity.isActive() || currentActivity.isSuspended()) {
				deliveryRequest = false;
				throw SequencingException.getInstance("SB.2.10-2", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
			}
			if (currentActivity.hasAvailableChildren()) {
				try {
					identifiedActivity = doFlowSubprocess(currentActivity, "forward", true);
				}
				// If the Flow Subprocess Request Process
				catch (SequencingException e) {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.10-3", "[ActivityID:" + currentActivity.getIdentifier() + "]", e);
				}
				// Else
				deliveryRequest = true;
				return;
			}
			identifiedActivity = currentActivity;
			deliveryRequest = true;
			return;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Exit Sequencing Request Process
	 * Exitシーケンシングリクエストプロセス
	 * @return End Sequencing Session
	 */
	private boolean doExitSequencingRequestProcess() throws SequencingException, SystemException {

		try {
			if (currentActivity == null) {
				throw SequencingException.getInstance("SB.2.11-1", null, null);
			}
			if (currentActivity.isActive()) {
				throw SequencingException.getInstance("SB.2.11-2", "[ActivityID:" + currentActivity.getIdentifier() + "]", null);
			}
			if (currentActivity.isRoot()) {
				return true;
			}
			return false;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Sequencing Rrequest Process
	 * シーケンシングリクエストプロセス
	 * @return control be return to the LTS flag
	 */
	private boolean doSequencingRequestProcess() throws SequencingException, SystemException {

		try {
			// Trace Start <sequencingrequest>
			TraceItem sequencingrequestTraceItem = trace.startTrace("sequencingrequest");
			try {
				// Trace <request>
				sequencingrequestTraceItem.appendChild("request", sequencingRequest);

				// Case:sequencing request is Start
				if (sequencingRequest.equalsIgnoreCase("start")) {
					// Apply the Start Sequencing Request Process
					try {
						doStartSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}

				// Case:sequencing request is Resume All
				else if (sequencingRequest.equalsIgnoreCase("resumeAll")) {
					// Apply the Resume All Sequencing Request Process
					try {
						doResumeAllSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}

				// Case:sequencing request is Exit
				else if (sequencingRequest.equalsIgnoreCase("exit")) {
					// Apply the Exit Sequencing Request Process
					boolean endSequencingSession;
					try {
						endSequencingSession = doExitSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = false;
					// End Sequencing Session
					return endSequencingSession;
				}

				// Case:sequencing request is Retry
				else if (sequencingRequest.equalsIgnoreCase("retry")) {
					// Apply the Retry Sequencing Request Process
					try {
						doRetrySequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}

				// Case:sequencing request is Continue
				else if (sequencingRequest.equalsIgnoreCase("continue")) {
					// Apply the Continue Sequencing Request Process
					try {
						doContinueSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}

				// Case:sequencing request is Previous
				else if (sequencingRequest.equalsIgnoreCase("previous")) {
					// Apply the Previous Sequencing Request Process
					try {
						doPreviousSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}

				// Case:sequencing request is Choice
				else if (sequencingRequest.equalsIgnoreCase("choice")) {
					// Apply the Choice Sequencing Request Process
					try {
						doChoiceSequencingRequestProcess();
					}
					catch (SequencingException e) {
						deliveryRequest = false;
						throw e;
					}
					deliveryRequest = true;
					return false;
				}
				else {
					deliveryRequest = false;
					throw SequencingException.getInstance("SB.2.12-1", "[SequencingRequest:" + sequencingRequest + "]", null);
				}
			}
			finally {
				// Trace End <sequencingrequest>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Delivery Request Process
	 * デリバリリクエストプロセス
	 * @return the validity of the delivery request
	 */
	private boolean doDeliveryRequestProcess() throws SequencingException, SystemException {

		try {
			if (identifiedActivity.hasChildren()) {
				throw SequencingException.getInstance("DB.1.1-1", "[IdentifiedActivityID:" + identifiedActivity.getIdentifier() + "]", null);
			}

			ActivityPath path = new ActivityPath(rootActivity, identifiedActivity);
			if (path.isEmpty()) {
				throw SequencingException.getInstance("DB.1.1-2", null, null);
			}
			while (true) {
				Activity eachActivity = path.getNext();
				// Apply the Check Activity Process to the activity
				boolean evaluation = doCheckActivityProcess(eachActivity);
				if (evaluation) {
					deliveryRequest = false;
					throw SequencingException.getInstance("DB.1.1-3", "[ActivityID:" + eachActivity.getIdentifier() + "]", null);
				}
				if (path.isLast()) {
					break;
				}
			}
			return true;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Content Delivery Environment Process
	 * コンテンツデリバリプロセス
	 */
	private void doContentDeliveryEnvironmentProcess() throws SequencingException, SystemException {

		try {
			// deliveryrequestトレースアイテム取得
			TraceItem deliveryrequestTraceItem = trace.getCurrentTraceItem();

			// * edit pseudo code
			if (currentActivity != null && currentActivity.isActive()) {
				throw SequencingException.getInstance("DB.2-1", "[CurrentActivityID:" + currentActivity.getIdentifier() + "]", null);
			}
			// * edit pseudo code
			if (suspendedActivity != null && ActivityPath.checkTarget(identifiedActivity, suspendedActivity) != ActivityPath.SAME_ACTIVITY) {
				doClearSuspendedActivitySubprocess(identifiedActivity);
			}

			// Apply the Terminate Descendent Attempts Processs to the activity identified for delivery
			doTerminateDescendentAttemptsProcess(identifiedActivity);

			ActivityPath path = new ActivityPath(rootActivity, identifiedActivity);
			while (true) {
				Activity eachActivity = path.getNext();

				// Trace Start <editActivityInformation>
				TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
				try {
					// Trace <activityid>
					editActivityInformation.appendChild("activityid", eachActivity.getIdentifier());

					if (!eachActivity.isActive()) {
						if (eachActivity.getSequencing().getDeliveryControlFlag("tracked")) {
							if (eachActivity.isSuspended()) {
								eachActivity.setSuspended(false);
								// Trace <activityissuspended>
								editActivityInformation.appendChild("activityissuspended", "false");
								// CBTCOM情報再開
								eachActivity.resumeAPIAdapter();
							}
							else {
								eachActivity.setActivityAttemptCount(eachActivity.getActivityAttemptCount() + 1);
								if (eachActivity.getActivityAttemptCount() == 1) {
									eachActivity.setActivityProgressStatus(true);
									// Trace <activityprogressstatus>
									editActivityInformation.appendChild("activityprogressstatus", "true");
								}

								// Initialize Objective Progress Information and Attempt Progress Information required for the new attempt
								// * add pseudo code
								// PersistState
								if (!eachActivity.hasChildren()) {
									if (!eachActivity.getPersistState()) {
										// 2度目なら処理を変える。
										if(eachActivity.getActivityAttemptCount() == 0){
											eachActivity.initializeAPIAdapter(userID, userName, aiccURL, APIAdapterEncoding, null, false);	
										}else{
											eachActivity.resumeAPIAdapter();
											// さらに一部APIの初期化
											eachActivity.initializeAPIAdapter2(userID, userName, aiccURL, APIAdapterEncoding);
										}
										
									}
									else {
										// CBTCOM情報再開
										eachActivity.resumeAPIAdapter();
									}
								}
								LocalObjective[] localObjectives = eachActivity.getObjective();
								for (int i = 0; i < localObjectives.length; i++) {
									localObjectives[i].initializeLocalObjectiveInformation(null);
									// Trace <objectiveid>
									editActivityInformation.appendChild("objectiveid", localObjectives[i].getObjectiveID());
									// Trace <objectiveprogressstatus>
									editActivityInformation.appendChild("objectiveprogressstatus", "false");
									// Trace <objectivemeasurestatus>
									editActivityInformation.appendChild("objectivemeasurestatus", "false");
								}
								eachActivity.initializeAttemptInformation();
								// Trace <attemptprogressstatus>
								editActivityInformation.appendChild("attemptprogressstatus", "false");
							}
						}
						eachActivity.setActive(true);
						// Trace <activityisactive>
						editActivityInformation.appendChild("activityisactive", "true");
					}

				}
				finally {
					// Trace Start <editActivityInformation>
					trace.endTrace();
				}

				if (path.isLast()) {
					break;
				}
			}
			// ここにとりあえずのuseCurrent処理
			if(identifiedActivity != null && (!identifiedActivity.isRoot())){
				if(currentActivity != null && (!currentActivity.isRoot())){
					String targetPName = identifiedActivity.getParent().getIdentifier();
					String currentPName = currentActivity.getParent().getIdentifier();		
					if(!targetPName.equals(currentPName)){
						// 共通の親ではないのでブロックの子のuseCurrentフラグをfalseに
						Activity pActivity = identifiedActivity.getParent();
						Activity[] tmpChild = pActivity.getChildren();
						int tmpCount = tmpChild.length;
						for( int i = 0;i < tmpCount;i++){
							// useCurrentフラグ変更処理
							tmpChild[i].setUseCurrentAttempt(false);
						}
					}
				}
			}
			// 自分自身は常にture
			identifiedActivity.setUseCurrentAttempt(true);
			
			// ここでcurrentActivityの変更
			currentActivity = identifiedActivity;
			// 試行開始時間設定
			path = new ActivityPath(currentActivity, rootActivity);
			if (!path.isEmpty()) {
				while (true) {
					Activity eachActivity = path.getNext();
					eachActivity.setUseCurrentAttempt(true);
					eachActivity.getStatus().setAttemptStartTime(now);
					if (path.isLast()) {
						break;
					}
				}
			}
			// Trace <currentactivityid>
			deliveryrequestTraceItem.appendChild("currentactivityid", currentActivity.getIdentifier());
		}
		catch (SystemException e) {
			throw e;
		}
		catch (SequencingException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("デリバリに失敗しました。(ContentDeliveryEnvironmentProcess failed)", e);
		}
	}

	/**
	 * Clear Suspended Activity Subprocess
	 * 中断Activity情報更新サブプロセス
	 * @param activity
	 */
	private void doClearSuspendedActivitySubprocess(Activity activity) throws SystemException {

		try {
			if (suspendedActivity != null) {
				Activity commonAncestor = ActivityPath.getCommonParent(activity, suspendedActivity);
				ActivityPath path = new ActivityPath(suspendedActivity, commonAncestor);
				if (!path.isEmpty()) {
					while (true) {
						Activity eachActivity = path.getNext();
						// Trace Start <editActivityInformation>
						TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
						try {
							// Trace <activityid>
							editActivityInformation.appendChild("activityid", eachActivity.getIdentifier());
							if (!eachActivity.hasAvailableChildren()) {
								eachActivity.setSuspended(false);
								// Trace <activityissuspended>
								editActivityInformation.appendChild("activityissuspended", "false");
							}
							else {
								boolean isChildSuspended = false;
								for (int i = 0; i < eachActivity.getAvailableChildren().length; i++) {
									if (eachActivity.getAvailableChildren()[i].isSuspended()) {
										isChildSuspended = true;
									}
								}
								if (!isChildSuspended) {
									eachActivity.setSuspended(false);
									// Trace <activityissuspended>
									editActivityInformation.appendChild("activityissuspended", "false");
								}
							}
							if (path.isLast()) {
								break;
							}
						}
						finally {
							// Trace Start <editActivityInformation>
							trace.endTrace();
						}
					}
				}
				suspendedActivity = null;
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Limit Condition Check Process
	 * リミットコンディション判定プロセス
	 * @param activity
	 * @return Limit Condition Violated
	 */
	private boolean doLimitConditionsCheckProcess(Activity activity, String limitCondition) throws SystemException {

		try {
			// Trace Start <limitconditionrule>
			TraceItem limitconditionruleTraceItem = trace.startTrace("limitconditionrule");
			try {
				boolean applied = false;
				// Trace <activityid>
				limitconditionruleTraceItem.appendChild("activityid", activity.getIdentifier());

				if (!activity.getSequencing().getDeliveryControlFlag("tracked")) {
					return false;
				}

				// Trace Start <limitcondition>
				TraceItem limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());
					// check attempt count
					if (limitCondition == null || limitCondition.equalsIgnoreCase("attemptLimit")) {
						Integer attemptLimit = activity.getSequencing().getAttemptLimit();
						if (attemptLimit != null) {
							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "attemptLimit");

							// Trace <attemptprogressstatus>
							limitconditionTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));

							if (activity.getActivityProgressStatus()) {
								// Trace <activityattemptcount>
								limitconditionTraceItem.appendChild("activityattemptcount", Integer.toString(activity.getActivityAttemptCount()));
								int attemptCount = activity.getActivityAttemptCount();

								if (attemptCount >= attemptLimit.intValue()) {
									applied = true;
								}
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());

					// check activity absolute duration
					if (limitCondition == null || limitCondition.equalsIgnoreCase("activityAbsoluteDurationLimit")) {
						Duration activityAbsoluteLimit = activity.getSequencing().getDurationLimit("activityAbsoluteDurationLimit");
						if (activityAbsoluteLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "activityAbsoluteDurationLimit");

							// Trace <activityprogressstatus>
							limitconditionTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
							if (activity.getActivityProgressStatus()) {
								// Trace <activityabsoluteduration>
								limitconditionTraceItem.appendChild("activityabsoluteduration", activity.getActivityAbsoluteDuration().toString());
								if (activity.getActivityAbsoluteDuration().compareTo(activityAbsoluteLimit) >= 0) {
									applied = true;
								}
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());

					// check activity experienced duration
					if (limitCondition == null || limitCondition.equalsIgnoreCase("activityExperiencedDurationLimit")) {
						Duration activityExperiencedLimit = activity.getSequencing().getDurationLimit("activityExperiencedDurationLimit");
						if (activityExperiencedLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "activityExperiencedDurationLimit");

							// Trace <activityprogressstatus>
							limitconditionTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
							if (activity.getActivityProgressStatus()) {
								// Trace <activityexperiencedduration>
								limitconditionTraceItem.appendChild("activityexperiencedduration", activity.getActivityExperiencedDuration().toString());
								if (activity.getActivityExperiencedDuration().compareTo(activityExperiencedLimit) >= 0) {
									applied = true;
								}
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());
					// check attempt absolute duration
					if (limitCondition == null || limitCondition.equalsIgnoreCase("attemptAbsoluteDurationLimit")) {
						Duration attemptAbsoluteLimit = activity.getSequencing().getDurationLimit("attemptAbsoluteDurationLimit");
						if (attemptAbsoluteLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "attemptAbsoluteDurationLimit");

							// Trace <attemptprogressstatus>
							limitconditionTraceItem.appendChild("attemptprogressstatus", Boolean.toString(activity.getProgress().getAttemptProgressStatus()));

							if (activity.getProgress().getAttemptProgressStatus()) {
								// Trace <attemptabsoluteduration>
								limitconditionTraceItem.appendChild("attemptabsoluteduration", activity.getProgress().getAttemptAbsoluteDurationForEvaluation().toString());
								if (activity.getProgress().getAttemptAbsoluteDurationForEvaluation().compareTo(attemptAbsoluteLimit) >= 0) {
									applied = true;
								}
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());
					// check attemt experienced duration
					if (limitCondition == null || limitCondition.equalsIgnoreCase("attemptExperiencedDurationLimit")) {
						Duration attemptExperiencedLimit = activity.getSequencing().getDurationLimit("attemptExperiencedDurationLimit");
						if (attemptExperiencedLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "attemptExperiencedDurationLimit");

							// Trace <attemptprogressstatus>
							limitconditionTraceItem.appendChild("attemptprogressstatus", Boolean.toString(activity.getProgress().getAttemptProgressStatus()));

							if (activity.getProgress().getAttemptProgressStatus()) {
								// Trace <attemptexperiencedduration>
								limitconditionTraceItem.appendChild("attemptexperiencedduration", activity.getProgress().getAttemptExperiencedDurationForEvaluation().toString());
								if (activity.getProgress().getAttemptExperiencedDurationForEvaluation().compareTo(attemptExperiencedLimit) >= 0) {
									applied = true;
								}
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());
					// check begin time
					if (limitCondition == null || limitCondition.equalsIgnoreCase("beginTimeLimit")) {
						Calendar beginTimeLimit = activity.getSequencing().getDateTimeLimit("beginTimeLimit");
						if (beginTimeLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "beginTimeLimit");

							long limitSec = beginTimeLimit.getTimeInMillis();
							long currentSec = now.getTimeInMillis();

							// Trace <attemptexperiencedduration>
							limitconditionTraceItem.appendChild("currenttime", formatter.format(now.getTime()));

							if (limitSec > currentSec) {
								applied = true;
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace Start <limitcondition>
				limitconditionTraceItem = trace.startTrace("limitcondition");
				try {
					// Trace <activityid>
					limitconditionTraceItem.appendChild("activityid", activity.getIdentifier());
					// check end time
					if (limitCondition == null || limitCondition.equalsIgnoreCase("endTimeLimit")) {
						Calendar endTimeLimit = activity.getSequencing().getDateTimeLimit("endTimeLimit");
						if (endTimeLimit != null) {

							// Trace <condition>
							limitconditionTraceItem.appendChild("condition", "endTimeLimit");

							long limitSec = endTimeLimit.getTimeInMillis();
							long currentSec = now.getTimeInMillis();

							// Trace <attemptexperiencedduration>
							limitconditionTraceItem.appendChild("currenttime", formatter.format(now.getTime()));

							if (limitSec < currentSec) {
								applied = true;
							}
						}
					}
				}
				finally {
					// Trace End <limitcondition>
					trace.endTrace();
				}

				// * add pseudo code
				if (applied) {
					// Trace <applied>
					limitconditionruleTraceItem.appendChild("applied", "true");
					return true;
				}

				// Trace <applied>
				limitconditionruleTraceItem.appendChild("applied", "false");
				return false;
			}
			finally {
				// Trace End <limitconditionrule>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * Sequencing Rule Check Process
	 * シーケンシングルール判定プロセス
	 * @param activity アクティビティ
	 * @param ruleAction ルールアクション
	 * @param category ルールカテゴリ
	 * @return the Action to apply
	 */
	private String doSequencingRulesCheckProcess(Activity activity, String[] ruleAction, String category) throws SystemException {

		try {
			CachedNode sequencingRules = activity.getSequencing().getSequencingRules();
			if (sequencingRules == null) {
				return "";
			}
			StringBuffer testCase = null;
			for (int i = 0; i < ruleAction.length; i++) {
				if (i == 0) {
					testCase = new StringBuffer("ruleAction/@action='");
					testCase.append(ruleAction[i]);
					testCase.append("'");
				}
				else {
					testCase.append(" or ruleAction/@action='");
					testCase.append(ruleAction[i]);
					testCase.append("'");
				}
			}
			CachedNode[] conditionRulesNodes = sequencingRules.selectNodeList(category + "[" + testCase.toString() + "]");

			for (int i = 0; i < conditionRulesNodes.length; i++) {

				// Apply the Sequencing Rule Check Subprocess to the activity and the rule
				if (doSequencingRuleCheckSubprocess(activity, conditionRulesNodes[i])) {
					return conditionRulesNodes[i].selectSimpleSingleNode("ruleAction/@action").getNodeValue();
				}
			}
			return null;
		}
		catch (Exception e) {
			throw new SystemException("シーケンシングルールチェックに失敗しました。(SequencingRulesCheckProcess failed)", e);
		}
	}

	/**
	 * Sequencing Rule Check Subprocess
	 * シーケンシングルール判定サブプロセス
	 * @param activity アクティビティ
	 * @param conditionRuleNode シーケンシングルール
	 * @return rule evaluation
	 */
	private boolean doSequencingRuleCheckSubprocess(Activity activity, CachedNode conditionRuleNode) throws SystemException {

		try {
			// Trace Start <sequencingrule>
			TraceItem sequencingruleTraceItem = trace.startTrace("sequencingrule");

			try {
				// Trace <activityid>
				sequencingruleTraceItem.appendChild("activityid", activity.getIdentifier());

				CachedNode conditionsNode = conditionRuleNode.selectSingleChildNode("ruleConditions");
				// Trace <action>
				sequencingruleTraceItem.appendChild("action", conditionsNode.selectSingleNode("../ruleAction/@action").getNodeValue());

				CachedNode[] conditionNodes = conditionsNode.selectChildNodeList("ruleCondition");
				// conditionごとの判定
				boolean[] conditionBag = new boolean[conditionNodes.length];

				for (int i = 0; i < conditionNodes.length; i++) {

					String referencedObjective = "";
					BigDecimal measureThreshold = null;
					String condition = "";
					boolean blnSatisfiedByMeasure = false;

					// referenced objective id の取得
					CachedNode referenceNode = conditionNodes[i].selectSingleChildNode("@referencedObjective");
					if (referenceNode != null) {
						referencedObjective = referenceNode.getNodeValue();
					}
					else {
						LocalObjective primary = activity.getObjectiveContributeToRollup();
						if (primary != null) {
							referencedObjective = primary.getObjectiveID();
						}
					}

					// threshold の取得
					CachedNode thresholdNode = conditionNodes[i].selectSingleChildNode("@measureThreshold");
					if (thresholdNode != null) {
						measureThreshold = new BigDecimal(thresholdNode.getNodeValue());
					}
					else {
						measureThreshold = new BigDecimal(Default.getValue("sequencingRules/preConditionRule/ruleConditions/ruleCondition/@measureThreshold"));
					}
					measureThreshold = measureThreshold.setScale(4, BigDecimal.ROUND_HALF_UP);

					// conditionの取得
					CachedNode conditionNode = conditionNodes[i].selectSingleChildNode("@condition");
					condition = conditionNode.getNodeValue();

					// Trace Start <condition>
					TraceItem conditionTraceItem = trace.startTrace("condition");
					try {
						// Trace <conditionrule>
						conditionTraceItem.appendChild("conditionrule", condition);
						// Trace <activityid>
						conditionTraceItem.appendChild("activityid", activity.getIdentifier());
						// Trace <objectiveid>
						conditionTraceItem.appendChild("objectiveid", referencedObjective);

						// condition の評価
						if (condition.equalsIgnoreCase("satisfied")) {
							// Trace <objectiveprogressstatus>
							conditionTraceItem.appendChild("objectiveprogressstatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveProgressStatus()));
							if (activity.getObjective(referencedObjective).getObjectiveProgressStatus()) {
							
								conditionBag[i] = activity.getObjective(referencedObjective).getObjectiveSatisfiedStatus();
								// Trace <objectivesatisfiedstatus>
								conditionTraceItem.appendChild("objectivesatisfiedstatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveSatisfiedStatus()));
							}
							else {
								conditionBag[i] = false;
							}
							
							
/*							
							if (activity.getObjective(referencedObjective).getObjectiveProgressStatus()) {
								conditionBag[i] = activity.getObjective(referencedObjective).getObjectiveSatisfiedStatus();
								// Trace <objectivesatisfiedstatus>
								conditionTraceItem.appendChild("objectivesatisfiedstatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveSatisfiedStatus()));
							}
							else {
								conditionBag[i] = false;
							}
							
*/							
						}

						else if (condition.equalsIgnoreCase("objectiveStatusKnown")) {
							// objective satisfied known の評価
							conditionBag[i] = activity.getObjective(referencedObjective).getObjectiveProgressStatus();
							// Trace <objectiveprogressstatus>
							conditionTraceItem.appendChild("objectiveprogressstatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveProgressStatus()));
						}

						else if (condition.equalsIgnoreCase("objectiveMeasureKnown")) {
							// objective satisfied known の評価
							conditionBag[i] = activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation();
							// Trace <objectivemeasurestatus>
							conditionTraceItem.appendChild("objectivemeasurestatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation()));
						}

						else if (condition.equalsIgnoreCase("objectiveMeasureGreaterThan")) {
							// Trace <objectivemeasurestatus>
							conditionTraceItem.appendChild("objectivemeasurestatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation()));
							if (activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation()) {

								BigDecimal normalizedMeasure = activity.getObjective(referencedObjective).getObjectiveNormalizedMeasureForEvaluation();
								normalizedMeasure = normalizedMeasure.setScale(4, BigDecimal.ROUND_HALF_UP);

								// Trace <objectivenomarizedmeasure>
								conditionTraceItem.appendChild("objectivenomarizedmeasure", activity.getObjective(referencedObjective).getObjectiveNormalizedMeasureForEvaluation().toString());
								if (normalizedMeasure.compareTo(measureThreshold) == 1) {
									conditionBag[i] = true;
								}
							}
						}

						else if (condition.equalsIgnoreCase("objectiveMeasureLessThan")) {
							// Trace <objectivemeasurestatus>
							conditionTraceItem.appendChild("objectivemeasurestatus", Boolean.toString(activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation()));
							if (activity.getObjective(referencedObjective).getObjectiveMeasureStatusForEvaluation()) {

								BigDecimal normalizedMeasure = activity.getObjective(referencedObjective).getObjectiveNormalizedMeasureForEvaluation();
								normalizedMeasure = normalizedMeasure.setScale(4, BigDecimal.ROUND_HALF_UP);

								// Trace <objectivenomarizedmeasure>
								conditionTraceItem.appendChild("objectivenomarizedmeasure", activity.getObjective(referencedObjective).getObjectiveNormalizedMeasureForEvaluation().toString());
								if (normalizedMeasure.compareTo(measureThreshold) == -1) {
									conditionBag[i] = true;
								}
							}
						}

						else if (condition.equalsIgnoreCase("completed")) {
							// Trace <attemptprogressstatus>
							conditionTraceItem.appendChild("attemptprogressstatus", Boolean.toString(activity.getProgress().getAttemptProgressStatus()));
							if (activity.getProgress().getAttemptProgressStatus()) {
								// completed の評価
								conditionBag[i] = activity.getProgress().getAttemptCompletionStatus();
								// Trace <attemptcompletionstatus>
								conditionTraceItem.appendChild("attemptcompletionstatus", Boolean.toString(activity.getProgress().getAttemptCompletionStatus()));
							}
							else {
								conditionBag[i] = false;
							}
						}

						else if (condition.equalsIgnoreCase("activityProgressKnown")) {
							// attempted の評価
							conditionBag[i] = activity.getActivityProgressStatus();
							// Trace <activityprogressstatus>
							conditionTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
						}

						else if (condition.equalsIgnoreCase("attempted")) {
							// attempted の評価
							conditionBag[i] = activity.getActivityProgressStatus();
							// Trace <activityprogressstatus>
							conditionTraceItem.appendChild("activityprogressstatus", Boolean.toString(activity.getActivityProgressStatus()));
						}

						else if (condition.equalsIgnoreCase("attemptLimitExceeded")) {
							// attempt limit exceeded の評価
							if (doLimitConditionsCheckProcess(activity, "attemptLimit")) {
								conditionBag[i] = true;
							}
							else {
								conditionBag[i] = false;
							}
						}

						else if (condition.equalsIgnoreCase("timeLimitExceeded")) {
							// time limit exceeded の評価
							if (doLimitConditionsCheckProcess(activity, "attemptExperiencedDurationLimit")) {
								conditionBag[i] = true;
							}
							else if (doLimitConditionsCheckProcess(activity, "attemptAbsoluteDurationLimit")) {
								conditionBag[i] = true;
							}
							else if (doLimitConditionsCheckProcess(activity, "activityAbsoluteDurationLimit")) {
								conditionBag[i] = true;
							}
							else if (doLimitConditionsCheckProcess(activity, "activityExperiencedDurationLimit")) {
								conditionBag[i] = true;
							}
							else {
								conditionBag[i] = false;
							}
						}

						else if (condition.equalsIgnoreCase("outsideAvailableTimeRange")) {
							// Outside Available Time Range の評価
							if (doLimitConditionsCheckProcess(activity, "beginTimeLimit")) {
								conditionBag[i] = true;
							}
							else if (doLimitConditionsCheckProcess(activity, "endTimeLimit")) {
								conditionBag[i] = true;
							}
							else {
								conditionBag[i] = false;
							}
						}

						else if (condition.equalsIgnoreCase("always")) {
							conditionBag[i] = true;
						}

						else {
							throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][ruleCondition/@condition=" + condition + "]");
						}

						// operator の取得
						String ope = "";
						CachedNode opeNode = conditionNodes[i].selectSingleChildNode("@operator");
						if (opeNode == null) {
							ope = Default.getValue("sequencingRules/preConditionRule/ruleConditions/ruleCondition/@operator");
						}
						else {
							ope = opeNode.getNodeValue();
						}

						// operetor が "not" なら判定結果を反転する
						if (ope.equalsIgnoreCase("not")) {
							conditionBag[i] = !conditionBag[i];
						}
						else if (!ope.equalsIgnoreCase("noOp")) {
							throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][ruleCondition/@operator=" + ope + "]");
						}
						// Trace <operatedevaluation>
						conditionTraceItem.appendChild("operatedevaluation", Boolean.toString(conditionBag[i]));
					}
					finally {
						// Trace End <condition>
						trace.endTrace();
					}
				}

				if (conditionBag.length == 0) {
					return false;
				}

				// condition combination
				String conditionCombination;

				CachedNode conditionCombinationNode = conditionsNode.selectSingleChildNode("@conditionCombination");
				if (conditionCombinationNode != null) {
					conditionCombination = conditionCombinationNode.getNodeValue();
				}
				else {
					conditionCombination = Default.getValue("sequencingRules/preConditionRule/ruleConditions/@conditionCombination");
				}

				if (conditionCombination.equalsIgnoreCase("all")) {
					// condition combination = "all"
					for (int i = 0; i < conditionBag.length; i++) {
						if (!conditionBag[i]) {
							// Trace <applied>
							sequencingruleTraceItem.appendChild("applied", "false");
							return false;
						}
					}
					// Trace <applied>
					sequencingruleTraceItem.appendChild("applied", "true");
					return true;
				}
				else if (conditionCombination.equalsIgnoreCase("any")) {
					// condition combination = "any"
					for (int i = 0; i < conditionBag.length; i++) {
						if (conditionBag[i]) {
							// Trace <applied>
							sequencingruleTraceItem.appendChild("applied", "true");
							return true;
						}
					}
					// Trace <applied>
					sequencingruleTraceItem.appendChild("applied", "false");
					return false;
				}
				else {
					throw new IllegalManifestException("Manifest is Illegal. [ActivityID:" + activity.getIdentifier() + "][ruleConditions/@conditionCombination=" + conditionCombination + "]");
				}
			}
			finally {
				// Trace End <sequencingrule>
				trace.endTrace();
			}
		}
		catch (SystemException e) {
			throw e;
		}
		catch (Exception e) {
			throw new SystemException("シーケンシングルールチェックに失敗しました。(SequencingRuleCheckSubprocess failed)", e);
		}
	}

	/**
	 * Terminate Descendent Attempts Process
	 * 試行終了処理伝播プロセス
	 * @param activity アクティビティ
	 */
	private void doTerminateDescendentAttemptsProcess(Activity activity) throws SystemException {
		try {
			// * add pseudo code
			if (currentActivity != null) {
				Activity commonAncestor = ActivityPath.getCommonParent(currentActivity, activity);
				ActivityPath path = new ActivityPath(currentActivity, commonAncestor);
				path.removeFirst();
				path.removeLast();
				if (!path.isEmpty()) {
					while (true) {
						Activity eachActivity = path.getNext();
						// Applay the End Attempt Process to the activity
						doEndAttemptProcess(eachActivity);
						if (path.isLast()) {
							break;
						}
					}
				}
			}
		}
		catch (SystemException e) {
			throw e;
		}
	}

	/**
	 * End Attempt Process
	 * 試行終了プロセス
	 * @param activity アクティビティ
	 */
	private void doEndAttemptProcess(Activity activity) throws SystemException {

		try {
			// Trace Start <endattempt>
			TraceItem endattemptTraceItem = trace.startTrace("endattempt");
			try {
				// Trace <activityid>
				endattemptTraceItem.appendChild("activityid", activity.getIdentifier());
				// Trace Start <editActivityInformation>
				TraceItem editActivityInformation = trace.startTrace("editActivityInformation");
				try {
					// Trace <activityid>
					editActivityInformation.appendChild("activityid", activity.getIdentifier());
					if (!activity.hasChildren()) {
						if (activity.getSequencing().getDeliveryControlFlag("tracked")) {
							if (!activity.isSuspended()) {
								if (!activity.getSequencing().getDeliveryControlFlag("completionSetByContent")) {
									if (!activity.getProgress().getAttemptProgressStatus()) {
										activity.getProgress().setAttemptProgressStatus(true);
										activity.getProgress().setAttemptCompletionStatus(true);
										// Trace <activityattemptprogressstatus>
										editActivityInformation.appendChild("activityattemptprogressstatus", "true");
										// Trace <activityattemptcompletionstatus>
										editActivityInformation.appendChild("activityattemptcompletionstatus", "true");
									}
								}
								
								if (!activity.getSequencing().getDeliveryControlFlag("objectiveSetByContent")) {
									LocalObjective tmpActivity = activity.getObjectiveContributeToRollup();
									if (tmpActivity  != null) {
			//							if (!tmpActivity.getObjectiveLocalProgressStatus()) {
										if (!tmpActivity.getObjectiveProgressStatus()) {
											tmpActivity.setObjectiveProgressStatus(true);
											tmpActivity.setObjectiveSatisfiedStatus(true);
											// Trace <objectiveid>
											editActivityInformation.appendChild("objectiveid", tmpActivity.getObjectiveID());
											// Trace <objectiveprogressstatus>
											editActivityInformation.appendChild("objectiveprogressstatus", "true");
											// Trace <objectivesatisfiedstatus>
											editActivityInformation.appendChild("objectivesatisfiedstatus", "true");
										}else{
											// Trace <objectiveid>
											editActivityInformation.appendChild("objectiveid", tmpActivity.getObjectiveID());
											// Trace <objectiveprogressstatus>
											editActivityInformation.appendChild("objectiveprogressstatus", "false");
											// Trace <objectivesatisfiedstatus>
											editActivityInformation.appendChild("objectivesatisfiedstatus", "false");								
										}
									}
								}
							}
						}
					}
					else {
						boolean isChildSuspended = false;
						for (int i = 0; i < activity.getAvailableChildren().length; i++) {
							if (activity.getAvailableChildren()[i].isSuspended()) {
								isChildSuspended = true;
							}
						}
						if (isChildSuspended) {
							activity.setSuspended(true);
							// Trace <activityissuspended>
							editActivityInformation.appendChild("activityissuspended", "true");
						}
						else {
							activity.setSuspended(false);
							// Trace <activityissuspended>
							editActivityInformation.appendChild("activityissuspended", "false");
						}
					}
					activity.setActive(false);
					// Trace <activityisactive>
					editActivityInformation.appendChild("activityisactive", "false");

					// Select&Randomize履歴フラグ初期化
					activity.getStatus().setSelectionStatus(false);
					activity.getStatus().setRandomizeStatus(false);
				}
				finally {
					// Trace End <editActivityInformation>
					trace.endTrace();
				}
			}
			finally {
				// Trace Start <endattempt>
				trace.endTrace();
			}
			// Apply the Overall Rollup Process to the activity
			doOverallRollupProcess(activity);

			// * add pseudo code
			activity.setCandidatePreviousValue();
		}
		catch (SystemException e) {
			throw e;
		}
	}

	
	private void doEndAttemptProcessDummy(Activity activity) throws SystemException {

		try {
			// Apply the Overall Rollup Process to the activity
			doOverallRollupProcess(activity);
		}
		catch (SystemException e) {
			throw e;
		}
	}
	
	/**
	 * Check Activity Process
	 * デリバリ対象Activity判定プロセス
	 * @param activity アクティビティ
	 */
	private boolean doCheckActivityProcess(Activity activity) throws SystemException {

		try {
			// Apply the Sequencing Rules Check Process to the activity
			String[] actions = { "disabled" };
			String apply = doSequencingRulesCheckProcess(activity, actions, "preConditionRule");
			if (apply != null && !apply.equalsIgnoreCase("")) {
				return true;
			}

			// Apply the Limit Conditions Check Process to the activity
			boolean evaluation = doLimitConditionsCheckProcess(activity, null);
			if (evaluation) {
				return true;
			}
			return false;
		}
		catch (SystemException e) {
			throw e;
		}
	}

	private static String userIDPath(String strDirPath, String strUserID)
	{
		return UserIDFolder.getPath(strDirPath, strUserID);
	}
}
