/**
 * PQCore.js 클래스 리스트
 * 
 * MakeRequest
 * HandleResult
 * 
 * ModelCore
 * Model
 * 
 * PQService
 * PQScript
 * ScriptEvent
 * ScriptFormEvent
 * ScriptAtomEvent
 * PQProcessInfo
 */

function Atom (strVarName, strRefVarName, strScrollName, nOrder, 
				nScriptIndex, nSQLIndex, nDBIndex, bVanish) 
{
	this.m_strVarName = strVarName;
	this.m_strRefVarName = strRefVarName;
	this.m_strScrollName = strScrollName;
	this.m_nOrder = nOrder;
	
	this.m_nScriptIndex = nScriptIndex;
	this.m_nSQLIndex = nSQLIndex;
	this.m_nDBIndex = nDBIndex;
	
	this.m_bVanish = bVanish;
}

Atom.prototype.Atom = function (strVarName, strRefVarName, strScrollName, nOrder, 
				nScriptIndex, nSQLIndex, nDBIndex, bVanish)
{
	this.m_strVarName = strVarName;
	this.m_strRefVarName = strRefVarName;
	this.m_strScrollName = strScrollName;
	this.m_nOrder = nOrder;
	
	this.m_nScriptIndex = nScriptIndex;
	this.m_nSQLIndex = nSQLIndex;
	this.m_nDBIndex = nDBIndex;
	
	this.m_bVanish = bVanish;
}

Atom.prototype.getVarName = function ()
{
	return this.m_strVarName;
}

Atom.prototype.setVarName = function (strVarName)
{
	this.m_strVarName = strVarName;
}

Atom.prototype.getRefVarName = function ()
{
	return this.m_strRefVarName;
}

Atom.prototype.getScrollName = function ()
{
	return this.m_strScrollName;
}

Atom.prototype.getScriptIndex = function ()
{
	return this.m_nScriptIndex;
}

Atom.prototype.getSQLIndex = function ()
{
	return this.m_nSQLIndex;
}

Atom.prototype.getDBIndex = function ()
{
	return this.m_nDBIndex;
}

Atom.prototype.getFieldIndex = function ()
{
	return this.m_nFieldIndex;
}

Atom.prototype.getScrollAtom = function ()
{
	if (null != this.m_bScroll && this.m_bScroll)
	{
		var objScrollAtom = Model.getAtom(this.m_strScrollName);
		if (null != objScrollAtom)
		{
			return objScrollAtom;
		}
	}
	else if (ContainsWebScrollAtom() && this instanceof WebScrollAtom)
	{
		return this;
	}
	
	return null;
}

Atom.prototype.isDBIO = function ()
{
	if (this.m_bDBIO && true == this.m_bDBIO)
	{
		return true;
	}
	return false;
}

/**
 * @return 1베이스일 때 1 빼고 리턴
 */
Atom.prototype.getRealIndex = function (nIndex)
{
	if (g_objDoc.isEBLSource() && 0 < nIndex)
	{
		nIndex -= 1;
	}

	return nIndex;
}

Atom.prototype.getRealReturnIndex = function (nIndex)
{
	if (g_objDoc.isEBLSource() && 0 <= nIndex)
	{
		nIndex += 1;
	}

	return nIndex;
}

Atom.prototype.loadEnding = function ()
{
	if (this.m_strFieldType == "text")
	{
		var strResult = this.loadTextData(this.m_strTableName, this.m_strFieldName);
		
		this.setValue(strResult);
	}
}

Atom.prototype.loadTextData = function (strTable, strField)
{
	var strResult = "";
	
	for (var j = 0; j < g_arDefaultKeyVarName.length; j++)
	{
		var arGroup = g_arDefaultKeyVarName[j]
		var strScrollName = arGroup[0];
		var strVarName = arGroup[1];
		var objLoadAtom = Model.getAtom(strVarName, strScrollName);
		
		var strWhere = "";
		
		if (objLoadAtom.getTableName() == strTable)
		{
			for (var k = 1; k < arGroup.length; k+=1)
			{
				var strAtomVarName = arGroup[k];
				
				var objKeyAtom = Model.getAtom(strAtomVarName, strScrollName);
				
				var strDefaultKeyAtomFieldName = objKeyAtom.getFieldName();
				var strFilter = Utils.trim(objKeyAtom.getValue());

				// 입력란의 접두어 처리
				if (!Utils.isEmpty(strFilter) && objKeyAtom.getAtomType() == "InputData")
				{
					var strPrefix = objKeyAtom.getPrefix();
					strFilter = strPrefix + strFilter;
				}

				if (-1 < strWhere.indexOf(strFilter))
				{
					continue;
				}

				if (k > 1)
				{
					strWhere += " AND ";
				}

				var strFieldType = objKeyAtom.getFieldType();		
				if (strFieldType == "int" || strFieldType == "float" || strFieldType == "double")
				{
					strWhere += strDefaultKeyAtomFieldName + " = " + strFilter;
				}
				else
				{
					strWhere += strDefaultKeyAtomFieldName + " = '" + strFilter + "'";
				}
			}
			
			var strQuery = "SELECT " + strField + " FROM " + strTable + " WHERE " + strWhere;
			
			strQuery = g_objPQQuery.convertQuery(strQuery);
			
			try
			{
				var strModuleKey = PQQuery.getModuleKey(this.m_nDBIndex);
				
				var strValue = g_objDataService.executeOpenScalarX(strQuery, 14, this.m_nDBIndex, strModuleKey);
				
				strResult = strValue;
			}
			catch(e)
			{
			}
			
			break;
		}
	}
	return strResult;
}

Atom.prototype.saveTextData = function (strTable, strField, strValue)
{
	var strParamValue = strValue;
	
	if (Utils.isEmpty(strParamValue))
	{
		strParamValue = "NULL";
	}
	else
	{
		strParamValue = Utils.replace(strParamValue, "'", "''");
		strParamValue = "'" + strParamValue + "'";
	}
	
	for (var j = 0; j < g_arDefaultKeyVarName.length; j++)
	{
		var arGroup = g_arDefaultKeyVarName[j]
		var strScrollName = arGroup[0];
		var strVarName = arGroup[1];
		var objLoadAtom = Model.getAtom(strVarName, strScrollName);
		
		var strWhere = "";
		
		if (objLoadAtom.getTableName() == strTable)
		{
			for (var k = 1; k < arGroup.length; k++)
			{
				var strAtomVarName = arGroup[k];
				
				var objKeyAtom = Model.getAtom(strAtomVarName, strScrollName);
				
				var strDefaultKeyAtomFieldName = objKeyAtom.getFieldName();
				var strFilter = Utils.trim(objKeyAtom.getValue());
				
				if (k > 1)
				{
					strWhere += " AND ";
				}

				var strFieldType = objKeyAtom.getFieldType();		
				if (strFieldType == "int" || strFieldType == "float" || strFieldType == "double")
				{
					strWhere += strDefaultKeyAtomFieldName + " = " + strFilter;
				}
				else
				{
					strWhere += strDefaultKeyAtomFieldName + " = '" + strFilter + "'";
				}
			}
			
			var strQuery = "UPDATE " + strTable + " SET " + strField + " = " + strParamValue + " WHERE " + strWhere;
			
			strQuery = g_objPQQuery.convertQuery(strQuery);
			
			try
			{
				var strModuleKey = PQQuery.getModuleKey(this.m_nDBIndex);
				
				var strValue = g_objDataService.executeSQL(strQuery, 14, this.m_nDBIndex, strModuleKey);
			}
			catch(e)
			{
			}
			
			break;
		}
	}
}

Atom.prototype.get_FieldProperty = function (nNameID, arArgs, objRetVal)
{
	switch (nNameID)
	{
	case 342 : // 저장속성
	{
		if ("INSERT" == this.m_strSaveType)
		{
			objRetVal.setValueType(CVariantX._vtInt, 1134);
		}
		else if ("UPDATE" == this.m_strSaveType)
		{
			objRetVal.setValueType(CVariantX._vtInt, 1136);
		}
		else if ("DELETE" == this.m_strSaveType)
		{
			objRetVal.setValueType(CVariantX._vtInt, 1152);
		}

		break;
	}
	default : return StdCore.E_NOT_DEF_PROPERTY;
	}

	return StdCore.S_OK;
}

Atom.prototype.raw_ExecOperate = function (arArgs, objRetVal)
{
	if (null != this.isOperation && this.isOperation())
	{
		PQOperation.execute(this);
	}
	
	return StdCore.S_OK;
}

Atom.prototype.raw_LandAction = function (wNameID, arArgs, objRetVal)
{
	switch (wNameID)
	{
	case 344 : // 초점주기
		if (null != this.setFocus)
		{
			this.setFocus();
		}
		objRetVal.setValue(true);
		break; 
	default  : return StdCore.E_NOT_DEF_PROPERTY;
	}
	return StdCore.S_OK;
}

Atom.prototype.get_RefProperty = function (nNameID, arArgs, objRetVal)
{
	switch (nNameID)
	{
	case 302: // 고유변수
		objRetVal.setValue(this.m_strVarName);
		break;
	case 303: // 참조아톰
		objRetVal.setValue(this.m_strRefVarName);
		break;
	case 304: // 실행모델명
		if (null != this.m_strConnectionModelName)
		{
			pRetVal.setValue(this.m_strConnectionModelName);
		}
		break;
//	case 305: // 연산식
//		objRetVal.setValue(m_pAttrib.getOperate());
//		break;
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}
	return StdCore.S_OK;
}

Atom.prototype.set_RefProperty = function (nNameID, arArgs, objValue)
{
	switch (nNameID)
	{
	case 302: // 고유변수
		break;
	case 303: // 참조아톰
		var strRefVar = objValue.toStringX();
		this.m_strRefVarName = strRefVar;
		break;
	case 304: // 실행모델명
		if (null != this.m_strConnectionModelName)
		{
			this.m_strConnectionModelName = objValue.toStringX();
		}
		break;
	case 305: // 연산식
		var strOperate = objValue.toStringX();
		var strOriginOperate = "";
		
		if (strOriginOperate != strOperate)
		{
			//m_pAttrib.setOperate(strOperate);

			// 연산식 스트링을 Parse해서 TokenList로 만들어 Attrib에서 가지고 있어야 한다.
			var bResult = this.makeAtomOperate(strOperate);
			if (bResult)
			{
			
			}
		}
		break;
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}
	return StdCore.S_OK;
}

Atom.prototype.makeAtomOperate = function (strOperate)
{
	var retValue = false;
	if (this.m_strAtomType == "GridExAtom")
	{
		//TODO 그리드 일때 처리 추가해야함.
		retValue = false;
	}
	else
	{
		if (null != strOperate && !Utils.isEmpty(strOperate))
		{
			g_objPQOperation.makeOperation(strOperate, this.m_strVarName);
			
			retValue = true;
		}
		else
		{
			retValue = true;
		}
	}
	return retValue;
}

Atom.prototype.get_GdiProperty = function (wNameID, pvaArgs, pRetVal)
{
	switch (wNameID)
	{
	case 286: // 화면감춤
		var nValue = this.isVisible() ? 1 : 0;
		pRetVal.setValueType(CVariantX._vtInt, nValue);
		break;
	case 253: // 비활성화
		var nValue = this.isDisabled() ? 1 : 0;
		pRetVal.setValueType(CVariantX._vtInt, nValue);
		break;
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	return StdCore.S_OK;
}

/**
 * 일반 아톰의 속성을 변경한다.
 */
Atom.prototype.set_GdiProperty = function (wNameID, pvaArgs, pValue)
{
	if (null == pValue)
	{
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	return this.set_GdiPropertyProc(wNameID, pvaArgs, pValue, -1);
}

Atom.prototype.set_GdiPropertyProc = function (wNameID, pvaArgs, pValue, nScrollRowIndex)
{
	switch (wNameID)
	{
	case 286: // 화면감춤
		var bHidden = pValue.toBoolean();
		
		var objAtom = this.getAtomObject(nScrollRowIndex);
		if (null != objAtom)
		{
			objAtom.setVisibility(!bHidden);
		}
		break;
	case 253: // 비활성화
		var bDisable = pValue.toBoolean();
		
		var objAtom = this.getAtomObject(nScrollRowIndex);
		if (null != objAtom)
		{
			objAtom.setDisabled(bDisable);
		}
		break;
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	return StdCore.S_OK;
}

Atom.prototype.isVisible = function ()
{
	return this.m_heAtom.style.visibiltiy;
}

Atom.prototype.isDisabled = function ()
{
	return this.m_heAtom.disabled;
}

Atom.prototype.setVisibility = function (bVisible)
{
	if (null == this.m_heAtom)
	{
		return;
	}
	
	if (bVisible)
	{
		this.m_heAtom.style.visibility = "visible";
	}
	else
	{
		this.m_heAtom.style.visibility = "hidden"; 
	}
}

Atom.prototype.setDisabled = function (bDisable)
{
	this.m_heAtom.disabled = bDisable;
}

Atom.prototype.getAtomObject = function (nRowIndex)
{
	if (this.m_strScrollName && nRowIndex)
	{
		var objScroll = ScrollAtom.getAtom(this.m_strScrollName);
		if (null == objScroll)
		{
			return null;
		}
	
		objAtom = objScroll.getBindedAtom(this.m_strVarName, parseInt(nRowIndex));
	}
	else
	{
		objAtom = Model.getAtom(this.m_strVarName);
	}
	return objAtom;
}


function MakeRequest ()
{
}

/**
 * 스크롤에 묶이지 않은 입력란 아톰에 대해 요청 XML을 만듭니다.
 * 데이터입력란, 날짜입력란, 라디오, 체크, 콤보, 이미지입력란, 간트차트
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeTouchAtomRequest = function (xnAtomRequest)
{
	// 아톰이 모델에 없는 경우에는 그 아톰의 javascript도 import되지 않기 때문에 항상 체크 해준다.
	if (ContainsAttachAtom())
	{
		AttachAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsInputDataAtom())
	{
		InputDataAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsInputTimeAtom())
	{
		InputTimeAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsInputImageAtom())
	{
		InputImageAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsComboAtom())
	{
		ComboAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsCheckAtom())
	{
		CheckAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsRadioAtom())
	{
		RadioAtomGroup.makeRequest(xnAtomRequest);
	}
	if (ContainsDocumentManagerAtom())
	{
		DocumentManagerAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsGanttChartAtom())
	{
		GanttChartAtom.makeRequest(xnAtomRequest);
	}
}


/**
 * 그리기 계열을 포함한 DBIO 관련 없는 아톰에 대해 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeDecoAtomRequest = function (xnAtomRequest)
{
	if (ContainsDecorImageAtom())
	{
		DecorImageAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsRectangleAtom() || ContainsRoundSquareAtom() || ContainsOvalAtom())
	{
		RectangleAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsItemNameAtom())
	{
		ItemNameAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsTabViewAtom())
	{
		TabViewAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 스크롤에 묶인 입력란 아톰에 대해 요청 XML을 만듭니다.
 * 스크롤
 *
 * @param xnRequest 요청 XML
 *
 * @param bOnload 모델 열림 요청 인지 아닌지의 여부, 모델 열림시 요청이면 true, 아니면 false
 */
MakeRequest.prototype.makeScrollAtomRequest = function (xnAtomRequest)
{
	if (ContainsScrollAtom())
	{
		ScrollAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 모든 검색창아톰에 대해 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeBrowseAtomRequest = function (xnAtomRequest)
{
	if (ContainsReportBrowseAtom())
	{
		ReportBrowseAtom.makeRequest(xnAtomRequest);
	}
}

MakeRequest.prototype.makeWebBoardAtomRequest = function (xnAtomRequest)
{
	if (ContainsWebBoardAtom())
	{
		WebBoardAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 모든 확장그리드 아톰에 대해 요청 xml 생성
 */
MakeRequest.prototype.makeGridExAtomRequest = function (xnAtomRequest)
{
	if (ContainsGridExAtom())
	{
		GridExAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 모든 챠트아톰에 대해 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeChartAtomRequest = function (xnAtomRequest)
{
	if (ContainsChartAtom())
	{
		ChartAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 모든 트리아톰에 대해 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeTreeAtomRequest = function (xnAtomRequest)
{
	if (ContainsTreeAtom())
	{
		TreeAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 서버에 검색을 요청 할 검색아톰에 대한 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeSearchAtomRequest = function (xnAtomRequest, strVarName, strServiceName)
{
	var objAtom = null;
	var bConnectionSearch = false;
	
	if (ContainsReportBrowseAtom())
	{
		objAtom = ReportBrowseAtom.getAtom(strVarName);
		bConnectionSearch = true;
	}
	
	if (null == objAtom && ContainsTreeAtom())
	{
		objAtom = TreeAtom.getAtom(strVarName);
	}
	
	if (null == objAtom && ContainsGridExAtom())
	{
		objAtom = GridExAtom.getAtom(strVarName);
	}
	
	if (null == objAtom && ContainsChartAtom())
	{
		objAtom = ChartAtom.getAtom(strVarName);
	}
	
	if (null == objAtom && ContainsWebBoardAtom())
	{
		objAtom = WebBoardAtom.getAtom(strVarName);
		
		// 게시판 아톰에 대해 검색 버튼의 검색 동작이 일어 난경우 
		// 최초 페이지 부터 다시 검색이 일어 난다
		// 검색 버튼을 통해 게시판 아톰의 검색이 일어난 경우 
		// 아톰의 정보를 초기 화하여 초기 검색이 일어 나도록 한다
		if (null != objAtom)
		{
			objAtom.initSearchInfo();
		}
	}
	
	if (null == objAtom)
	{
		throw new CannotFindSearchAtomException();
	}

	objAtom.makeRequest(xnAtomRequest, bConnectionSearch, strServiceName, false /* 폼 열릴때만 헤더 요청 */);
}

MakeRequest.prototype.makeSearchAtomHeaderRequest = function (xnAtomRequest)
{
	if (ContainsGridExAtom())
	{
		// 그리드 헤더를 생성하기 위한 요청 정보 생성
		GridExAtom.makeRequestForHeader(xnAtomRequest);
	}
	
	if (ContainsReportBrowseAtom())
	{
		ReportBrowseAtom.makeRequestForHeader(xnAtomRequest);
	}
}

/**
 * 즉시실행 아톰에 대한 요청 XML을 만듭니다.
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeDirectExecRequest = function (xnAtomRequest)
{
	if (ContainsReportBrowseAtom())
	{
		ReportBrowseAtom.makeDirectExecRequest(xnAtomRequest);
	}
	if (ContainsChartAtom())
	{
		ChartAtom.makeDireceExecRequest(xnAtomRequest);
	}
	if (ContainsTreeAtom())
	{
		TreeAtom.makeDireceExecRequest(xnAtomRequest);
	}
	if (ContainsWebBoardAtom())
	{
		WebBoardAtom.makeDirectExecRequest(xnAtomRequest);
	}
	if (ContainsWebTableAtom())
	{
		WebTableAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * 탭뷰아톰에 대해 요청 XML을 만듭니다.
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.prototype.makeTabViewAtomRequest = function (xnAtomRequest)
{
	if (ContainsTabViewAtom())
	{
		TabViewAtom.makeRequest(xnAtomRequest);
	}
}

MakeRequest.prototype.makeImageAtomRequest = function (xnAtomRequest)
{
	if (ContainsInputImageAtom())
	{
		InputImageAtom.makeRequest(xnAtomRequest);
	}
}

/**
 * OA 아톰의 요청정보를 만든다.
 */
MakeRequest.prototype.makeOAAtomRequest = function (xnAtomRequest)
{
	if (ContainsDHtmlAtom())
	{
		DHtmlAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsKwdAtom())
	{
		KwdAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsMoveAtom())
	{
		MoveAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsOfficeAtom())
	{
		OfficeAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsReceiverAtom())
	{
		ReceiverAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsSenderAtom())
	{
		SenderAtom.makeRequest(xnAtomRequest);
	}	
	if (ContainsRuntimeAtom())
	{
		RuntimeAtom.makeRequest(xnAtomRequest);
		//실행객체 아톰에서 동적으로 메모첨부 아톰을 만들 수 있으므로 여기에 둔다.
		MemoAtom.makeRequest(xnAtomRequest);
		ReceiptAtom.makeRequest(xnAtomRequest);
		AttachAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsSanctionAtom())
	{
		SanctionAtom.makeRequest(xnAtomRequest);
	}
}

/**
 *	엑셀출력을 위한 요청정보를 만든다.
 *	@param xnAtomRequest - 요청정보를 담을 XML 노드
 *	@param strVarName - 엑셀출력할 아톰변수명
 */
MakeRequest.prototype.makeRequestForExportExcelFile = function (xnAtomRequest, strVarName)
{
	var objAtom = null;
	
	if (ContainsReportBrowseAtom()) // 검색창
	{
		objAtom = ReportBrowseAtom.getAtom(strVarName);
	}
	if (null == objAtom && ContainsTreeAtom()) // 트리
	{
		objAtom = TreeAtom.getAtom(strVarName);
	}
	if (null == objAtom && ContainsGridExAtom()) // 확장그리드
	{
		objAtom = GridExAtom.getAtom(strVarName);
	}
	if (null == objAtom && ContainsChartAtom()) // 스크롤
	{
		objAtom = ChartAtom.getAtom(strVarName);
	}
	if (null == objAtom)
	{
		return;
	}

	objAtom.makeRequestForExportExcelFile(xnAtomRequest);
}

MakeRequest.prototype.makeWebAtomRequest = function (xnAtomRequest)
{
	if (false == IsWebModel())
	{
		return;
	}
	
	if (ContainsWebDHtmlEditAtom())
	{
		WebDHtmlEditAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebFileAttachAtom())
	{
		WebFileAttachAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebPictureAtom())
	{
		WebPictureAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebRssAtom())
	{
		WebRssAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebHyperLinkAtom())
	{
		WebHyperLinkAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebHyperDataAtom())
	{
		WebHyperDataAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebModelAtom())
	{
		WebModelAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebIFrameAtom())
	{
		WebIFrameAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebHtmlModelAtom())
	{
		WebHtmlModelAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebHtmlTagAtom())
	{
		WebHtmlTagAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebFlashAtom())
	{
		WebFlashAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebSlidePanelAtom())
	{
		WebSlidePanelAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebTreeMenuAtom())
	{
		WebTreeMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebSlideMenuAtom())
	{
		WebSlideMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebComboMenuAtom())
	{
		WebComboMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebDropMenuAtom())
	{
		WebDropMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebLinkMenuAtom())
	{
		WebLinkMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebLabelMenuAtom())
	{
		WebLabelMenuAtom.makeRequest(xnAtomRequest);
	}
	if (ContainsWebTabMenuAtom())
	{
		WebTabMenuAtom.makeRequest(xnAtomRequest);
	}
}

MakeRequest.init = function ()
{
	g_objMakeRequest = new MakeRequest();
}

/**
 * 요청 XML을 만듭니다.
 *
 * @param xnRequest 현재 <Model /> 노드
 */
MakeRequest.createRequestNode = function ()
{
	var xnRequestDoc = XmlLib.createXML("Request");
	xnRequest = xnRequestDoc.documentElement;
	return XmlLib.createChild(xnRequest, "Model");
}

/**
 * 요청 XML에서 <Atom>노드를 반환합니다.
 * @return 요청 XML <Atom>노드
 */
MakeRequest.getAtomRequestNode = function (xnRequest)
{
	var xnAtomRequest = XmlLib.selectSingleNode(xnRequest, "./Atom");
	if (null == xnAtomRequest)
	{
		xnAtomRequest = XmlLib.createChild(xnRequest, "Atom");
	}
	
	return xnAtomRequest;
}

MakeRequest.makeServiceRequest = function (xnRequest)
{
	var xnServiceRequest = XmlLib.createChild(xnRequest, "Service");
	
	var htModelInfo = GlobalField.getModelInfo();
	for (var strName in htModelInfo)
	{
		if ("length" == strName)
		{
			continue;
		}
		
		var strValue = htModelInfo[strName];
		
		XmlLib.createChildWithValue(xnServiceRequest, strName, strValue);
	}
	
	// ModelAction이면 부모창에서 넘어온 참조아톰정보 추가
	if ("ModelAction" == GlobalField.getServiceName())
	{
		// 부모창에서 받은 참조아톰정보를 요청에 추가
		MakeRequest.addRefAtomInfo(xnServiceRequest);
	}
	
	// 서비스 요청을 만들고, 정보를 초기화 합니다.
	GlobalField.initModelInfo();
}

/**
 * 주의 : ModelAction에서 사용한다.
 * 요청에 부모폼으로부터 넘어온 참조아톰정보 추가
 */
MakeRequest.addRefAtomInfo = function (xnServiceRequest)
{
	var xnRefAtomInfos = XmlLib.createChild(xnServiceRequest, "RefAtomInfos");
	var objRefAtomInfos = GlobalField.getRefAtomInfos();
	
	for (var strVarName in objRefAtomInfos)
	{
		var xnRefAtomInfo = XmlLib.createChild(xnRefAtomInfos, "RefAtomInfo");
		
		XmlLib.setAttribute(xnRefAtomInfo, "VarName", strVarName);
		XmlLib.setAttribute(xnRefAtomInfo, "Value", objRefAtomInfos[strVarName]);
	}
}

/**
 * 모든 아톰에 대해 요청 XML을 만듭니다.
 * (사용 : 스크립트)
 *
 * @param xnRequest 요청 XML
 *        bSearch	: 아톰 요청을 만들때, 검색창 계열 아톰을 포함 시키는지 여부
 */
MakeRequest.makeAtomRequest = function (xnRequest, bSearch)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeTouchAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeScrollAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeTreeAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeDecoAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeOAAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeWebAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeWebBoardAtomRequest(xnAtomRequest);
	
	if (true != bSearch)	// false == bSearch 로 바꾸지 마세요. by SiamDaArc
	{
		g_objMakeRequest.makeBrowseAtomRequest(xnAtomRequest);
		g_objMakeRequest.makeGridExAtomRequest(xnAtomRequest);
	}
}

/**
 *	엑셀출력을 위한 요청정보를 만든다.
 *	@param xnRequest - 요청정보가 담길 XML 노드
 *	@param strVarName - 엑셀출력할 아톰 변수명
 */
MakeRequest.makeRequestForExportExcelFile = function (xnRequest, strVarName)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeRequestForExportExcelFile(xnAtomRequest, strVarName);
}

/**
 * 입력란 아톰에 대해 요청 XML을 만듭니다.
 * 데이터입려란, 날짜입력란, 라디오, 체크, 콤보, 이미지입력란, 간트차트, 스크롤
 * (사용 : 저장)
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.makeInputAtomRequest = function (xnRequest)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeTouchAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeScrollAtomRequest(xnAtomRequest);
}

/**
 * 스크롤에 묶이지 않은 입력란 아톰에 대해 요청 XML을 만듭니다.
 * 데이터입려란, 날짜입력란, 라디오, 체크, 콤보, 이미지입력란
 * (사용 : 앞장/뒷장, 삭제, 검색)
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.makeTouchAtomRequest = function (xnRequest)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeTouchAtomRequest(xnAtomRequest);
}

/**
 * 서버에 검색을 요청 할 검색아톰에 대한 요청 XML을 만듭니다.
 * (사용 : 검색)
 *
 * @param xnRequest 요청 XML
 */
MakeRequest.makeSearchAtomRequest = function (xnRequest, strVarName, strServiceName)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeSearchAtomRequest(xnAtomRequest, strVarName, strServiceName);
}

MakeRequest.makeDecoAtomRequest = function (xnRequest)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeDecoAtomRequest(xnAtomRequest);
}

MakeRequest.makeWebAtomRequest = function (xnRequest)
{
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeWebAtomRequest(xnAtomRequest);
}

/**
 * 폼 열림시 데이터를 로드하기 위한 요청 XML을 만듭니다.
 * @param xnRequest 요청 XML
 */
MakeRequest.makeLoadDataRequest = function (xnRequest)
{
	// <Atom> 노드 구성
	var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);
	
	g_objMakeRequest.makeTouchAtomRequest(xnAtomRequest);
	g_objMakeRequest.makeDecoAtomRequest(xnAtomRequest);
	
	// 모델 로드 요청 임을 알리는 boolean 값을 같이 넘긴다
	g_objMakeRequest.makeScrollAtomRequest(xnAtomRequest);
	
	// 문서 열림시 이미지 입력란 정보를 가져오기 위해 필요하다.
	g_objMakeRequest.makeImageAtomRequest(xnAtomRequest);
	
	// 검색창 계열 아톰 헤더 요청
	g_objMakeRequest.makeSearchAtomHeaderRequest(xnAtomRequest);
	
	// 검색창, 트리 즉시실행에 대한 요청 정보를 만듭니다.
	g_objMakeRequest.makeDirectExecRequest(xnAtomRequest);
	
	//일반모델에 올라갈 수 있는 OA 아톰에 대한 요청 정보를 만든다.
	g_objMakeRequest.makeOAAtomRequest(xnAtomRequest);
	
	g_objMakeRequest.makeWebAtomRequest(xnAtomRequest);
}

/**
 * 문서모델에서 스크립트 동작으로 변경될수 있는 속성에 대한 요청을 생성한다.
 */
MakeRequest.makeNtoaScriptRequest = function (xnRequest)
{
	var xnNtoaRequest = XmlLib.createChild(xnRequest, "Ntoa");
	
	g_objMasterInfomation.makeRequest(xnNtoaRequest);
	g_objMasterInfomation.makeMasterAttribRequest(xnNtoaRequest);
	
	g_objProcessInfomation.makeRequest(xnNtoaRequest);
}

function HandleResult ()
{
}

HandleResult.prototype.handleAtomResult = function (xnResult)
{
	if (null == xnResult)
	{
		return;
	}
	
	var xnAtomResult = HandleResult.getAtomNode(xnResult);
	if (null == xnAtomResult)
	{
		return;
	}
	
	/*
	 * 조회 X: 이벤트 발생, 검색아톰 검색동작, 사용자가 직접 입력했을 경우, 실제로는 의미없음
	 * 조회 O: 이벤트 발생 안함
	 */
	var nOccurEventType = Define.OCCUR_EVENT; // 이벤트 발생
	
	if (this._handleRefresh(xnAtomResult))
	{
		nOccurEventType = Define.NO_OCCUR_EVENT; // 이벤트 발생 안함
	}
	
	this._handleAtomResult(xnAtomResult, nOccurEventType);
	
	this._handleNtoaAtomResult(xnAtomResult);
	
	this._handleMemoryPopupResult(xnAtomResult);
}

HandleResult.prototype.handleOperateResult = function (xnResult)
{
	if (null != xnResult)
	{
		var xnOperateResult = HandleResult.getOperateNode(xnResult);
		if (null != xnOperateResult)
		{
			var bChanged = "true" == xnOperateResult.getAttribute("isChange");
			if (bChanged)
			{
				var xnOperate = xnOperateResult.firstChild;
				if (null != xnOperate)
				{
					PQOperation.change(xnOperate);
				}
			}
		}
	}
}

/**
 * 기본키 아톰의 저장속성을 설정한다.
 */
HandleResult.prototype.setSaveType = function (xnResult)
{
	if (null != xnResult)
	{
		var xnAtomResult = HandleResult.getAtomNode(xnResult);
		if (null != xnAtomResult)
		{
			var xlAtomList = xnAtomResult.childNodes;				
			for (var i = 0, nLen = xlAtomList.length; i != nLen; i=i+1)
			{
				var xnAtom = xlAtomList[i];
				
				var strAtomType = xnAtom.nodeName;
				var strVarName = xnAtom.getAttribute("VarName");					
				var objAtom = null;
				if ("InputData" == strAtomType)
				{
					objAtom = InputDataAtom.getAtom(strVarName);
				}
				else if ("InputTime" == strAtomType)
				{
					objAtom = InputTimeAtom.getAtom(strVarName);
				}
				else if ("Combo" == strAtomType)
				{
					objAtom = ComboAtom.getAtom(strVarName);
				}
				else if ("CheckAtom" == strAtomType)
				{
					objAtom = CheckAtom.getAtom (strVarName);
				}
				else if ("Radio" == strAtomType)
				{
					objAtom = RadioAtom.getAtom (strVarName);
				}
				
				// 기본키가 설정된 아톰의 저장속성을 설정한다.
				var strSaveType = xnAtom.getAttribute("SaveType");
				if (null != objAtom  && objAtom.setSaveType && (null != strSaveType && 0 < strSaveType.length))
				{
					objAtom.setSaveType(strSaveType);
				}
			}
		}
	}
}

/**
 * 화면이 새로 고쳐지는 결과이면, 화면을 모두 지웁니다.
 *  - 저장, 삭제, 앞장/뒷장
 * @param xnAtomResult 아톰 결과 최상위 노드
 */
HandleResult.prototype._handleRefresh = function (xnAtomResult)
{
	if (xnAtomResult.getAttribute("IsRefresh"))
	{
		// 모든 탭뷰 저장검색
		if (IsAllSave())
		{
			g_objModelCore.clearAtomValue();
		}
		// 개별뷰이면 해당뷰만 처리
		else
		{
			if (ContainsTabViewAtom())
			{
				var nTabIndex = parseInt(XmlLib.getAttribute(xnAtomResult, "ExecuteTabIndex"));
				TabViewAtom.clearAtomValue(nTabIndex);
			}
		}
		
		return true;
	}
	
	return false;
}

/**
 * 아톰의 결과값을 처리합니다.
 * @param xnAtomResult 아톰 결과 최상위 노드
 */
HandleResult.prototype._handleAtomResult = function (xnAtomResult, nOccurEventType)
{
	// 입력란의 처리가 끝난다음에 처리해야할 아톰들
	var arAtom = new Array(); 
	
	// WebModelAtom은 결과 처리를 가장 마지막에 합니다.
	// WebModelAtom의 이동 기능때문이다.
	// 다른 아톰의 결과가 다 처리 된 다음에 이동해야 한다. 
	var arModelAtomList = new Array();
	// 하이퍼링크의 이동은 다른 아톰들의 값이 필요한 경우가 있기 때문에 나중에 처리됩니다.
	var arHyperDataAtomList = new Array();
	
	var xlAtomList = xnAtomResult.childNodes;
	
	for (var i = 0; i < xlAtomList.length; i=i+1)
	{
		var xnAtom = xlAtomList[i];
		var strAtomType = xnAtom.nodeName;
		var strVarName = xnAtom.getAttribute("VarName");
		
		if ("CheckAtom" == strAtomType)
		{
			CheckAtom.getAtom(strVarName).handleResult(xnAtom);
		}
		else if ("Combo" == strAtomType)
		{
			var objAtom = ComboAtom.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
		}
		else if ("Scroll" == strAtomType)
		{
			ScrollAtom.getAtom(strVarName).handleResult(xnAtom, nOccurEventType);
		}
		// 입력란의 처리가 끝나고 나서 처리되어야 할 아톰들
		else if ("Chart" == strAtomType
			|| "DocumentManager" == strAtomType
			|| "GridEx" == strAtomType
			|| "ReportBrowse" == strAtomType
			|| "TabView" == strAtomType
			|| "Tree" == strAtomType
			|| "WebBoard" == strAtomType
			|| "WebTable" == strAtomType)
		{
			arAtom.push(xnAtom);
		}
		else if ("AttachAtom" == strAtomType)
		{
			var objAtom = AttachAtom.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);				
			}
			else
			{
				//실행객체 아톰에서 추가한 경우.
				AttachAtom.RUN_TIME_VAR_NAME = "ATTACH";
				var objRuntimeAtom = RuntimeAtom.getAtom();
				if (null != objRuntimeAtom)
				{
					AttachAtom.makeAddedAtom(objRuntimeAtom.getTableName(), objRuntimeAtom.getFieldName(), objRuntimeAtom.getRefVarName());
					objAtom = AttachAtom.getAtom(AttachAtom.RUN_TIME_VAR_NAME);
					objAtom.setValue(xnAtom);
				}
			}
		}
		else if ("WebDHtmlEditAtom" == strAtomType)
		{
			var objAtom = WebDHtmlEditAtom.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.handleResult(xnAtom);
			}
		}
		else if ("WebHtmlTagAtom" == strAtomType)
		{
			var objAtom = WebHtmlTagAtom.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
		}
		else if ("WebFileAttachAtom" == strAtomType)
		{
			var objAtom = Model.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
		}
		else if ("WebPictureAtom" == strAtomType)
		{
			var objAtom = Model.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.handleResult(xnAtom);
			}
		}
		else if ("WebRssAtom" == strAtomType)
		{
			WebRssAtom.getAtom(strVarName).handleResult(xnAtom);
		}
		else if ("WebHyperLinkAtom" == strAtomType)
		{
			var objAtom = WebHyperLinkAtom.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
		}
		else if ("WebHyperDataAtom" == strAtomType)
		{
			var objAtom = Model.getAtom(strVarName);
			if ("true" == xnAtom.getAttribute("Move"))
			{
				arHyperDataAtomList.push(strVarName);
			}

			objAtom.handleResult(xnAtom);				
		}
		else if ("WebFlashAtom" == strAtomType)
		{
			var objAtom = WebFlashAtom.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
		}
		else if ("WebSlidePanelAtom" == strAtomType)
		{
			WebSlidePanelAtom.getAtom(strVarName).handleResult(xnAtom);
		}
		else if ("WebModelAtom" == strAtomType ||
				 "WebIFrameAtom" == strAtomType ||
				 "WebHtmlModelAtom" == strAtomType)
		{
			// 모든 아톰의 처리가 끝나고 나서 웹모델아톰을 처리한다.
			arModelAtomList.push(xnAtom)
		}
		else if ("WebMenu" == strAtomType)
		{
			var objAtom = Model.getAtom(strVarName);
			objAtom.handleResult(xnAtom);
			
		}
		else // 결과 XML 에서 값이 TextNode 뿐인 아톰
		{
			var objAtom = null;
			
			if ("InputData" == strAtomType)
			{
				objAtom = InputDataAtom.getAtom(strVarName);
				var strPrefix = xnAtom.getAttribute("Prefix");
				
				if (objAtom && strPrefix)
				{
					objAtom.setPrefix(strPrefix);
				}
			}
			else if ("InputTime" == strAtomType)
			{
				objAtom = InputTimeAtom.getAtom(strVarName);
			}
			else if ("InputImageAtom" == strAtomType)
			{
				objAtom = InputImageAtom.getAtom(strVarName);
			}
			else if ("Radio" == strAtomType)
			{
				objAtom = RadioAtom.getAtom(strVarName);
				if (null != objAtom)
				{
					objAtom.setDisplayString(xnAtom.getAttribute("DefaultString"));
					
				    if ("Y" == objAtom.getGroupKey())
				    {
				    	objAtom.setSelectValue(XmlLib.getTextValue(xnAtom));
				    }
			    }
			    continue;
			}
			else if ("RectangleAtom" == strAtomType)
			{
				objAtom = RectangleAtom.getAtom(strVarName);
			}
			else if ("Progress" == strAtomType)
			{
				objAtom = ProgressAtom.getAtom(strVarName);
			}
			else if ("Button" == strAtomType)
			{
				objAtom = ButtonAtom.getAtom (strVarName);
				var strValue = XmlLib.getTextValue(xnAtom);
				objAtom.setTextByScript(strValue);
				continue;
			}
			else if ("GanttChart" == strAtomType)
			{
				objAtom = GanttChartAtom.getAtom(strVarName);
			}
			
			else if ("DecorImage" == strAtomType)
			{
				objAtom = DecorImageAtom.getAtom(strVarName);
			}
			
			if (null == objAtom)
			{
				continue;
			}

			// 기본키가 설정된 아톰의 저장속성을 설정한다.
			var strSaveType = xnAtom.getAttribute("SaveType");
			if (objAtom.setSaveType && (null != strSaveType && 0 < strSaveType.length))
			{
				objAtom.setSaveType(strSaveType);
			}
			// Atom.setValue()에서 연산식이 발생하므로 값 설정 전에 연산식 실행 여부를 설정해줘야한다.
			// Applet에서 연산식을 수행하였기 때문에 handleResult에서는 연산식 수행하지 않습니다.
			if (objAtom.setIsOperation)
			{					
				objAtom.setIsOperation(false);
			}
			
			objAtom.setValue(XmlLib.getTextValue(xnAtom), nOccurEventType);
			
			if (objAtom.setIsOperation)
			{
				objAtom.setIsOperation(true);
			}
		}	
	}
		
	if (ContainsButtonAtom())
	{
		ButtonAtom.changeButtonTitle(); // "저장" 버튼의 텍스트 변경 : "저장" <-> "수정"
		ButtonAtom.disableDeleteButton(); // "삭제" 버튼의 (비)활성화
	}

	if (ContainsScrollAtom())
	{
		ScrollAtom.refreshValidRowCount();
	}
	
	this._handleHyperDataAtomResult(arHyperDataAtomList);
	this._handleRestAtomResult(arAtom, xnAtomResult.getAttribute("IsRefresh"));
	this._handleModelAtomResult(arModelAtomList);
}

/**
 * 하이퍼링크의 이동을 처리합니다.
 * 다른 아톰들의 값이 필요한 경우가 있기 때문에 나중에 처리됩니다.
 */
HandleResult.prototype._handleHyperDataAtomResult = function (arHyperDataAtomList)
{
	var nLen = arHyperDataAtomList.length;
	for (var i = 0; i < nLen; i=i+1)
	{
		var strVarName = arHyperDataAtomList[i];
		var objAtom = Model.getAtom(strVarName);
		
		if (null != objAtom)
		{
			objAtom.connectLink();
		}
	}
}

HandleResult.prototype._handleModelAtomResult = function (arAtomList)
{
	var nLen = arAtomList.length;
	for (var i = 0; i < nLen; i=i+1)
	{
		var xnAtom = arAtomList[i];
		var strVarName = xnAtom.getAttribute("VarName");
		
		var objAtom = null;
		if (ContainsWebModelAtom())
		{
			objAtom = WebModelAtom.getAtom(strVarName);
		}
		if (null == objAtom && ContainsWebIFrameAtom())
		{
			objAtom = WebIFrameAtom.getAtom(strVarName);
		}
		if (null == objAtom && ContainsWebHtmlModelAtom())
		{
			objAtom = WebHtmlModelAtom.getAtom(strVarName);
		}
		
		if (null != objAtom)
		{
			objAtom.handleResult(xnAtom);
		}
	}
}

/**
 * 입력란의 처리가 끝난 후에 처리되어야 할 아톰들을 처리합니다.
 * @param arAtomList 마지막에 처리할 아톰 리스트
 */
HandleResult.prototype._handleRestAtomResult = function (arAtomList, strIsRefresh)
{
	for (var i = 0; i < arAtomList.length; i=i+1)
	{
		var xnAtom = arAtomList[i];
		var strAtomType = xnAtom.nodeName;
		var strVarName = xnAtom.getAttribute("VarName");
		
		if ("Chart" == strAtomType)
		{
			var objAtom = ChartAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
		else if ("DocumentManager" == strAtomType)
		{
			var objAtom = DocumentManagerAtom.getAtom(strVarName);
			objAtom.setValue(XmlLib.getTextValue(xnAtom));
			
			// 통합문서관리 아톰은 refresh 일때만, 조회 요청을 수행한다.
			if (strIsRefresh)
			{
				objAtom.processInquiry();
			}
		}
		else if ("GridEx" == strAtomType)
		{
			var objAtom = GridExAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
		else if ("ReportBrowse" == strAtomType)
		{
			var objAtom = ReportBrowseAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
		else if ("TabView" == strAtomType)
		{
			var objAtom = TabViewAtom.getAtom(strVarName);
			objAtom.selectTabPage(parseInt(xnAtom.getAttribute("SelectTab")));
		}
		else if ("Tree" == strAtomType)
		{
			var objAtom = TreeAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
		else if ("WebBoard" == strAtomType)
		{
			var objAtom = WebBoardAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
		else if ("WebTable" == strAtomType)
		{
			var objAtom = WebTableAtom.getAtom(strVarName);
			objAtom.setValue(xnAtom);
		}
	}
}

/**
 * 일반모델에 포함된 OA 아톰의 결과를 처리한다.
 * 예를 들어 일반모델에 포함된 수신자목록 아톰에 수신자 목록을 넣어준다.
 */
HandleResult.prototype._handleNtoaAtomResult = function (xnAtomResult)
{
	var xlAtomList = xnAtomResult.childNodes;
	var nLen = xlAtomList.length;
	
	for (var i = 0; i < nLen; i += 1)
	{
		var xnAtom = xlAtomList[i];
		
		var strAtomType = xnAtom.nodeName;
		var strVarName = xnAtom.getAttribute("VarName");
		
		if ("Sender" == strAtomType)
		{
			var objAtom = SenderAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.handleResult(xnAtom);
			}
		}
		else if ("Receive" == strAtomType)
		{
			var objAtom = ReceiverAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
		}
		else if ("KWD" == strAtomType)
		{
			var objAtom = KwdAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
		}
		else if ("DHtml" == strAtomType)
		{
			var objAtom = DHtmlAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.handleResult(xnAtom);
			}
		}
		else if ("RuntimeAtom" == strAtomType)
		{
			var objAtom = RuntimeAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
		}
		else if ("MemoAtom" == strAtomType)
		{
			var objAtom = MemoAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
			else
			{
				MemoAtom.addTempMemoAtom(strVarName, xnAtom);
			}
		}
		else if ("Move" == strAtomType)
		{
			var objAtom = MoveAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
			else
			{
				MoveAtom.addTempMemoAtom(strVarName, xnAtom);
			}
		}
		else if ("ReceiptAtom" == strAtomType)
		{
			var objAtom = ReceiptAtom.getAtom();
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
			else 
			{
				ReceiptAtom.addTempReceiptAtom(strVarName, xnAtom);
			}
		}
		else if ("Office" == strAtomType)
		{
			var objAtom = OfficeAtom.getAtom(strVarName);
			
			if (null != objAtom)
			{
				objAtom.setValue(xnAtom);
			}
		}
		else if ("Sanction" == strAtomType)
		{
			var objAtom = SanctionAtom.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.setSanctionInfo(xnAtom);
				objAtom.displaySanction();
			}
		}
	}
	
	if (ContainsRuntimeAtom())
	{
		RuntimeAtom.makeAddedAtom();
	}
}

HandleResult.prototype._handleMemoryPopupResult = function (xnAtomResult)
{
	if (ContainsPopupAtom())
	{
		// 입력란의 onChange이벤트에 의해 들어간 다른 입력란에 들어간 메모리 팝업값이
		// 다른 입력란 자체의 결과값에 의해서 바뀌는 현상 발생하므로
		// 메모리 팝업의 값을 다시 한번 설정해 준다.
		PopupAtom.handleMemoryPopupResult();
	}
}

///////////////////////////////////
// static method
//

HandleResult.init = function ()
{
	g_objHandleResult = new HandleResult();
}

HandleResult.getResultNode = function (xnResultDoc)
{
	return XmlLib.selectSingleNode(xnResultDoc, "/Result/Model");
}

HandleResult.getAtomResultNode = function (xnResultDoc)
{
	return XmlLib.selectSingleNode(xnResultDoc, "/Result/Model/Atom");
}

HandleResult.getNtoaResultNode = function (xnResultDoc)
{
	return XmlLib.selectSingleNode(xnResultDoc, "/Result/Model/Ntoa");
}

HandleResult.getAtomNode = function (xnResult)
{
	return XmlLib.selectSingleNode(xnResult, "./Atom");
}

HandleResult.getOperateNode = function (xnResult)
{
	return XmlLib.selectSingleNode(xnResult, "./Operate");
}

HandleResult.getScriptNode = function (xnResult)
{
	return XmlLib.selectSingleNode(xnResult, "./Script");
}

/**
 * 아톰 기능으로 동작한 결과를 처리합니다.
 * @param xnResultDoc - 결과 XML
 */
HandleResult.execute = function (xnResultDoc)
{
	var xnResult = HandleResult.getResultNode(xnResultDoc);
	
	HandleResult.handleAtomResult(xnResult);
}

/**
 * 아톰 결과를 처리합니다.
 */
HandleResult.handleAtomResult = function (xnResult)
{
	g_objHandleResult.handleAtomResult(xnResult);
}

HandleResult.handleOperateResult = function (xnResult)
{
	g_objHandleResult.handleOperateResult(xnResult);
}

HandleResult.handleNtoaModelResult = function (xnResultDoc)
{
	if (null != xnResultDoc)
	{
		// 애플릿간 통신을 위해 PQService 애플릿 ID를 결재처리란에 전달한다.
		var xnUniqueID = XmlLib.selectSingleNode(xnResultDoc, "/Result/Model/UniqueID");
		var strUniqueID = XmlLib.getTextValue(xnUniqueID);
		
		/**
		 * 객체처리란 applet 객체 생성을 initAtomList에서 할 경우, 두번이상 기안지를 띄우면 늦어지는 현상이 발생하였다.
		 * applet 객체 생성 시점을 NtoaModelAction 결과 처리할때로 변경하니까 그런 현상이 발생하지 않았다.
		 */
		if (ContainsSanctionAtom())
		{
			SanctionAtom.init(strUniqueID);
		}
		
		g_objProcessInfomation.handleResult(xnResultDoc);
		
		g_objMasterInfomation.handleResult(xnResultDoc);
		
		g_objProcessInfomation.handleSanctionResult(xnResultDoc);
	}
}


HandleResult.handleNtoaScriptResult = function (xnResultDoc)
{
	if (null != xnResultDoc)
	{
		// 결재실행과 같은 스크립트가 시행시에 사용되므로 처리함
		g_objProcessInfomation.handleResult(xnResultDoc);
		
		g_objMasterInfomation.handleResult(xnResultDoc);
		
		g_objProcessInfomation.handleSanctionResult(xnResultDoc);
	}
}

/**
 * 기본키 아톰의 저장속성을 설정한다.
 */
HandleResult.setSaveType = function (xnResultDoc)
{
	var xnResult = HandleResult.getResultNode(xnResultDoc);
	
	g_objHandleResult.setSaveType(xnResult);
}


/**
* Model을 로드하기 위한 사전 작업(아톰 만들기, 초기와 , Window초기화 등 의 작업) 수행
* Model의 Type을 구별하여 Load
*/
function ModelCore ()
{
}

ModelCore.prototype.clearAtomValue = function ()
{
	// 아톰이 모델에 없는 경우에는 그 아톰의 javascript도 import되지 않기 때문에 항상 체크 해준다.
	if (ContainsScrollAtom())
	{
		ScrollAtom.init();
	}
	if (ContainsInputDataAtom())
	{
		InputDataAtom.init(IsNotClear());
	}
	
	if (!IsNotClear())
	{	
		if (ContainsInputTimeAtom())
		{
			InputTimeAtom.init();
		}
		if (ContainsInputImageAtom())
		{
			InputImageAtom.init();
		}
		if (ContainsComboAtom())
		{
			ComboAtom.init();
		}
		if (ContainsCheckAtom())
		{
			CheckAtom.init();
		}
		if (ContainsRadioAtom())
		{
			RadioAtomGroup.init();
		}
	}
	if (ContainsButtonAtom())
	{
		ButtonAtom.init();
	}
	
	// NTOA 아톰
	if (ContainsAttachAtom())
	{
		AttachAtom.init();
	}
	if (ContainsDocumentManagerAtom())
	{
		DocumentManagerAtom.init();
	}
	if (ContainsGanttChartAtom())
	{
		GanttChartAtom.clear();
	}
	
	// 웹 아톰
	if (ContainsWebDHtmlEditAtom())
	{
		WebDHtmlEditAtom.clear();
	}
	if (ContainsWebFileAttachAtom())
	{
		WebFileAttachAtom.init();
	}
}


////////////////////////////////////////////////////////////
// event handler
ModelCore.prototype.onLoadForNoAction = function (strModelName)
{
	g_bTrialVersion = true;
	
	this._initWindowSizeForTrial();
	this._alignModel();
	this._initModel();
	this._initAtom();
}

ModelCore.prototype.onLoad = function (strModelName)
{
	this._checkEmbededModel();
	
	this._initWindowSize(strModelName);
	
	if(IsDotNet() && ContainsWebLoginAtom())
	{
		this._bosCheck();
	}
	
	this._initGlobalTool();
	this._initModel();
	
	//버튼, 메뉴 아톰 등에서 권한 검사 하기 전에 포털 로그인 사용자 정보가 있어야 한다.
	ModelCore.getPortalUserData();
	
	if (false == IsWebModel())
	{
		this._checkSolutionLogin();
	}
	
	this._initAtom(); // 아톰 초기화
	this._loadData(); // 데이터 로드
	
	if (IsWebModel())
	{
		if (ContainsWebModelAtom())
		{
			WebModelAtom.init();
		}
		if (ContainsWebHtmlModelAtom())
		{
			WebHtmlModelAtom.init();
		}
		
		ScriptFormEvent.onLoad();
		
		this._setMyAddress();
		
		// body.onload 시점에 vml 엘리먼트가 완전히 렌더링되지 않는다.
		// vml 엘리먼트가 모델의 맨 아래 위치 했을 경우 offsetHeight를 제대로 구할 수 없다.
		// body.onload 이벤트 핸들러 종료 후, 어느 시점(?)에 vml 엘리먼트 랜더링이 완료된다.
		// vml 엘리먼트의 랜더링 완료 후에 '모델삽입' 아톰의 스크롤 세팅을 하기 위해 타이머 설정함.
		// 
		// TODO: 왜 body.onload 시점에 vml 엘리먼트의 랜더링이 되어 있지 않는지 알아내고,
		// 타이머를 사용하지 않는 방향으로 수정해야 함.
		setTimeout(
			function ()
			{
				if (GlobalField.isEmbededModel())
				{
					window.parent.WebModelAtom.setWebModelScroll();
				}
			}, 1 // 0.001 초 후에
		);
		
		//웹퀵링크 아톰의 움직임을 부드럽게 하기 위해서 ...
		if (ContainsWebQuickLinkAtom())
		{
			window.setTimeout("WebQuickLinkAtom.repositionYPos()", 500);
		}
		
		//this._addWebModelList();
	}
	else
	{
		// 자식폼은 폼_열림 스크립트를 실행하지 않습니다.
		// 폼이 모두 로딩 되었다는 플래그를 설정합니다.
		if (IsOpenChildModel())
		{
			// 부모 폼에게 자신의 로드가 끝났다는 것을 알립니다.
			PQScript.modelLoadInform();
			
			// 부모폼의 연결모델 정보 초기화
			this._clearParentConnectionInfo();
		}
		else
		{
			// 폼_열림 스크립트
			ScriptFormEvent.onLoad();
		}
	}
	
	// 시간 측정 결과 출력
//	Utils.printTimeCheckResult();
}

ModelCore.prototype._checkSolutionLogin = function ()
{
	var objParent = ModelCore.getParentWindow();
	if (objParent)
	{
		g_nSolutionLoginState = objParent.g_nSolutionLoginState;
	}
	
	//IE8에서 애플릿마다 java.exe 프로세스가 생성되면서 전역정보가 공유되지않는 문제가 있기 때문에
	//모델의 애플릿에 솔루션 로그인 설정을 해준다.
	if (g_objPQService.setSolutionLoggedin())
	{
		g_nSolutionLoginState = SOLUTION_LOGIN_GLOBAL;
		
		if (objParent)
		{
			objParent.g_nSolutionLoginState = g_nSolutionLoginState;
		}
		
		// 서버접속 아톰의 이미지 변경을 위해서..
		if (ContainsWebLoginAtom())
		{
			WebLoginAtom.init();
		}
		// 다이어리 아톰의 데이터를 가져오기 위해서...
		if (ContainsWebSchedulerAtom())
		{
			WebSchedulerAtom.load();
		}
	}
}

ModelCore.prototype.onUnload = function ()
{
	// 사진게시 아톰이 저장되지 않았으면 '미리보기'를 위해 업로드했던 파일을 삭제
	if (ContainsWebPictureAtom() && !WebPictureAtom.isSaved())
	{
		WebPictureAtom.deleteUploadedFile();
	}

	// 웹편집기와 서버간의 이미지파일 동기화
	if (ContainsWebDHtmlEditAtom())
	{
		WebDHtmlEditAtom.synchronizeImageFile();
	}
	
	if (ContainsReportBrowseAtom())
	{
		ReportBrowseAtom.saveAttrib();
	}
	
	if (ContainsGridExAtom())
	{
		GridExAtom.saveAttrib();
	}
	
	// 폼_닫힘 스크립트
	ScriptFormEvent.onUnload();
	
	this._closeModel();
	
	if (IsWebModel())
	{
		// unload 이벤트가 창닫을때 또는 주소 바뀔때 일어난지를 판단할 수 없음
		//this._removeWebModelList();		
	}
}

/**
 * 뒤로가기, F5 리프레시 등에 의해서 페이지에서 벗어나려고 할 때 발생하는 이벤트 처리.
 */
ModelCore.prototype.onBeforeUnload = function (objEvent)
{
	if (IsWPQModel())
	{
		//작성 중인 경우 문서에서 벗어나면 내용이 다 사라지므로 확인 메시지 띄운다.
		//단, 결재를 했거나 새로운 서식/문서를 여는 등의 경우에는 메시지가 안 나오도록 한다.
		event.returnValue = "이 페이지를 벗어나면 작성중인 문서가 저장되지 않습니다.";
	}
}

/**
 * 웹페이지 모델이 열리면 열려있는 모델 관리 목록에 추가합니다.
 */
ModelCore.prototype._addWebModelList = function ()
{
	var newModelUID = GlobalField.createModelUID();	
	
	var strCookieValue = CookieLib.getCookie("_WebModelList_");
	var arWebModelList = strCookieValue.split(",");
	var bExists = false;
	for (var i = 0, nLen = arWebModelList.length; i != nLen; i++)
	{
		var strModelUID = arWebModelList[i];
		if (newModelUID == strModelUID)
		{
			bExists = true;
			break;
		}
	}
	
	if (!bExists)
	{
		arWebModelList.push(newModelUID);
	}
	
	CookieLib.setCookie("_WebModelList_", arWebModelList.join(), 1);
}

/**
 * 웹페이지 모델이 닫히면 열려있는 모델 관리 목록에서 제거합니다.
 */
ModelCore.prototype._removeWebModelList = function ()
{
	var thisModelUID = GlobalField.getModelUID();
	
	var arNewList = new Array();
	
	var strCookieValue = CookieLib.getCookie("_WebModelList_");
	var arWebModelList = strCookieValue.split(",");
	for (var i = 0, nLen = arWebModelList.length; i != nLen; i++)
	{
		var strModelUID = arWebModelList[i];
		if ("" != strModelUID && thisModelUID != strModelUID)
		{
			arNewList.push(strModelUID);
		}
	}
	
	//열렸던 모든 웹페이지가 닫히면 로그아웃. 단, 로그인하면서 페이지 전환되는건 제외. 
	if (0 == arNewList.length && !GlobalField.isWebLoginInProgress())
	{
		CookieLib.setCookie("_WebModelList_", "", 1);
		if (ContainsWebLoginAtom())
		{
			WebLoginAtom.logout();
		}
	}
	else
	{
		CookieLib.setCookie("_WebModelList_", arNewList.join(), 1);
	}
}

ModelCore.prototype._clearParentConnectionInfo = function ()
{
	var parentWindow = window.top.opener;
	if (null != parentWindow)
	{
		parentWindow.g_objPQConnectionModel._setChildModelRegisterNumber("");
		parentWindow.g_objPQConnectionModel._setChildModelUseDmt(false);
	}
}

/**
 * 솔루션에 로그인했는가?
 */
ModelCore.prototype.isSolutionLoggedin = function ()
{
	if (IsDotNet())
	{
		var bResult = false;
		var heWebBosClient = document.getElementById("__PQClient_DotNet");
		if (null != heWebBosClient)
		{
			bResult = heWebBosClient.IsLogin;
		}
		
		return bResult;
	}
	else
	{
		return PQService.isSolutionLoggedin();
	}
}

////////////////////////////////////////////////////////////
// private 메서드 

/**
 * 이 모델이 임베딩된 모델일 경우 이 모델을 감싸고 있는 모델을 가져온다.
 */
ModelCore.prototype._getOuterModel = function ()
{
	if (GlobalField.isEmbededModel())
	{
		return window.parent;
	}
}

/**
 * 현재  모델의 주소를 어딘가에 설정한다.
 * 임베딩된 모델의 경우에는 감싸고 있는 프로그램 모델 아톰에 설정한다.
 * 임베딩되지 않은 모델은 자기 자신에게 설정한다.
 */
ModelCore.prototype._setMyAddress = function ()
{
	if (GlobalField.isEmbededModel())
	{
		var strAddress = "";
		var strLocationHref = decodeURI(window.location.href);
		
		var strProjectName = "/" + GetProjectName() + "/";
		var nIndex = strLocationHref.indexOf(strProjectName);
		if (0 < nIndex)
		{
			strAddress = strLocationHref.substring(nIndex + strProjectName.length);
		}
		
		var strWebModelAtomVarName = GlobalField.getWebModelAtomName();
		var objOuterWindow = this._getOuterModel();		
		objOuterWindow.WebModelAtom.updateAddress(strWebModelAtomVarName, strAddress);
	}
	else
	{
		ModelCore.updateAddress();
	}
}

ModelCore.prototype._initWindowSize = function (strModelName)
{
	// 웹페이지 모델이 아니면
	if (!IsWebModel())
	{
		if (!GlobalField.isEmbededModel())
		{
			// 크기 변경
			window.parent.resizeTo(GetWindowWidth(), GetWindowHeight());
			
			// ie 의 보안수준이 높아져서 주소표시줄/상태표시줄이 기본으로 표시된다.
			// 그만큼 윈도우의 높이를 늘려줘야 하는데, ie 는 전체 윈도우의 크기를 알 수 있는 프로퍼티가 제공되지 않는다.
			// * 윈도우 높이를 늘리기 위해 사용한 방법
			//  - 임의의 엘리먼트(div)를 생성하여 뷰의 제일 아래 위치시킨다. (주소표시줄/상태표시줄이 존재하면 엘리먼트의 전체가 보이지 않을 것이다.)
			//  - 엘리먼트(div)에 .focus() 시키면 엘리먼트 전체가 보이는 위치까지 스크롤 된다.
			//  - 스크롤된 높이만큼 윈도우 높이를 늘려준다.
			//  - 스크롤을 초기화한다.
			//  - 생성한 엘리먼트(div) dom 에서 제거 (더이상 필요없음.)
			var heDiv = document.createElement("div");
			document.body.appendChild(heDiv);
			heDiv.style.position = "absolute";
			heDiv.style.width = 100;
			
			var nWindowHeight = GetWindowHeight();
			var nScreenHeight = window.screen.height;
			if (IsNtoaModel())
			{
				if (nWindowHeight > nScreenHeight)
				{
					nWindowHeight = nScreenHeight;
					document.getElementById("__NTOAMODEL_PAGE_LAYOUT").style.height = document.body.offsetHeight + "px";
				}
				heDiv.style.top = nWindowHeight - heDiv.offsetHeight - 36; // 36: 윈도우에서 뷰를 제외한 높이
			}
			else if (null == parent.frameElement)
			{
				heDiv.style.top = nWindowHeight - heDiv.offsetHeight;
			}
			else
			{
				heDiv.style.top = nWindowHeight - heDiv.offsetHeight - 36; // 36: 윈도우에서 뷰를 제외한 높이
			}
			
			heDiv.focus();
			window.parent.resizeTo(GetWindowWidth(), nWindowHeight + document.body.scrollTop);
			scrollTo(0, 0);
			document.body.removeChild(heDiv);
		}
		else
		{
			// 임베디드 모델인 경우, WebModelAtom 에서 처리함
			window.parent.parent.WebModelAtom.initSize(GlobalField.getWebModelAtomName(), GetWindowWidth(), GetWindowHeight());
		}
	}
}

/**
 * WebBos 설정과 업그레이드 사항 체크
 */
ModelCore.prototype._bosCheck = function ()
{
	var heBosChecker = document.getElementById("__BOS_CHECKER__");
 	var heWebBosClient = document.getElementById("__PQClient_DotNet");
 
 	if (null == heBosChecker)
 	{
  		alert("boschecker가 설치되지 않았습니다.");
 	}
	else if (0==heBosChecker.CheckBosEnv() || true != heWebBosClient.IsCreated)
	{
		heBosChecker.RegTrustedSite (document.URL); //신뢰할수 있는 사이트
		if (false == heBosChecker.SetBosEnv())
			history.back();
		else
			window.close();
		return;
	}
}

ModelCore.prototype._initGlobalTool = function ()
{
	MakeRequest.init();
	HandleResult.init();
	
	PQService.init();
	
	// 현재 모델이 웹 포탈이면
	if (IsWebModel())
	{
		// PQPortalService를 만든다.
		PQPortalService.init();
		
		// Query정보를 만든다.
		MakePQQuery();
	}
	
	PQOperation.init();
	
	PQConnectionInput.init();
	PQConnectionSearch.init();
	PQConnectionModel.init();
	
	PQScript.init();
	
	// 진행관리자 전처리 정보를 만든다.
	MakeProcessManagerBeforeActionInfoTable();
	
	// 진행관리자 후처리 정보를 만든다.
	MakeProcessManagerAfterActionInfoTable();
	
	// 팝업차단 정보 읽음
	GlobalField.initPopupBlockInfo();
}

ModelCore.prototype._initModel = function ()
{
	if (IsNtoaModel())
	{
		g_objModel = new NtoaModel();
	}
	else
	{
		g_objModel = new Model();
	}
	
	g_objModel.initModel();
}

ModelCore.prototype._checkEmbededModel = function ()
{
	var strLocationHref = ""
	if (IsWebModel())
	{
		strLocationHref = decodeURI(window.location.href);
	}
	else
	{
		strLocationHref = decodeURI(window.parent.location.href);
	}
	
	var nQueIndex = strLocationHref.indexOf("?");
	if (0 < nQueIndex)
	{
		var arTemp = strLocationHref.substring(nQueIndex + 1);
		var arQueryList = arTemp.split("&");
		for (var i = 0, nLen = arQueryList.length; i != nLen; i += 1)
		{
			var strQuery = arQueryList[i];
			
			// 현재 모델을 감싸고 있는 웹모델 아톰의 이름.
			if (0 <= strQuery.indexOf("E="))
			{
				var arUnits = strQuery.split("=");
				GlobalField.setWebModelAtomName(arUnits[1]);
				break;
			}
		}
	}
}

ModelCore.prototype._initAtom = function ()
{
	this._makeAtomList();
	this.initAtomList();
	
	g_objModel.initAtom();
	
	MakeTabOrderList();
}

/**
 * 일반모델, 문서모델에 쓰일 수 있는 아톰들의 리스트를 만든다.
 */
ModelCore.prototype._makeAtomList = function ()
{
	// 스크롤 아톰 먼저 리스트를 만들고
	// 스크롤에 묶이는 아톰들에 대한 리스트를 만듭니다.
	MakeScrollAtomList();	
	if (IsWebModel())
	{
		MakeWebDisplayAtomList();
		MakeWebRssAtomList();
		MakeWebScrollPageAtomList();
	}
	
	MakeInputDataAtomList();
	MakeInputTimeAtomList();
	MakeComboAtomList();
	MakeCheckAtomList();
	MakeRadioAtomList();
	MakeInputImageAtomList();
	MakeButtonAtomList();
	MakeGroupBoxAtomList();
	MakeStraightLineAtomList();
	MakeFreeLineAtomList();
	MakeRectangleAtomList();
	MakeItemNameAtomList();
	MakeDecorImageAtomList();
	
	// NTOA
	MakeAttachAtomList();
	MakeDHtmlAtomList();
	MakeGanttChartAtomList();
	MakeReceiverAtomList();
	MakeTransmitAtomList();
	MakeUrlAtomList();
	MakeMoveAtomList();		// 파일문서일 경우, 문서삽입객체는 ntoamodel이 아닌것으로 간주된다.
	
	// WebPage
	if (IsWebModel())
	{
		MakeWebLoginAtomList();
		MakeWebFlashAtomList();
		MakeWebIFrameAtomList();
		MakeWebBoardAtomList();
		MakeWebHyperLinkAtomList();
		MakeWebHyperDataAtomList();
		MakeWebModelAtomList();
		MakeWebDHtmlEditAtomList();
		MakeWebHtmlTagAtomList();
		MakeWebFileAttachAtomList();
		MakeWebPictureAtomList();
		MakeWebQuickLinkAtomList();
		MakeWebSlidePanelAtomList();
		MakeWebTableAtomList();
		MakeWebTabPanelAtomList();
		MakeWebSchedulerAtomList();
		MakeWebTableTagAtomList();
		MakeWebHtmlModelAtomList();
		MakeWebTreeMenuAtomList();
		MakeWebTabMenuAtomList();
		MakeWebSlideMenuAtomList();
		MakeWebLinkMenuAtomList();
		MakeWebLabelMenuAtomList();
		MakeWebDropMenuAtomList();
		MakeWebComboMenuAtomList();
	}
}

/**
 *	QPG뿐만 아니라 QFR, QWP 등 다른모델에서도 쓰이는 아톰을 초기화한다.
 *	QPG 모델에서만 쓰이는 아톰은 PQCore.js의 _initAtomList()에 추가 
 */
ModelCore.prototype.initAtomList = function ()
{
	if (ContainsScrollAtom())
	{
		ScrollAtom.init();
	}
	if (ContainsInputDataAtom())
	{
		InputDataAtom.init();
	}
	if (ContainsFreeLineAtom())
	{
		FreeLineAtom.init();
	}
	if (ContainsInputTimeAtom())
	{
		InputTimeAtom.init();
	}
	if (ContainsInputImageAtom())
	{
		InputImageAtom.init();
	}	
	if (ContainsCheckAtom())
	{
		CheckAtom.init();
	}
	if (ContainsComboAtom())
	{
		ComboAtom.init();
	}
	if (ContainsRadioAtom())
	{
		RadioAtomGroup.init();
	}
	if (ContainsButtonAtom())
	{
		ButtonAtom.init();
	}
	if (ContainsGroupBoxAtom())
	{
		GroupBoxAtom.init();
	}
	
	/**
	 *	NTOA 아톰
	 */
	if (ContainsAttachAtom())
	{
		AttachAtom.init();
	}
	if (ContainsDHtmlAtom())
	{
		DHtmlAtom.init();
	}
	if (ContainsGanttChartAtom())
	{
		GanttChartAtom.init();
	}
	if (ContainsReceiverAtom())
	{
		ReceiverAtom.init();
	}
	if (ContainsMoveAtom())
	{
		MoveAtom.init();
	}
	
	if (IsWebModel())
	{
		/**
		 * 웹페이지 아톰
		 */
		if (ContainsWebTreeMenuAtom())
		{
			WebTreeMenuAtom.init();
		}
		if (ContainsWebComboMenuAtom())
		{
			WebComboMenuAtom.init();
		}
		if (ContainsWebDropMenuAtom())
		{
			WebDropMenuAtom.init();	
		}
		if (ContainsWebLabelMenuAtom())
		{
			WebLabelMenuAtom.init();
		}
		if (ContainsWebLinkMenuAtom())
		{
			WebLinkMenuAtom.init();
		}
		if (ContainsWebTabMenuAtom())
		{
			WebTabMenuAtom.init();
		}
		if (ContainsWebFlashAtom())
		{
			WebFlashAtom.init();
		}
		if (ContainsWebIFrameAtom())
		{
			WebIFrameAtom.init();
		}
		if (ContainsWebHyperLinkAtom())
		{
			WebHyperLinkAtom.init();
		}
		if (ContainsWebHyperDataAtom())
		{
			WebHyperDataAtom.init();
		}
		if (ContainsWebBoardAtom())
		{
			WebBoardAtom.init();
		}
		if (ContainsWebLoginAtom())
		{
			WebLoginAtom.init();
		}
		if (ContainsWebSlideMenuAtom())
		{
			WebSlideMenuAtom.init();
		}
		if (ContainsWebDHtmlEditAtom())
		{
			WebDHtmlEditAtom.init();
		}
		if (ContainsWebHtmlTagAtom())
		{
			WebHtmlTagAtom.init();
		}
		if (ContainsWebFileAttachAtom())
		{
			WebFileAttachAtom.init();
		}
		if (ContainsWebPictureAtom())
		{
			WebPictureAtom.init();
		}
		if (ContainsWebQuickLinkAtom())
		{
			WebQuickLinkAtom.init();
		}
		if (ContainsWebRssAtom())
		{
			WebRssAtom.init();
		}
		if (ContainsWebSlidePanelAtom())
		{
			WebSlidePanelAtom.init();
		}
		if (ContainsWebTableAtom())
		{
			WebTableAtom.init();
		}
		if (ContainsWebSchedulerAtom())
		{
			WebSchedulerAtom.init();
		}
		if (ContainsWebTabPanelAtom())
		{
			//웹탭뷰의 초기화는 모든 아톰 중에서 가장 나중에 해야 한다.
			//'탭활성화시 DBIO' 등 기능때문에 게시판 아톰 등에 설정을 해줘야 하기 때문이다.
			WebTabPanelAtom.init();
		}
	}
}

ModelCore.prototype._loadData = function ()
{
	g_objModel.loadData();
}

ModelCore.prototype._closeModel = function ()
{
	var strModelPath = GetModelSubPath() + GetModelName();
	PQService.closeModel(strModelPath, false);
}

/**
 * 아톰 리스트의 초기화가 끝나고 전체적으로 연산식을 수행한다.
 */
ModelCore.prototype._executeOperation = function ()
{
	if (ContainsInputDataAtom())
	{
		InputDataAtom.executeOperation();
	}
	
	if (ContainsInputTimeAtom())
	{
		InputTimeAtom.executeOperation();
	}
}

var g_objDoc = null;
var g_bModelCoreReady = false;

/**
* 폼 열림 이벤트 
*/
ModelCore.onLoad = function (strModelName)
{
	g_objModelCore = new ModelCore();
	
	// 웹모델이면 조회 동작은 서버에서 하지 않도록 변경함
	if (IsWebModel() && g_bQWPClientMode)
	{
		g_objDoc = new LightJDoc();
		g_objDoc.onLoad(strModelName);
	}
	else
	{
		g_objModelCore.onLoad(strModelName);
	}
	g_bModelCoreReady = true;
}

/**
* 동작이 없는 폼의 열림 이벤트 
*/
ModelCore.onLoadForNoAction = function (strModelName)
{
	g_objModelCore = new ModelCore();
	
	g_objModelCore.onLoadForNoAction(strModelName);
}

/**
 * 폼_닫힘 이벤트
 */
ModelCore.onUnload = function () 
{
	g_objModelCore.onUnload();
	
	if (IsWebModel())
	{
		if (0 < g_strPQWebURL.length)
		{
			var strPath = "/ups/" + GetProjectName() + "/" + Utils.replace(Utils.getModelName(g_strPQWebURL), ".QWP", ".html");
			CookieLib.setCookie("_PQWebURL_", strPath, 1);
		}
		
		//g_objDoc.onUnload();
	}
}

/**
 * 모델이 닫히기 전에 발생하는 이벤트를 처리한다.
 */
ModelCore.onBeforeUnload = function (objEvent)
{
	g_objModelCore.onBeforeUnload(objEvent);	
}

ModelCore.onScroll = function (objEvent)
{
	if (ContainsComboAtom())
	{
		ComboAtom.hideAllOptionList();		
	}
}
////////////////////////////////////////////////////////////////
//

ModelCore.getParentWindow = function ()
{
	var objParent = window.top.opener;
	
	if (null == objParent)
	{
		// 모델삽입안에 qpg 들어간 경우
		objParent = window.parent.parent;
	}
	
	if (null != objParent)
	{
		try
		{
			var arChildWindow = objParent.GlobalField.getChildWindows();
			var nLen = arChildWindow.length;
			if (0 < nLen)
			{
				for (var i = 0; i < arChildWindow.length; i=i+1)
				{
					// 이미 닫힌 자식폼이 있을 수 있으므로 예외처리 적용.
					if (arChildWindow[i] == window.top)
					{
						return objParent;
					}
				}
			}
			else
			{
				return objParent;
			}
		}
		catch(e)
		{
		}
	}
	return null;
}

/**
 * 솔루션에 로그인 한 상태인가?
 */
ModelCore.isSolutionLoggedin = function ()
{
	if (null != g_objModelCore)
	{
		return g_objModelCore.isSolutionLoggedin();
	}
	
	return false;	
}

/**
 * '웹페이지주소'는 현재 모델의 주소입니다. 모델명과 참조아톰값으로 구성됩니다.
 * 이 값은 '웹페이지주소'라는 아톰변수명을 가진 사각형 아톰에 설정됩니다. 어떤 페이지에서 지금 페이지로 돌아고자할 때 쓰입니다.
 *
 * 예) "/sub/index.html?C=입력란1:가나다,입력란2:123&C=모델삽입아톰변수명:inner.QWP&P=모델삽입아톰변수명$입력란3:abc"
 * "/sub/index.html?C=입력란1:가나다,입력란2:123"은  현재 모델의 주소와 참조아톰으로 넘어온 값입니다.
 * "C=모델삽입아톰변수명:inner.QWP"는 '모델삽입아톰변수명'이라는 모델삽입 아톰의 값입니다.
 * "P=모델삽입아톰변수명$입력란3:abc"는 'inner.QWP'로 넘어갈 참조아톰값입니다.
 */
ModelCore.updateAddress = function ()
{
	//참조아톰 값.
	var strAtomParameter = "";
	var objAtom = null;
	var htAtomVarNames = GlobalField.getRefAtomVarName();
	for (var strAtomVarName in htAtomVarNames)
	{
		var strAtomType = htAtomVarNames[strAtomVarName];
		objAtom = Model.getAtom(strAtomVarName);
		if (null != objAtom)
		{
			strAtomParameter = strAtomParameter + strAtomVarName + ":" + objAtom.getValue() + ",";
		}
	}
	
	if (0 < strAtomParameter.length)
	{
		strAtomParameter = "&C=" + strAtomParameter;
	}
	
	// 폼생성조건.
	var strModelCreateCondition = GetModelCreateCondition();
	if (0 < strModelCreateCondition.length)
	{
		strModelCreateCondition = "&D=" + strModelCreateCondition;
	}
	
	//웹모델 아톰의 참조아톰값.
	var strWebModelParameter = "";
	if (ContainsWebModelAtom())
	{
		strWebModelParameter = "&" + WebModelAtom.getParameters();
	}
	
	var strModelPath = GetModelSubPath() + GetModelName() + "?";
	var strAddress = strModelPath + strAtomParameter + strModelCreateCondition + strWebModelParameter;
	
	if (ContainsRectangleAtom())
	{
		var objAtom = RectangleAtom.getAtom("웹페이지주소");
		if (null != objAtom)
		{
			objAtom.setValue(strAddress);
		}
	}
	
	g_strPQWebURL = strAddress;
		
	return strAddress;
}

/**
 * 일반 모델(QPG)을 열 수 있는가?
 * 일반 모델은 솔루션 로그인을 해야 열 수 있다.
 */
ModelCore.canOpenModel = function (strModelPath)
{
	if (0 < strModelPath.indexOf(".QPG") || 0 < strModelPath.indexOf(".QRP"))
	{
		if (!ModelCore.isSolutionLoggedin())
		{
			alert("이 기능을 이용하려면 솔루션 로그인이 필요합니다.");				
			return false;
		}
	}
	
	return true;
}

/**
 * 바디에서 리사이즈가 끝나는 직후 발생한다.
 */
ModelCore.onResize = function (event)
{
	// 다이어리 아톰이 있다면 리사이즈 한다.
	if (ContainsWebSchedulerAtom())
	{
		WebSchedulerAtom.resize(event);
	}

	if (g_bTrialVersion)
	{
		this._changePosition();
	}
	
	if (IsNtoaModel())
	{
		NtoaPageManager.resizeWindow();
	}
}

/**
 * 포털 로그인 사용자 정보를 가져옵니다.
 */
ModelCore.getPortalUserData = function ()
{
	if (IsWebModel())
	{
		if (GlobalField.isEmbededModel())
		{
			var objParentUserData = window.parent.g_htPortalUserData;
			
			if (null != objParentUserData)
			{
				// 사용자가 로그인을 한경우, 부모창의 사용자정보를 가져와서 사용한다.
				GlobalField.setPortalUserData(
						objParentUserData["DP_SCODE"], objParentUserData["USER_ID"], objParentUserData["USER_NAME"],
						objParentUserData["PS_CODE"], objParentUserData["JOB_LEVEL"], objParentUserData["DocLevel"], 
						objParentUserData["PS_NAME"], objParentUserData["AdditionalJob"], objParentUserData["UPSType"]);
			}
			
			g_htDBNameModuleKey = window.parent.g_htDBNameModuleKey;
			g_arDBNameOwner = window.parent.g_arDBNameOwner;
			g_arDBName = window.parent.g_arDBName;
			g_nDBKind = window.parent.g_nDBKind
		}
		else
		{
			var strResult = PQAjax.post("/ups/PortalGlobalInfoService.do?pn=" + GetProjectName() + "&clk=" + GetCommonLoginKey() + "&type=UserData", "");
			if (null != strResult && 0 < strResult.length)
			{
				var xnResult = XmlLib.loadXMLFromString(strResult);
				
				var xnDepCode = XmlLib.selectSingleNode(xnResult, "//DepCode");
				if (null != xnDepCode)
				{
					GlobalField.setPortalUserData(
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//DepCode")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//UserID")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//UserName")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//GroupCode")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//JobLevel")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//DocLevel")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//GroupName")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//AdditionalJob")),
						XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//UPSType")));
				}
				
				// 솔루션 로그인 여부 설정함
				var strSolutionLogin = XmlLib.getTextValue(XmlLib.selectSingleNode(xnResult, "//SolutionLogin"));
				if ("true" == strSolutionLogin && g_nSolutionLoginState == SOLUTION_NOT_LOGIN)
				{ 
					g_nSolutionLoginState = SOLUTION_LOGIN_NOGLOBAL;
				}
				
				var xnDBKind = XmlLib.selectSingleNode(xnResult, "//DBKind");
				if (null != xnDBKind)
				{
					var strDBKind = XmlLib.getTextValue(xnDBKind);
					g_nDBKind = parseInt(strDBKind);
				}
				
				// 클라이언트에서 쿼리구성을 하기 위해서, 필요한 정보를 가져온다.
				var xnInfos = XmlLib.selectSingleNode(xnResult, "//ModuleKeyInfo");
				if (null != xnInfos && g_bQWPClientMode)
				{
					var nSize = xnInfos.childNodes.length;
					for (var i = 0; i < nSize; i+=1)
					{
						var xnKeyInfo = xnInfos.childNodes[i];
						var strKey = xnKeyInfo.nodeName;
						var strName = XmlLib.getTextValue(xnKeyInfo);
						var strOwner = XmlLib.getAttribute(xnKeyInfo, "owner");
						
						g_htDBNameModuleKey[strKey] = strName;
						g_arDBName.push(strName);
						
						if (1 == g_nDBKind)
						{
							// oracle
							g_arDBNameOwner.push(strOwner);
						}
						else
						{
							g_arDBNameOwner.push(strName + "." + strOwner);
						}
					}
				}
			}
		}
	}
}

/**
 * 포털 로그인 사용자 정보를 제거합니다.
 */
ModelCore.removePortalUserData = function ()
{
	GlobalField.removePortalUserData();
}

/**
 * 사용자의 특정 제품영역의 직무등급을 가져옵니다.
 * @param strKey 제품영역 키. [A-T]
 * @param strDealLevel 로그인 사용자의 직무등급.
 * @return 모델에 제품영역키가 없으면 1등급. 있으면 사용자의 해당 제품영역의 직무등급. 
 * 			단 해당 직무등급이 설정되어있지않은 경우 8등급.
 */
ModelCore.getJobLevel = function (strKey, strDealLevel)
{
	//웹페이지모델일 경우 로그인을 안 했으면 7등급.
	//웹페이지모델은 특성상 로그인을 안한 경우에도 동작해야하는 경우가 있기 때문.
	if (IsWebModel() && !GlobalField.isPortalLoggedin())
	{
		return 7;
	}
	
	if (null == strKey || 0 == strKey.length)
	{
		return 1;
	}
	
	var nJobLevel = 8;
	var nPos = strDealLevel.indexOf(strKey);
	if (-1 < nPos && nPos + 1 < strDealLevel.length)
	{
		nJobLevel = parseInt(strDealLevel.charAt(nPos + 1));
	}
	
	return 0 == nJobLevel ? 8 : nJobLevel;
}

/*
 * 시연용일 때 모델을 정렬시킵니다. (가운데)
 */
ModelCore.prototype._alignModel = function ()
{
	var heBody = document.getElementById("__BODY_");
	var heModelArea = document.getElementById("ModelArea");
	
	if (null != heBody && null != heModelArea)
	{
		var objOuterWindow = window.parent;
		var strLocationHref = strLocationHref = decodeURI(window.location.href);
		if (null != objOuterWindow && 0 < strLocationHref.indexOf("?"))
		{
			heModelArea.style.width = GetWindowWidth();
			heModelArea.style.height = GetWindowHeight()
		}
		else
		{
			heModelArea.style.width = GetWindowWidth();
			heModelArea.style.height = GetWindowHeight() + 22; // Wonderful Soft, Applipedia 링크 위치만큼
		}
		
		var nBodyWidth = heBody.offsetWidth;
		var nBodyHeight = heBody.offsetHeight;
		
		var nModelWidth = Utils.removePx(heModelArea.style.width);
		var nModelHeight = Utils.removePx(heModelArea.style.height);
		
		var nMarginLeft = Math.floor((nBodyWidth - nModelWidth - 4) / 2);
		var nMarginTop = Math.floor((nBodyHeight - nModelHeight)/2);
		
		if (nMarginLeft < 0)
		{
			nMarginLeft = 0;
		}
		
		if (nMarginTop < 0)
		{
			nMarginTop = 0;
		}
		heModelArea.style.marginLeft = nMarginLeft + "px";
		heModelArea.style.marginTop = nMarginTop + "px";
		heModelArea.style.overflow = "hidden";
	}
}

ModelCore.prototype._initWindowSizeForTrial = function ()
{
	var objOuterWindow = window.parent;
	var strLocationHref = strLocationHref = decodeURI(window.location.href);
	if (null != objOuterWindow && 0 < strLocationHref.indexOf("?"))
	{
		if (null != objOuterWindow.WebHtmlModelAtom && null != objOuterWindow.WebHtmlModelAtom.initSize)
		{
			var arTemp = strLocationHref.split("?");
			var nWidth = GetWindowWidth();
			var nHeight = GetWindowHeight() + 25; // 25는 여백
			objOuterWindow.WebHtmlModelAtom.initSize(arTemp[1], nWidth, nHeight);
		}
	}
}

/*
 * 익스플로어 크기가 변경될 때 모델도 변경된 만큼 위치가 이동하도록 합니다.
 */
ModelCore._changePosition = function ()
{
	var heBody = document.getElementById("__BODY_");
	var heModelArea = document.getElementById("ModelArea");
	
	if (null != heBody && null != heModelArea)
	{
		var nWidth = heBody.offsetWidth;
		var nHeight = heBody.offsetHeight;
		
		var nModelWidth = heModelArea.style.width;
		var nModelHeight = heModelArea.style.height;
		nModelWidth = Utils.removePx(nModelWidth.toString());
		nModelHeight = Utils.removePx(nModelHeight.toString());
		
		if (!isNaN(nModelWidth) && !isNaN(nModelHeight))
		{
			if ((nWidth - nModelWidth < 0) && (nHeight - nModelHeight < 0))
			{
				heModelArea.style.marginLeft = "0px";
				heModelArea.style.marginTop = "0px";
				return ;
			}
			
			if (nWidth - nModelWidth < 0)
			{
				heModelArea.style.marginLeft = "0px";
				heModelArea.style.marginTop = ((nHeight- nModelHeight))/2 + "px";
			}
			else if (nHeight - nModelHeight < 0)
			{
				heModelArea.style.marginLeft = ((nWidth - nModelWidth))/2 - 10 + "px";
				heModelArea.style.marginTop = "0px";
			}
			else
			{
				heModelArea.style.marginTop = ((nHeight- nModelHeight))/2 + "px";
				heModelArea.style.marginLeft = ((nWidth - nModelWidth))/2 - 10 + "px";
			}
		}
	}
}

/**
 * Model.js
 * 일반문서 클래스
 */
function Model ()
{
}

Model.prototype.initModel = function ()
{
	g_htModelInfo = new Hashtable();
	
	GlobalField.setModelName(GetModelName());
	GlobalField.setModelSubPath(GetModelSubPath());
	GlobalField.setModelCreateCondition(GetModelCreateCondition());
	GlobalField.setModelFieldName(GetModelFieldName());
	GlobalField.setUseTopDmt(IsUseTopDmt());
	GlobalField.initGarbageBin();
}

Model.prototype.initAtom = function ()
{
	this._makeAtomList();
	this._initAtomList();
}

Model.prototype.loadData = function ()
{
	GlobalField.setServiceName("ModelAction");
	
	// 부모창에서 넘긴 데이터를 전역정보에 저장
	this._initParentData();
	
	var xnRequest = MakeRequest.createRequestNode();
	MakeRequest.makeServiceRequest(xnRequest);

	try
	{
		MakeRequest.makeLoadDataRequest(xnRequest);
	}
	catch (e)
	{
		HandleException(e);
		return;
	}
	
	var xnResultDoc = PQService.executeService(xnRequest.ownerDocument);
	
	HandleResult.execute(xnResultDoc);
}

/**
 * 일반모델에 쓰일 수 있는 아톰들의 리스트를 만든다.
 */
Model.prototype._makeAtomList = function ()
{
	MakeReportBrowseAtomList();
	MakeChartAtomList();
	MakeGridExAtomList();
	MakeTreeAtomList();
	
	// 수행조건 팝업을 수행조건 아톰에서 따로 리스트로 관리 하게된 관계로,
	// 팝업 아톰리스트를 만드는 루틴은 반드시 수행조건 아톰이 만들어 진 뒤로 해서 합니다.
	MakeSearchConditionAtomList();
	MakePopupAtomList();
	
	MakeTabViewAtomList();
	MakeDocumentManagerAtomList();
	MakeOcxAtomList();
	MakeProgressAtomList();
	MakeScheduleAtomList();
}

/**
 *	QPG 모델에서만 쓰이는 아톰만 초기화한다.
 *	QFR, QWP 등 다른모델에서도 쓰이는 아톰은 ModelCore.js의 initAtomList()에 추가  
 */
Model.prototype._initAtomList = function ()
{
	if (ContainsReportBrowseAtom())
	{
		ReportBrowseAtom.init();
	}
	if (ContainsChartAtom())
	{
		ChartAtom.init();
	}
	if (ContainsTreeAtom())
	{
		TreeAtom.init();
	}
	if (ContainsSearchConditionAtom())
	{
		SearchConditionAtom.init();
	}
	if (ContainsPopupAtom())
	{
		PopupAtom.init();
	}
	if (ContainsDocumentManagerAtom())
	{
		DocumentManagerAtom.init();
	}
	if (ContainsGridExAtom())
	{
		GridExAtom.init();
	}
	if (ContainsOcxAtom())
	{
		OcxAtom.init();
	}
	if (ContainsProgressAtom())
	{
		ProgressAtom.init();
	}
}	

/**
 * 부모폼에서 넘겨주는 참조 아톰의 값을 세팅한다.
 */	
Model.prototype._initParentData = function ()
{
	// 웹모델일 경우 자신의 URL에서 파라미터를 구성한다.
	if (IsWebModel())
	{
		this._initPortalParentData();
	}
	else
	{
		var objParent = ModelCore.getParentWindow();
		
		if (objParent && objParent.GlobalField)
		{
			Model.setReceivedData(objParent.GlobalField.getConnectionModelInfo(), true);
		}
	}
}

/**
 * 웹 포탈 모델의 부모폼에서 넘겨주는 참조 아톰의 값을 세팅한다.
 */
Model.prototype._initPortalParentData = function ()
{
	var strLocationHref = decodeURI(window.location.href);
	
	var nQueIndex = strLocationHref.indexOf("?");
	if (0 < nQueIndex)
	{
		var arTemp = strLocationHref.substring(nQueIndex + 1);
		var arQueryList = arTemp.split("&");
		
		for (var i = 0; i < arQueryList.length; i += 1)
		{
			var strQuery = arQueryList[i];
			
			// 참조아톰값이 있다면
			if (0 <= strQuery.indexOf("C="))
			{
				// 참조아톰값들을 분리한다.
				var arUnits = strQuery.split("=");
				var strParemters = arUnits[1];
				var arParams = strParemters.split(",");
				
				for (var j = 0; j < arParams.length; j += 1)
				{
					// @PATH:를 재거한다.
					arParams[j] = Utils.getPathString(arParams[j]);
					arParams[j] = Utils.removePQPath(arParams[j]);
					
					// 참조아톰값에서 변수와 값을 분리한다.
					var arParamUnit = arParams[j].split(":");
					if (1 < arParamUnit.length)
					{
						var strVarName = arParamUnit.shift();
						var strValue = arParamUnit.join(":");
						
						// 참조변수를 입력란 아톰에서 찾는다.
						var objAtom = Model.getAtom(strVarName);
						
						if (objAtom)
						{
							// 참조아톰의 '아톰명', '값'을 전역정보로 저장
							// ModelAction에서 요청정보에 추가됨
							GlobalField.setRefAtomInfo(strVarName, strValue);
							
							// 게시판
							if ("WebBoardAtom" == objAtom.getAtomType())
							{
								objAtom.setRefPage(Number(strValue))
							}
							else
							{
								// 게시판 외 아톰은 setValue
								objAtom.setValue(strValue);
							}
						}
						
						if (objAtom)
						{
							GlobalField.setRefAtomVarName(strVarName, objAtom.getAtomType());
						}
					}
				}
			}
			
			//생성조건.
			if (0 <= strQuery.indexOf("D="))
			{
				var arUnits = strQuery.split("=");
				GlobalField.setModelCreateCondition(arUnits[1]);
			}
			
			//프로그램모델 아톰의 파라미터.
			//P=프로그램모델명1$입력란:값,입력란1:값&P=프로그램모델명2$입력란3:값,입력란4:값
			if (0 <= strQuery.indexOf("P="))
			{
				var arUnits = strQuery.split("=");
				var strWebModelAtomParameter = arUnits[1];				
				arUnits = strWebModelAtomParameter.split("$");
				if (ContainsWebModelAtom())
				{
					objAtom = WebModelAtom.getAtom(arUnits[0]);
					if (null != objAtom)
					{
						objAtom.setParameter(arUnits[1]);
					}
				}
			}
		}
	}
}

/**
 * 변수명으로 아톰값을 찾아서 리턴한다.
 *	@param strVarName - 아톰변수명
 *	@return strVarName과 아톰변수명이 일치하는 아톰의 값
 */
Model.getAtomValue = function (strVarName)
{
	var objAtom = Model.getAtom(strVarName);
	if (null != objAtom && objAtom.getValue)
	{
		return objAtom.getValue();
	}
}

Model.switchAllVanish = function ()
{
	for (var strVarName in Model._atoms)
	{
		if ("function" == typeof(Model._atoms[strVarName].vanish))
		{
			Model._atoms[strVarName].vanish();
		}
	}
}

/**
 * 연결된 모델에서 받은 값을 해당 아톰에 넣어준다.
 * @param htReceivedData 받은 값. {변수명, {값, 필드명, 테이블명}} 
 * @param bExecuteOperation 연산식 수행 여부
 */ 
Model.setReceivedData = function (htReceivedData, bExecuteOpeation, bFromChild)
{
	if (null != htReceivedData)
	{
		// strKey = 참조변수명 또는 $테이블명.필드명
		// arInfo = (값, 필드명) 
		for (var strKey in htReceivedData)
		{
			var arInfo = htReceivedData[strKey];
			
			if (null == arInfo)
			{
				continue;
			}
			
			// 참조변수명으로 아톰을 찾고 
			var objAtom = Model.getAtom(strKey);
			
			// 참조변수의 필드명으로 아톰을 찾고
			if (null == objAtom)
			{
				objAtom = Model.getAtom(arInfo[1]);
			}
			
			// 상세폼의 테이블명, 필드명이 일치하는 입력란을 찾는다.
			if (null == objAtom && ContainsInputDataAtom())
			{
				objAtom = InputDataAtom.getAtomByDatabaseInfo(arInfo[2], arInfo[1]);
			}
			
			// 상세폼의 테이블명, 필드명이 일치하는 날짜입력란을 찾는다.
			if (null == objAtom && ContainsInputTimeAtom())
			{
				objAtom = InputTimeAtom.getAtomByDatabaseInfo(arInfo[2], arInfo[1]);
			}
			
			// 상세폼의 테이블명, 필드명이 일치하는 콤보아톰을 찾는다.
			if (null == objAtom && ContainsComboAtom())
			{
				ComboAtom.getAtomByDatabaseInfo(arInfo[2], arInfo[1]);
			}
			
			if (null != objAtom)
			{
				// 자식에게서 온 값이면 
				if (bFromChild)
				{
					objAtom.setValue(arInfo[0]);
				}
				// 부모에게서 온 값이면
				else
				{
					// 참조아톰의 '아톰명', '값'을 전역정보로 저장
					// ModelAction에서 요청정보에 추가됨
					GlobalField.setRefAtomInfo(strKey, arInfo[0]);
				}
			}
		}
	}
}

/**
 * 부모폼 값 전달 기능으로 자식폼에서 받은 값을 적절하게 넣어준다.
 * @param htReceivedData 자식폼에서 넘어온 값.
 */
Model.receiveDataFromChildForm = function (htReceivedData)
{
	Model.setReceivedData(htReceivedData, false, true);
}

/**
 * Bpm Workflow에서  생성된 폼인지 여부를 반환합니다.
 *
 * @return Bpm폼이면 true, 아니면 false
 */
Model.isBpmModel = function ()
{
	var objParentWindow = ModelCore.getParentWindow();
	var bBpmModel = false;
	if (null != objParentWindow && !objParentWindow.closed && null != objParentWindow.GlobalField)
	{
		var htBpmExecuteInfoList = objParentWindow.GlobalField.getBpmExcuteInfoList();
		if (null != htBpmExecuteInfoList)
		{
			var objBpmExecuteInfo = htBpmExecuteInfoList[GetModelName()];
			if (null != objBpmExecuteInfo)
			{
				bBpmModel = true;
			}	
		}		
	}
	return bBpmModel;
}

/**
 * Bpm 모델이 수행되었는지 판단한다.
 *
 * @return 수행 되었으면 true, 아니면 false
 */
Model.isBpmExecute = function()
{
	var objParentWindow = ModelCore.getParentWindow();
	var bExecute = false;
	
	var htBpmExecuteInfoList = objParentWindow.GlobalField.getBpmExcuteInfoList();
	var objBpmExecuteInfo = htBpmExecuteInfoList[GetModelName()];

	bExecute = objBpmExecuteInfo.getIsExecute();

	return bExecute;		
}

/**
 * 문서 첨부 아톰 저장동작을 수행한다
 */
Model.saveAttachAtom = function ()
{
	var xnUploadRequest = MakeRequest.createRequestNode();
		
	if (IsNtoaModel() || ContainsAttachAtom())
	{
		if (AttachAtom.makeUploadRequest(xnUploadRequest))
		{
			Model.uploadSubmit(xnUploadRequest.ownerDocument);
		}
	}
}

/**
 * 이미지입력란, 통합 문서 아톰 등 파일 업로드 계열의 아톰들을 업로드 한다.
 */
Model.uploadFile = function ()
{
	var xnUploadRequest = MakeRequest.createRequestNode();
	
	var bImageUpload = false;
	if (ContainsInputImageAtom())
	{
		bImageUpload = InputImageAtom.makeUploadRequest(xnUploadRequest);
	}
	
	var bDocumentUpload = false;
	if (ContainsDocumentManagerAtom())
	{
		bDocumentUpload = DocumentManagerAtom.makeUploadRequest(xnUploadRequest);
	}
		
	if (bImageUpload || bDocumentUpload)
	{
		Model.uploadSubmit(xnUploadRequest.ownerDocument);
	}
}

/**
 * 첨부 파일을 업로드한다.
 * 파일이 업로드되면 숨겨진 iframe(id = "__FILE_UPLOAD_TARGET")의 페이지가 변경이 된다.
 * submit() 다음에 오는 자바스크립트가 비동기로 실행되기 때문에 
 * 업로드가 완료되지 않았는데 저장완료 스크립트가 실행될 수 있으므로 업로드가 완료될 때까지 기다린다.
 * TODO 무한정 기다릴 수는 없으므로 최대 대기 시간 설정을 할 수 있어야 함.
 */
Model.uploadSubmit = function (xnUploadRequestDoc)
{
	var strRequest = XmlLib.serializeToString(xnUploadRequestDoc);
	document.getElementById("__FILE_UPLOAD_INFO").value = strRequest;
	document.getElementById("__FILE_UPLOAD_FORM").submit();
	
	//업로드 완료까지 대기한다.
	while (true)
	{
		if (null == document.getElementById("__FILE_UPLOAD_TARGET") ||
			"complete" == document.getElementById("__FILE_UPLOAD_TARGET").readyState)
		{
			break;
		}
		
		try
		{
			//통합문서관리아톰, 이미지입력란 등 일반모델의 파일 업로드 계열은 모델에 있는 애플릿을 이용한다.
			PQService.pause(1000);
		}
		catch (e)
		{
			return;
		}
	}
}

Model.executeRefresh = function ()
{
	GlobalField.setServiceName(ButtonAtom.INQUIRYACTION);
	GlobalField.setServiceEventName("Refresh");
	
	var xnRequest = MakeRequest.createRequestNode();		
	try
	{
		MakeRequest.makeServiceRequest(xnRequest);
		MakeRequest.makeInputAtomRequest(xnRequest);
		MakeRequest.makeDecoAtomRequest(xnRequest);
	}
	catch (e)
	{
		HandleException(e);
		return;
	}
	
	var xnRequestDoc = xnRequest.ownerDocument;
	if (null != xnRequestDoc)
	{
		var xnResultDoc = null;
		try
		{	
			xnResultDoc = PQService.executeService(xnRequestDoc);
		}
		catch (e)
		{
			HandleException(e);
		}
		
		if (null != xnResultDoc)
		{
			HandleResult.execute(xnResultDoc);				
		}
	}
}

/**
 * 메시지박스를 보여준다
 *
 * @param strMessage 메시지 내용
 */
Model.startWaitMessage = function ()
{
	var heMessage = document.getElementById("__PQ_WAIT_MESSAGE_");
	
	if (null == heMessage)
	{
		heMessage = Model.makeWaitMessage();
	}
	
	heMessage.style.backgroundImage = 'url(/ups/sys/image/pq/webatom/webboard/upload.gif)';
	heMessage.style.visibility = "visible";
}

/**
 * 메시지박스를 감춘다
 */
Model.stopWaitMessage = function ()
{
	var heWait = document.getElementById("__PQ_WAIT_MESSAGE_");
	
	if (null != heWait)
	{
		heWait.style.visibility = "hidden";
	}
}

/**
 * 메시지 박스를 생성한다
 * 메지시 영역 넓이 
 * 가로 : 300px;
 * 세로 : 200px;
 */
Model.makeWaitMessage = function ()
{
	var heMessage = document.createElement("table");
	
	var nLeft = GetWindowWidth() / 2 - 150;
	var nTop = GetWindowHeight() / 2 - 100;
	
	heMessage.id = "__PQ_WAIT_MESSAGE_";
	
	heMessage.style.position = "absolute";
	
	heMessage.style.top = nTop + "px";
	heMessage.style.left = nLeft + "px";
	
	heMessage.style.width = "400px";
	heMessage.style.height = "120px";
	
	heMessage.style.border = "solid 10px #F7F7F7";
	heMessage.style.backgroundColor = "#7D7D7D";
	
	heMessage.style.visibility = "hidden";
	
	heMessage.align = "center";
	
	heMessage.insertRow().insertCell();
	
	document.body.appendChild(heMessage);
	
	return heMessage;
}

/**
 * 모델을 인쇄합니다.
 */
Model.printModel = function ()
{
	window.print();
}

/**
 * 모델의 모든 아톰리스트를 저장하는 객체
 */
Model._atoms = new Object ();

Model._atomsByIndex = new Object ();

/**
 * 모델의 아톰리스트에 아톰 저장
 * @param strVarName - 아톰명
 * @param objAtom - 아톰의 자바스크립트 객체
 */
Model.putAtom = function (strVarName, objAtom)
{
	Model._atoms[strVarName] = objAtom;
	
	objAtom.putAtom();
	
	// 스크립트 엔진에서 아톰 객체를 찾기 위해서 저장함
	if (objAtom.getScriptIndex)
	{
		var nScriptIndex = objAtom.getScriptIndex();
		Model._atomsByIndex[nScriptIndex] = objAtom;
	}
}

/**
 * 모델의 아톰리스트에서 삭제
 * 주의 : 트리팝업에서 추가되었던 임시아톰을 삭제할때 사용됨.
 */
Model.removeTreePopupAtom = function (strVarName)
{
	var objAtom = Model._atoms[strVarName];
	
	if (objAtom && "TreeAtom" == objAtom.getAtomType())
	{
		delete TreeAtom._atoms[strVarName];
		delete Model._atoms[strVarName];
	}
}

/**
 * @param strVarName - 아톰명
 * @param strScrollName - 스크롤아톰명 (optional)
 * @param heAtom - (optional)
 * @param nScrollRowIndex - 스크롤 행수 (optional)
 * @return 아톰명에 해당되는 자바스크립트 객체
 */
Model.getAtom = function (strVarName, strScrollName, heAtom, nScrollRowIndex)
{
	var objAtom = Model._atoms[strVarName];
	
	if (!objAtom)
	{
		if (ContainsScrollAtom())
		{
			var objScrollAtom = ScrollAtom.getAtom(strScrollName);
			
			if (objScrollAtom)
			{
				var nRowIndex = objScrollAtom.getRowIndex(heAtom);
				if (nScrollRowIndex)
				{
					nRowIndex = nScrollRowIndex;
				}
				
				if (0 <= nRowIndex)
				{
					objAtom = objScrollAtom.getBindedAtom(strVarName, nRowIndex);
				}
				else
				{
					objAtom = objScrollAtom.getBindedAtom(strVarName, 0);
				}
			}
			else
			{
				objAtom = ScrollAtom.getAtomByBindedVarName(strVarName);
			}
		}
		else if (ContainsWebRssAtom())
		{
			objAtom = WebRssAtom.getBindedAtom(strScrollName, strVarName, heAtom);
		}
	}
	
	return objAtom;
}


/**
 * 클라이언트 서비스 요청을 처리하는 클래스
 * 애플릿에 서비스 요청을 하고, 서비스 처리 결과를 받아 처리한다.
 */
function PQService ()
{
}

/**
 * 솔루션에 로그인하면 애플릿에 설정합니다.
 * 쿠키에 있는 전역 정보가 있으면 설정합니다.
 */
PQService.prototype.setSolutionLoggedin = function ()
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		//개별문서일 경우 로그인을 하지 않기때문에 설정하지 않음
		if(0 != g_nSolutionLoginState)
		{
			objApplet.setSolutionLoggedin("", false);
		
			var nInitState = (g_nSolutionLoginState == SOLUTION_LOGIN_NOGLOBAL) ? 1 : 2;
		
			if (g_nSolutionLoginState == SOLUTION_LOGIN_GLOBAL)
			{
				var strCookie = CookieLib.getCookie("_GlobalInfo_");
				objApplet.setAllGlobalInfo(strCookie);
			}
		
			objApplet.initApplet(nInitState);
		
			var strAfterInfo = objApplet.getAllGlobalInfo();
			CookieLib.setCookie("_GlobalInfo_", strAfterInfo, 1);
		
			return true;
		}
	}
	else
	{
		throw new NotInstallClientProgram();
	}
	return false;
}

/**
 * 솔루션에 로그인했는가?
 */
PQService.prototype.isSolutionLoggedin = function ()
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.isSolutionLoggedin();
	}
	else
	{
		return g_nSolutionLoginState != SOLUTION_NOT_LOGIN;
	}
}

/**
 * 아톰 동작을 실행
 *
 * @param xnRequest 요청 XML
 * @return 응답 XML
 */	 
PQService.prototype.executeService = function (xnRequest)
{
	var xnResult = null;
	
	if (IsWebModel())
	{
		// 웹 페이지 모델인 경우 PQPortalService에서 서비스 한다.
		xnResult = PQPortalService.executeService(xnRequest);
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			xnResult = this._executeService(objApplet, xnRequest);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
	
	return xnResult;
}

/**
 * 스크립트 동작을 실행
 *
 * @param xnRequest 요청 XML
 * @return 응답 XML
 */	 
PQService.prototype.executeScriptService = function (xnRequest, bIncludePreProcess)
{
	var xnResult = null;
	
	if (IsWebModel())
	{
		// 웹 페이지 모델인 경우 PQPortalService에서 서비스 한다.
		xnResult = PQPortalService.executeScriptService(xnRequest, bIncludePreProcess);
	}
	else
	{
		var objModelApplet = this._getAppletObject();
		
		if (null != objModelApplet)
		{
			var strGlobalInfo = CookieLib.getCookie("_GlobalInfo_");
			objModelApplet.setAllGlobalInfo(strGlobalInfo);
			
			xnResult = this._executeScriptService(objModelApplet, xnRequest, bIncludePreProcess);
			
			strGlobalInfo = objModelApplet.getAllGlobalInfo();
			CookieLib.setCookie("_GlobalInfo_", strGlobalInfo, 1);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
	
	return xnResult;
}

/**
 * 프로그램 실행 관리자 후처리를 실행한다.
 *
 * @param xnRequest 요청 정보.
 * @param strPath 경로를 포함한 자식폼 이름.
 * @return 응답 정보.
 */	 
PQService.prototype.executeProcessManagerAfterAction = function (xnRequest, strPath)
{
	var xnResult = null;
	
	if (IsWebModel())
	{
	}
	else
	{
		var objModelApplet = this._getAppletObject();
	
		if (null != objModelApplet)
		{
			var strGlobalInfo = CookieLib.getCookie("_GlobalInfo_");
			objModelApplet.setAllGlobalInfo(strGlobalInfo);
			
			xnResult = this._executeProcessManagerAfterAction(objModelApplet, xnRequest, strPath);
			
			strGlobalInfo = objModelApplet.getAllGlobalInfo();
			CookieLib.setCookie("_GlobalInfo_", strGlobalInfo, 1);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
	
	return xnResult;
}

PQService.prototype.setScriptAttribute = function (strVarName, strAttributeName, strValue)
{
	if (IsWebModel())
	{
		//TODO
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			return objApplet.setScriptAttribute(strVarName, strAttributeName, strValue);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
}

PQService.prototype.scriptMakeRequest = function (strRequest)
{
	if (IsWebModel())
	{
		//TODO
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			return objApplet.scriptMakeRequest(strRequest);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
}

PQService.prototype.scriptHandleResult = function ()
{
	if (IsWebModel())
	{
		//TODO
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			return objApplet.scriptHandleResult();
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}	
}

/**
 * 스케줄러 서비스를 수행한다.
 *
 * 스케줄러 서비스는 로그인이 된 상태(Applet이 로딩된 상태)에서 수행할  수 있다.
 * 그러므로 WebModel여부를 따지지 않는다.
 */
PQService.prototype.executeSchedulerService = function (xnRequest)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return this._executeSchedulerService(objApplet, xnRequest);
	}
	else
	{
		throw new NotInstallClientProgram();
	}
}

/**
 * 팝업 유효성 검사 수행
 */
PQService.prototype.executeForeignKeyCheck = function (xnRequest)
{
	var xnResult = null;
	
	if (IsWebModel())
	{
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			xnResult = this._executeForeignKeyCheck(objApplet, xnRequest);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
	
	return xnResult;
}

PQService.prototype.getOperationInfo = function ()
{
	var xnResult = null;
	
	if (IsWebModel())
	{
		var strOpCount = document.body.OperationCount;
		
		// 실제 연산식 정보가 있을 경우에만 요청을 보내도록 수정함
		if (null != strOpCount && 0 < parseInt(strOpCount))
		{
			// 웹 페이지 모델인 경우 PQPortalService에서 서비스 한다.
			xnResult = PQPortalService.getOperationInfo();
		}
		else
		{
			// 연산식 정보가 없는 결과를 리턴한다.
			xnResult = XmlLib.createXML("Model");
			
			var xnOperations = XmlLib.createChild(xnResult.documentElement, "Operations");
			XmlLib.createChild(xnOperations, "OperationVarList");
			XmlLib.createChild(xnOperations, "OperationAtomList");
		}
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			var strResult = objApplet.getOperationInfo();
			xnResult = XmlLib.loadXMLFromString(strResult);
		}
		else
		{
			throw new NotInstallClientProgram();
		}
	}
	
	return xnResult;
}

/**
 * XSL 문서를 반환합니다.
 * 
 * @param nXSLIndex XSL 인덱스
 * @return XSL
 */
PQService.prototype.getXSL = function (strPath)
{
	var strResult = "";
	
	var strResult = PQAjax.get(strPath, "")
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	return xnResult;
}

/**
 * 모델을 닫고, 저장된 데이터를 지웁니다.
 * @param strModelName 모델 이름
 * @param bSolutionLogout 솔루션 로그아웃.
 */
PQService.prototype.closeModel = function (strModelName, bSolutionLogout)
{
	if (IsWebModel())
	{
		// 웹 페이지 모델인 경우 PQPortalService에서 서비스 한다.
		// xnResult = PQPortalService.executeCloseModel(strModelName);
		if (ContainsWebSchedulerAtom())
		{
			WebSchedulerAtom.unLoad();
		}
	}
	else
	{
		var objApplet = this._getAppletObject();
	
		if (null != objApplet)
		{
			objApplet.closeModel(strModelName, bSolutionLogout);
		}
	}
}

/**
 * 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)를 '새로운 서식 작성' 기능에 의해서 엽니다.
 */
PQService.prototype.openSmartPaper = function (bSmartPaperForm)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		if (objApplet.openSmartPaper(bSmartPaperForm))
		{
			//새 서식을 연다는것은 현재 페이지에서 벗어나려는게 확실
			window.onbeforeunload = null;
			window.parent.location.reload();
		}
	}
}

/**
 * 작성 중이던 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)를 로컬 디스크에 저장합니다.
 */
PQService.prototype.saveTempSPD = function ()
{
	GlobalField.setServiceName("NtoaTempSave");
	GlobalField.setServiceEventName("TempSaveAction");
	
	var xnRequest = MakeRequest.createRequestNode();	
	MakeRequest.makeServiceRequest(xnRequest);
	
	var xnNtoaRequest = XmlLib.createChild(xnRequest, "Ntoa");	
	g_objMasterInfomation.makeRequest(xnNtoaRequest);
	g_objProcessInfomation.makeRequest(xnNtoaRequest);
	
	MakeRequest.makeAtomRequest(xnRequest, false);	
	if (ContainsKwdAtom())
	{
		var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);		
		KwdAtom.makeRequest(xnAtomRequest, true);
	}
	
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		var strRequest = XmlLib.serializeToString(xnRequest.ownerDocument);
		objApplet.saveTempSPD(strRequest);
	}
}

PQService.prototype.saveSPFWithChangedPopup = function (strAtomVarName, strNewDataString)
{
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		objApplet.saveSPFWithChangedPopup(strAtomVarName, strNewDataString);
	}
}


PQService.prototype.printNtoaModel = function (xnRequestDoc)
{
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		var strRequest = XmlLib.serializeToString(xnRequestDoc);
		objApplet.printNtoaModel(strRequest);
	}
}

/**
 * 원더풀 오피스의 개별 문서의 결재 처리를 한다.
 * @param xnRequestDoc 문서 내용 xml
 */
PQService.prototype.sanctWPQModel = function (xnRequestDoc)
{
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		var strRequest = XmlLib.serializeToString(xnRequestDoc);
		var nCloseModel = objApplet.sanctWPQModel(strRequest);
		
		//결재를 했으면 현재 문서가 저장되었으므로 닫아도 됨.
		window.onbeforeunload = null;
		
		return (0 == nCloseModel) ? true : false;
	}
	return false;
}

/**
 * 원더풀 오피스의 개별 문서 사용자의 정보를 가져옵니다.
 * @return 이름\t소속\t직위\t이메일\t전화번호\t팩스\t주소\t
 * 기본메일서버사용여부\t사용자설정메일서버주소\t사용자설정메일계정\t사용자설정메일계정비밀번호\t
 * 소속기관상호\t소속기관대표자\t소속기관주소
 */
PQService.prototype.getWonderfulOfficeUserInformation = function ()
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.getWonderfulOfficeUserInformation();
	}
	
	return "";
}

/**
 * 원더풀 오피스의 개별 문서 사용자의 정보를 저장합니다.
 * @param strUserName 이름
 * @param strUserCompany 소속
 * @param strUserPosition 직위
 * @param strUserEmail 이메일
 * @param strUserPhone 전화번호
 * @param strUserFax 팩스
 * @param strUserAddress 주소
 * @param bUseDefaultEmailServer 기본 메일 서버 사용 여부
 * @param strEmailServerAddress 사용자 설정 메일 서버 주소
 * @param strEmailServerID 사용자 설정 메일 계정
 * @param strEmailServerPassword 사용자 설정 메일 계정 비밀번호
 * @param strCompanyName 소속기관 상호
 * @param strCompanyPresident 소속기관 대표자
 * @param strCompanyAddress 소속기관 주소
 */
PQService.prototype.setWonderfulOfficeUserInformation = function (
		strUserName, strUserCompany, strUserPosition, 
		strUserEmail, strUserPhone, strUserFax, strUserAddress,
		bUseDefaultEmailServer, strEmailServerAddress, 
		strEmailServerID, strEmailServerPassword,
		strCompanyName, strCompanyPresident, strCompanyAddress)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.setWonderfulOfficeUserInformation(strUserName, strUserCompany, strUserPosition, 
				strUserEmail, strUserPhone, strUserFax, strUserAddress,
				bUseDefaultEmailServer, strEmailServerAddress, 
				strEmailServerID, strEmailServerPassword,
				strCompanyName, strCompanyPresident, strCompanyAddress);
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 가져옵니다.
 * @return 조직\t직위\t이름\t이메일\t조직\t직위\t이름\t이메일\t....
 */
PQService.prototype.getSanctionLineInfoList = function ()
{
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		return objApplet.getSanctionLineInfoList();
	}
	
	return "";
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에 추가한다.
 * @param strOrganization 조직
 * @param strPostition 직위
 * @param strPersonName 이름
 * @param strEmailAddress 이메일 주소
 */
PQService.prototype.addSanctionLineInfo = function (strOrganization, strPostition, strPersonName, strEmailAddress)
{
	var objApplet = this._getAppletObject();

	if (null != objApplet)
	{
		objApplet.addSanctionLineInfo(strOrganization, strPostition, strPersonName, strEmailAddress);
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에 수정한다.
 * @param strOrgEmailAddress 원본 이메일 주소
 * @param strNewOrganization 새 조직
 * @param strNewPostition 새 직위
 * @param strNewPersonName 새 이름
 * @param strNewEmailAddress 새 이메일 주소
 */
PQService.prototype.changeSanctionLineInfo = function (strOrgEmailAddress,
		strNewOrganization, strNewPostition, strNewPersonName, strNewEmailAddress)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.changeSanctionLineInfo(strOrgEmailAddress,
				strNewOrganization, strNewPostition, strNewPersonName, strNewEmailAddress);
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에서 삭제한다.
 * @param strEmailAddress 이메일 주소
 */
PQService.prototype.removeSanctionLineInfo = function (strEmailAddress)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.removeSanctionLineInfo(strEmailAddress);
	}
}

PQService.prototype.openAttachmentOfWPQModel = function (strFileIndex)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.openAttachmentOfWPQModel(strFileIndex);
	}
	
	return null;
}

/**
 * @return 전역정보맵에 키가 있는지 여부
 */
PQService.prototype.containsGlobalInfo = function (strKey)
{
	if (IsWebModel())
	{
		return ("DP_SCODE" == strKey || "USER_ID" == strKey || "USER_NAME" == strKey || 
			"PS_CODE" == strKey || "JOB_LEVEL" == strKey || "DocLevel" == strKey ||
			"UserID" == strKey || "UserName" == strKey || "PS_NAME" == strKey ||
			"UPSType" == strKey)
	}
	else
	{
		if (IsWPQModel())
		{
			//사용자기호, 사용자명, 부서명, 직위
			return ("USER_ID" == strKey || "USER_NAME" == strKey ||
					"UserID" == strKey || "UserName" == strKey ||
					"PS_NAME" == strKey || "PS_CLASS" == strKey);
		}
		else
		{
			var strValue = null;
			try
			{
				strValue = this._getAppletObject().containsGlobalInfo(strKey);
			}
			catch (e)
			{
				strValue = null;
			}
			
			return strValue ? true : false;
		}
	}
}

/**
 * 전역 정보를 반환합니다. 
 * 전역 정보는 로그인이 된 상태일 때만 가져 올 수 있다.
 * @param strKey 전역정보 키
 * @return 전역정보 값
 */
PQService.prototype.getGlobalInfo = function (strKey)
{
	if (IsWebModel())
	{
		if (GlobalField.isPortalLoggedin())
		{
			var strValue = GlobalField.getPortalUserData(strKey);
	
			if (null != strValue && 0 < strValue.length && "JOB_LEVEL" == strKey)
			{
				return ModelCore.getJobLevel(GetKnowledgeBankRegistryFlag(), strValue).toString();
			}

			return strValue;
		}
		else if (ModelCore.isSolutionLoggedin())
		{
			if (IsDotNet())
			{
				var strValue = null;
				var heWebBosClient = document.getElementById("__PQClient_DotNet");
				if (null != heWebBosClient)
				{
					strValue = heWebBosClient.GetGlobalInfo(strKey);
				}
				
				return strValue;
			}
			else
			{
				var objApplet = this._getAppletObject();
		
				if (null != objApplet)
				{
					return objApplet.getGlobalInfo(strKey);
				}
			}
		}
	}
	else
	{
		if (IsWPQModel())
		{
			//사용자기호, 사용자명, 부서명, 직위
			if ("USER_ID" == strKey || "USER_NAME" == strKey ||
					"UserID" == strKey || "UserName" == strKey ||
					"PS_NAME" == strKey || "PS_CLASS" == strKey)
			{
				var strUserInformationString = PQService.getWonderfulOfficeUserInformation();
				var arUserInformationList = strUserInformationString.split("\t");
				if (null == arUserInformationList || 0 == arUserInformationList.length)
				{
					return "";
				}
				
				if ("USER_NAME" == strKey || "UserName" == strKey)
				{
					return arUserInformationList[0];
				}
				else if ("PS_NAME" == strKey)
				{
					return arUserInformationList[1];					
				}	
				else if ("PS_CLASS" == strKey)
				{
					return arUserInformationList[2];					
				}	
				else if ("USER_ID" == strKey || "UserID" == strKey)
				{
					return arUserInformationList[3];
				}
			}
		}
		else
		{
			var objApplet = this._getAppletObject();
			
			if (null != objApplet)
			{
				return objApplet.getGlobalInfo(strKey);
			}
		}
	}
	
	return "";
}

/**
 * 전체 전역 정보를 반환합니다.
 */
PQService.prototype.getAllGlobalInfo = function ()
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.getAllGlobalInfo();
	}
}

// DataSet cell 값 변경
PQService.prototype.updateDataSetCellValue = function (strKey, nRowIndex, nColumn, strValue)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.updateDataSetCellValue(strKey, nRowIndex, nColumn, strValue);
	}
}

// DataSet row의 값 가져옴	
PQService.prototype.getRowValueArray = function (strKey, nRowIndex)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.getRowValueArray(strKey, nRowIndex);
	}
}

// DataSet Row 추가
PQService.prototype.insertRowToDataSet = function (strKey, nRowIndex)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.insertRowToDataSet(strKey, nRowIndex);
	}
}

// DataSet Row 삭제
PQService.prototype.deleteRowToDataSet = function (strKey, nRowIndex)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.deleteRowToDataSet(strKey, nRowIndex);
	}
}

PQService.prototype.pause = function (lDuration)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.pause(lDuration);
	}
	else
	{
		throw new NotInstallClientProgram();
	}
}

/**
 * PQClient 애플릿을 가져옵니다.
 * 
 * @param  bCreate : WebBosAgent가 생성되지 않았을 경우, 생성함 
 */
PQService.prototype._getAppletObject = function()
{
	var objApplet = null;
	if (IsWebModel())
	{
	}
	else
	{
		var objFrame = Utils.findClientFrame();
		
		if (null != objFrame)
		{
			objApplet = objFrame.document.getElementById("__PQClient");
		}
		
		if (null != objApplet)
		{
			try
			{
				objApplet.isActive();
			}
			catch (e)
			{
				objApplet = null;
			}
		}
	}
	
	
	return objApplet;
}

PQService.prototype._executeService = function (objApplet, xnRequest)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeService(strRequest);
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	
	return xnResult;
}

PQService.prototype._executeSchedulerService = function (objApplet, xnRequest)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeSchedulerService(strRequest);
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	
	return xnResult;
}

PQService.prototype._executeQpgService = function (objApplet, xnRequest)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeQpgService(strRequest);
	
	return strResult;
}

PQService.prototype._executeScriptService = function (objApplet, xnRequest, bIncludeBeforeAction)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeScriptService(strRequest, bIncludeBeforeAction);
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	
	return xnResult;
}

/**
 * 프로그램 진행 관리자의 후처리를 처리한다.
 * @param objApplet 애플릿.
 * @param xnRequest 요청 정보.
 * @param strPath 경로를 포함한 자식폼 이름. 상세폼 기능에 쓰인다.
 */
PQService.prototype._executeProcessManagerAfterAction = function (objApplet, xnRequest, strPath)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeProcessManagerAfterAction(strRequest, strPath);
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	
	return xnResult;
}

/**
 * 저장하기전 팝업 유효성 검사를 수행한다.
 */
PQService.prototype._executeForeignKeyCheck = function (objApplet, xnRequest)
{
	var strRequest = XmlLib.serializeToString(xnRequest);
	
	var strResult = objApplet.executeForeignKeyCheck(strRequest);
	
	var xnResult = XmlLib.loadXMLFromString(strResult);
	
	return xnResult;
}

/**
 * 애플릿으로부터 file data를 byte[]로 받는다.
 *
 * @param strKey - 아톰명(varName)
 * @return file data
 */
PQService.prototype._getFileData = function (strKey)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		return objApplet.getFileData(strKey);
	}
}

/**
 *	애플릿에 file data를 byte[]로 보낸다.
 *
 *	@param strKey - 아톰명(varName)
 *	@param arValue - file data
 */
PQService.prototype._putFileData = function (strKey, arValue)
{
	var objApplet = this._getAppletObject();
	
	if (null != objApplet)
	{
		objApplet.putFileData(strKey, arValue);
	}
}

PQService.prototype.getProjectName = function ()
{
	var objApplet = this._getAppletObject();
	if (null != objApplet)
	{
		return objApplet.getProjectName();
	}
	
	return "";
}

PQService.init = function ()
{
	g_objPQService = new PQService();
}

/**
 * 솔루션에 로그인 되었다고 설정한다.
 */
PQService.setSolutionLoggedin = function ()
{
	try
	{
		g_objPQService.setSolutionLoggedin();
	}
	catch (e)
	{
		HandleException(e);
	}
}

/**
 * 솔루션에 로그인이 되었는가?
 */
PQService.isSolutionLoggedin = function ()
{
	return g_objPQService.isSolutionLoggedin();
}

PQService.executeService = function (xnRequestDoc)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.executeService(xnRequestDoc);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.executeScriptService = function (xnRequestDoc, bIncludePreProcess)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.executeScriptService(xnRequestDoc, bIncludePreProcess);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.setScriptAttribute = function (strVarName, strAttributeName, strValue)
{
	try
	{
		g_objPQService.setScriptAttribute(strVarName, strAttributeName, strValue);
	}
	catch (e)
	{
		HandleException(e);
	}
}

PQService.scriptMakeRequest = function (strRequest)
{
	try
	{
		g_objPQService.scriptMakeRequest(strRequest);
	}
	catch (e)
	{
		HandleException(e);
	}
}

PQService.scriptHandleResult = function ()
{
	try
	{
		g_objPQService.scriptHandleResult();
	}
	catch (e)
	{
		HandleException(e);
	}
}

/**
 * 프로그램 진행 관리자의 후처리를 처리한다.
 * @param xnRequestDoc 요청 정보.
 * @param strPath 경로를 포함한 자식폼 이름. 상세폼 기능에 쓰인다.
 */
PQService.executeProcessManagerAfterAction = function (xnRequestDoc, strPath)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.executeProcessManagerAfterAction(xnRequestDoc, strPath);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.executeSchedulerService = function (xnRequestDoc)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.executeSchedulerService(xnRequestDoc);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.executeForeignKeyCheck = function (xnRequestDoc)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.executeForeignKeyCheck(xnRequestDoc);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.getOperationInfo = function ()
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.getOperationInfo();
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

PQService.getXSL = function (strPath)
{
	var xnResult = null;
	
	try
	{
		xnResult = g_objPQService.getXSL(strPath);
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return xnResult;
}

/**
 * @return 전역정보맵에 키가 있는지 여부 
 */
PQService.containsGlobalInfo = function (strKey)
{
	if (null != g_objPQService)
	{
		return g_objPQService.containsGlobalInfo(strKey);
	}

	return false;
}

/**
 * 로그인 사용자의 정보를 가져온다.
 * @param strKey  
 */
PQService.getGlobalInfo = function (strKey)
{
	if (null != g_objPQService)
	{
		var strGrobalInfo = null;
		
		try
		{
			strGrobalInfo = g_objPQService.getGlobalInfo(strKey);
		}
		catch (e)
		{
			HandleException(e);
		}
		
		return strGrobalInfo;
	}
	else
	{
		return "";
	}
}

/**
 * 전체 전역 정보를 "Key1$Value;Key2$Value;" 형태의 문자열로 가져온다.
 */
PQService.getAllGlobalInfo = function ()
{
	var strGrobalInfo = "";
	
	try
	{
		strGrobalInfo = g_objPQService.getAllGlobalInfo();
	}
	catch (e)
	{
		HandleException(e);
	}
	
	return strGrobalInfo;
}

/**
 *모델을 닫을때 요청.
 *@param strModelName 모델서브경로/모델명
 *@param bSolutionLogout 솔루션 로그아웃.
 */
PQService.closeModel = function (strModelName, bSolutionLogout)
{
	g_objPQService.closeModel(strModelName, bSolutionLogout);
}

/**
 * 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)를 엽니다.
 * @param bSmartPaperForm true: SPF, false: SPD
 */
PQService.openSmartPaper = function (bSmartPaperForm)
{
	if (IsWPQModel())
	{
		g_objPQService.openSmartPaper(bSmartPaperForm);		
	}
	else
	{
		alert("기능이 추가될 예정입니다.");
	}
}

/**
 * 작성 중이던 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)를 로컬 디스크에 저장합니다.
 */
PQService.saveTempSPD = function ()
{
	if (IsWPQModel())
	{
		g_objPQService.saveTempSPD();		
	}
	else
	{
		alert("기능이 추가될 예정입니다.");
	}
}

/**
 * 결재모델을 인쇄합니다.
 */
PQService.printNtoaModel = function (xnRequestDoc)
{
	var xnRequest = MakeRequest.createRequestNode();	
	MakeRequest.makeServiceRequest(xnRequest);
	//Sanction.makeSanctionRequest() 참고.
	var xnNtoaRequest = XmlLib.createChild(xnRequest, "Ntoa");	
	g_objMasterInfomation.makeRequest(xnNtoaRequest);
	g_objProcessInfomation.makeRequest(xnNtoaRequest);
	
	MakeRequest.makeAtomRequest(xnRequest, false);	
	if (ContainsKwdAtom())
	{
		var xnAtomRequest = MakeRequest.getAtomRequestNode(xnRequest);		
		KwdAtom.makeRequest(xnAtomRequest, true);
	}
	
	g_objPQService.printNtoaModel(xnRequest.ownerDocument);
}

/**
 * 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)- 변경된 팝업 데이터를 저장합니다.
 * @param strAtomVarName 팝업 아톰 변수명.
 * @param strNewDataString 변경된 팝업 데이터 문자열. '값1$값1#값2$값2'
 */
PQService.saveSPFWithChangedPopup = function (strAtomVarName, strNewDataString)
{
	if (IsWPQModel())
	{
		g_objPQService.saveSPFWithChangedPopup(strAtomVarName, strNewDataString);		
	}
}

/**
 * 원더풀 오피스 개별 문서(Wonderful office Private QFR Model)의 결재 처리를 합니다.
 * @param xnRequestDoc 문서 내용 xml
 */
PQService.sanctWPQModel = function (xnRequestDoc)
{
	if (IsWPQModel())
	{
		return g_objPQService.sanctWPQModel(xnRequestDoc);		
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 가져옵니다.
 * @return 조직\t직위\t이름\t이메일\t조직\t직위\t이름\t이메일\t....
 */
PQService.getSanctionLineInfoList = function ()
{
	if (IsWPQModel())
	{
		return g_objPQService.getSanctionLineInfoList();		
	}
}

/**
 * 원더풀 오피스의 개별 문서 사용자의 정보를 가져옵니다.
 * @return 이름\t소속\t직위\t이메일\t전화번호\t팩스\t주소\t
 * 기본메일서버사용여부\t사용자설정메일서버주소\t사용자설정메일계정\t사용자설정메일계정비밀번호\t
 * 소속기관상호\t소속기관대표자\t소속기관주소
 */
PQService.getWonderfulOfficeUserInformation = function ()
{
	if (IsWPQModel())
	{
		return g_objPQService.getWonderfulOfficeUserInformation();		
	}
}

/**
 * 원더풀 오피스의 개별 문서 사용자의 정보를 저장합니다.
 * @param strUserName 이름
 * @param strUserCompany 소속
 * @param strUserPosition 직위
 * @param strUserEmail 이메일
 * @param strUserPhone 전화번호
 * @param strUserFax 팩스
 * @param strUserAddress 주소
 * @param bUseDefaultEmailServer 기본 메일 서버 사용 여부
 * @param strEmailServerAddress 사용자 설정 메일 서버 주소
 * @param strEmailServerID 사용자 설정 메일 계정
 * @param strEmailServerPassword 사용자 설정 메일 계정 비밀번호
 * @param strCompanyName 소속기관 상호
 * @param strCompanyPresident 소속기관 대표자
 * @param strCompanyAddress 소속기관 주소
 */
PQService.setWonderfulOfficeUserInformation = function (
		strUserName, strUserCompany, strUserPosition, strUserEmail, strUserPhone, strUserFax, strUserAddress,
		bUseDefaultEmailServer, strEmailServerAddress,strEmailServerID, strEmailServerPassword,
		strCompanyName, strCompanyPresident, strCompanyAddress)
{
	if (IsWPQModel())
	{
		return g_objPQService.setWonderfulOfficeUserInformation(
				strUserName, strUserCompany, strUserPosition, strUserEmail, strUserPhone, strUserFax, strUserAddress, 
				bUseDefaultEmailServer, strEmailServerAddress, strEmailServerID, strEmailServerPassword,
				strCompanyName, strCompanyPresident, strCompanyAddress);		
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에 추가한다.
 * @param strOrganization 조직
 * @param strPostition 직위
 * @param strPersonName 이름
 * @param strEmailAddress 이메일 주소
 */
PQService.addSanctionLineInfo = function (strOrganization, strPostition, strPersonName, strEmailAddress)
{
	if (IsWPQModel())
	{
		return g_objPQService.addSanctionLineInfo(strOrganization, strPostition, strPersonName, strEmailAddress);		
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에서 수정한다.
 * @param strOrgEmailAddress 원본 이메일 주소
 * @param strNewOrganization 새 조직
 * @param strNewPostition 새 직위
 * @param strNewPersonName 새 이름
 * @param strNewEmailAddress 새 이메일 주소
 */
PQService.changeSanctionLineInfo = function (strOrgEmailAddress,
		strNewOrganization, strNewPostition, strNewPersonName, strNewEmailAddress)
{
	if (IsWPQModel())
	{
		return g_objPQService.changeSanctionLineInfo(strOrgEmailAddress,
				strNewOrganization, strNewPostition, strNewPersonName, strNewEmailAddress);		
	}
}

/**
 * 원더풀 오피스의 개별 문서의 대외 결재선 정보를 주소록에서 삭제한다.
 * @param strEmailAddress 이메일 주소
 */
PQService.removeSanctionLineInfo = function (strEmailAddress)
{
	if (IsWPQModel())
	{
		return g_objPQService.removeSanctionLineInfo(strEmailAddress);		
	}
}

/**
 * 스마트페이퍼 - 개별문서의 문서첨부 기능의 첨부 파일 열기
 * @param strFileIndex 첨부 파일의 고유 번호. 0부터 시작
 * @return 첨부 파일 전체 경로. 없으면 null. ex) c:/temp/abc.txt
 */
PQService.openAttachmentOfWPQModel = function (strFileIndex)
{
	if (IsWPQModel())
	{
		return g_objPQService.openAttachmentOfWPQModel(strFileIndex);		
	}
}

/**
 *	애플릿에서 file data를 byte[]로 받는다.
 *
 *	@param strKey - 아톰명(varName)
 */
PQService.getFileData = function (strKey)
{
	return g_objPQService._getFileData(strKey);
}

/**
 *	XML request에 포함 할 수 없는 byte[]를 애플릿에 저장
 *
 *	@param strKey - 아톰명(varName)
 *	@param arValue - byte[]
 */
PQService.putFileData = function (strKey, arValue)
{
	g_objPQService._putFileData(strKey, arValue);
}

/**
 * strMenuPath경로의 메뉴(QMX)를 구한다.
 */
PQService.getMenuQMX = function (strMenuPath)
{
	var xnQMX = null;
	
	var strQuery = "/ups/Download.do?ServiceName=QMXFile&FilePath=" + strMenuPath;
	var strQMX = PQAjax.post(strQuery, "");
	if (null != strQMX)
	{
		xnQMX = XmlLib.loadXMLFromString(strQMX);
	}	
	
	return xnQMX;
}

/**
 * 모델의 프로세스를 일시 중지한다.
 * 
 * @param lDuration 중지할 시간. 밀리세컨드 단위.
 */
PQService.pause = function (lDuration)
{
	g_objPQService.pause(lDuration);
}

/**
 * 현재 모델의 프로젝트명을 가져옵니다.
 */
PQService.getProjectName = function ()
{
	return g_objPQService.getProjectName();
}
/**
 * 스크립트 실행에 필요한 Client Engine 라이브러리
 */
 
/**
 * 가장 마지막에 객체생성한 자식폼의 Loading이 끝났는지 여부  
 */
var g_bCurrentChildLoaded = false;

/**
 * 부모윈도우, 부모<->자식 폼간 소통시 관계된 폼의 makeRequest와 handleResult를 하기 위해서 관리됨
 */
var g_objParentWnd = null;

/**
 * 자식윈도우, 부모<->자식 폼간 소통시 관계된 폼의 makeRequest와 handleResult를 하기 위해서 관리됨
 */
var g_alChildWnd = new Array();

function PQScript ()
{
	this.m_htFunctionTable = null;
}


/*
 * 스크립트 실행
 * @param nScriptIndex 아톰의 스크립트 인덱스
 * @param nEventID 발생한 이벤트 ID (BOS에서 정의)
 * @param arParam 스크립트 파라미터 정보
 * @return 스크립트 실행 결과 실패 -1, 성공 0이상, 기타 null
 */
PQScript.prototype.execute = function (nScriptIndex, nEventID, arParam, bIncludeBeforeAction)
{
	if (g_bQWPClientMode && null != g_objDoc)
	{
		return g_objDoc.executeScript(nScriptIndex, nEventID, arParam, bIncludeBeforeAction);
	}
	
	this._setScriptModelInfo(PQScript.SCRIPT_ACTION, nScriptIndex, nEventID);

	// 관계된 폼의 요청만들기를 발생시킨다.
	PQScript.makeRequestForRelationWindow();
	
	var xnRequestDoc = this._makeRequest(arParam);
	
	var xnResultDoc = PQService.executeScriptService(xnRequestDoc, bIncludeBeforeAction);
	
	// 관계된 폼의 결과처리를 발생 시킨다.
	PQScript.handleResultForRelationWindow();
	
	return this.handleResult(xnResultDoc);
}

PQScript.prototype.executeProcessManagerAfterAction = function (nScriptIndex, nEventID, arParam)
{
	this._setScriptModelInfo(PQScript.SCRIPT_ACTION, nScriptIndex, nEventID);

	var xnRequestDoc = this._makeRequest(arParam);
	
	// 관계된 폼의 요청만들기를 발생시킨다.
	PQScript.makeRequestForRelationWindow();
	
	var xnResultDoc = PQService.executeProcessManagerAfterAction(xnRequestDoc, "");
	
	// 관계된 폼의 결과처리를 발생 시킨다.
	PQScript.handleResultForRelationWindow();
	
	return this.handleResult(xnResultDoc);
}

/**
 * 서버 스크립트 함수 동작
 * 이벤트에 의한 함수 호출이 아니라. 스크립트 문단 호출이다.
 */
PQScript.prototype.executeServerScript = function (strFuncName, nExeID, arArgs)
{
	this._setScriptModelInfo(PQScript.SCRIPT_ACTION, -1, -1);

	var xnRequestDoc = this._makeThinRequest(strFuncName, arArgs);
	
	var xnResult = null;
	
	try
	{
		if (IsWebModel())
		{
			// 웹 페이지 모델인 경우 PQPortalService에서 서비스 한다.
			xnResult = g_objPQPortalService.executeServerScriptService(xnRequest, false);
		}
	}
	catch (e)
	{
		HandleException(e);
	}
	
	if (null != xnResult)
	{
		return this._handleThinResult(xnResult);
	}
}

/**
 * 자식폼을 띄운다.
 * '객체생성(#폼) 스크립트를 이용한다.
 * @param strPath 경로를 폼함한 자식폼 이름.
 */
PQScript.prototype.createChildForm = function (strPath)
{
	this._setScriptModelInfo(PQScript.SCRIPT_ACTION, 0, 0);

	var xnRequestDoc = this._makeRequest(null);
	var xnResultDoc = PQService.executeProcessManagerAfterAction(xnRequestDoc, strPath);
	
	return this.handleResult(xnResultDoc);

}

PQScript.prototype.setScriptAttribute = function (strVarName, strAttributeName, strValue)
{
	PQService.setScriptAttribute(strVarName, strAttributeName, strValue);
}

PQScript.prototype.handleResult = function (xnResultDoc)
{
	var xnResult = HandleResult.getResultNode(xnResultDoc);
	
	this._handleFirstResult(xnResult);
	
	HandleResult.handleAtomResult(xnResult);
		
	if (IsNtoaModel())
	{
		HandleResult.handleNtoaScriptResult(xnResultDoc);
	}
	
	HandleResult.handleOperateResult(xnResult);
	
	return this._handleScriptResult(xnResult);
}

PQScript.prototype.findFunction = function (strMessage)
{
	var bExist = this.m_htFunctionTable[strMessage];
	
	if (null == bExist)
	{
		return false;
	}
	return bExist;
}

/**
 * PQ스크립트 함수 테이블을 set한다.
 */
PQScript.prototype.setFunctionTable = function (htFunctionTable)
{
	this.m_htFunctionTable = htFunctionTable;
}

/*
 * 모델 정보를 설정한다.
 * 
 * @param strServiceName 스크립트 서비스 종류
 * @param nScriptIndex 아톰의 스크립트 인덱스
 * @param nEventID 발생한 이벤트 ID (BOS에서 정의)
 */
PQScript.prototype.setScriptModelInfo = function (strServiceName, nScriptIndex, nEventID)
{
	GlobalField.setServiceName(strServiceName);
	GlobalField.setScriptIndex(nScriptIndex);
	GlobalField.setScriptEventID(nEventID);
}

////////////////////
// private method

/*
 * 모델 정보를 설정한다.
 * 
 * @param strServiceName 스크립트 서비스 종류
 * @param nScriptIndex 아톰의 스크립트 인덱스
 * @param nEventID 발생한 이벤트 ID (BOS에서 정의)
 */
PQScript.prototype._setScriptModelInfo = function (strServiceName, nScriptIndex, nEventID)
{
	GlobalField.setServiceName(strServiceName);
	GlobalField.setScriptIndex(nScriptIndex);
	GlobalField.setScriptEventID(nEventID);
}

PQScript.prototype._makeRequest = function (arParam)
{
	var xnRequest = MakeRequest.createRequestNode();
	MakeRequest.makeServiceRequest(xnRequest);
	MakeRequest.makeAtomRequest(xnRequest);
	
	if (ContainsPopupAtom())	// 팝업 실행 위해 전체 팝업 정보 전달
	{
		var xnAtomRequest = XmlLib.selectSingleNode(xnRequest, "./Atom");
		PopupAtom.makeRequest(xnAtomRequest);
	}
	
	this._makeScriptRequest(xnRequest, arParam);
	
	if (IsNtoaModel())
	{
		MakeRequest.makeNtoaScriptRequest(xnRequest);
	}
	
	return xnRequest.ownerDocument;
}

PQScript.prototype._makeScriptRequest = function (xnRequest, arParam)
{
	var xnScript = XmlLib.createChild(xnRequest, "Script");
	
	XmlLib.setAttribute(xnScript, "PopupBlock", g_strPopupBlockInfo);
	
	this._makeEventRequest(xnScript, arParam);
}

PQScript.prototype._makeEventRequest = function (xnScript, arParam)
{
	if (null == arParam)
	{
		return;
	}
	
	var xnEvent = XmlLib.createChild(xnScript, "Event");
	
	var nLen = arParam.length;
	for (i = 0 ; i < nLen; i = i+1)
	{
		var xnParam = XmlLib.createChild(xnEvent, "Param");
		XmlLib.setTextValue(xnParam, arParam[i]);
	}
}


PQScript.prototype._makeThinRequest = function (strFuncName, arArgs)
{
	var xnRequest = MakeRequest.createRequestNode();
	MakeRequest.makeServiceRequest(xnRequest);
	
	g_objDoc.makeScriptVarRequest(xnRequest, strFuncName);
	
	g_objDoc.makeFuncParamRequest(xnRequest, arArgs);
	
	this._makeServerScriptRequest(xnRequest, strFuncName);
	
	g_objPQQuery.makeQueryModifyRequest(xnRequest, strFuncName);
	
	return xnRequest.ownerDocument;
}

PQScript.prototype._makeServerScriptRequest = function (xnRequest, strFuncName)
{
	var xnScript = XmlLib.createChild(xnRequest, "ServerScript");
		
	XmlLib.createChildWithValue(xnScript, "FuncName", strFuncName);
}

PQScript.prototype._handleThinResult = function (xnResultDoc)
{
	var xnResult = HandleResult.getResultNode(xnResultDoc);
	
	g_objDoc.handleScriptVarResult(xnResult);
	
	var xnScriptResult = XmlLib.selectSingleNode(xnResult, "./ServerScript");
	
	return xnScriptResult.getAttribute("Result");
}

/**
 * 결과를 검사하여 폼을 닫아야 할 경우, 폼을 닫음
 */
PQScript.prototype._handleFormCloseResult = function (xnResult)
{
	var xnScriptResult = HandleResult.getScriptNode(xnResult);
	
	var xnAttributeResult = XmlLib.selectSingleNode(xnScriptResult, "Model");
	if (null == xnAttributeResult)
	{
		return;
	}
	
	var strVarName = xnAttributeResult.getAttribute("FormClose");
	if (null != strVarName)
	{
		PQScript.executeFormClose(strVarName)
		return;
	}
}

/**
 * 팝업차단 스크립트 결과를 처리한다.
 */
PQScript.prototype._handlePopupBlockResult = function (xnScript)
{
	var strPopupBlockAdd = xnScript.getAttribute("PopupBlockAdd")
	
	if (null != strPopupBlockAdd && 0 < strPopupBlockAdd.length)
	{
		var arAddInfo = strPopupBlockAdd.split(";");
		var nLen = arAddInfo.length;
		
		for (var i = 0; i < nLen - 1; i += 1)
		{
			var arInfo = arAddInfo[i].split("$");
			var strKey = "*" + arInfo[0];
			var nExpire = parseInt(arInfo[1]);
			
			CookieLib.setCookie(strKey, "1", nExpire);
		}
		
		GlobalField.initPopupBlockInfo();
		
		var parentWindow = window.top.opener;
		if (null != parentWindow)
		{
			parentWindow.GlobalField.initPopupBlockInfo();
		}
	}
}

/**
 * 스크립트 동작중 저장동작이 이루어 졌다면 일반모델의 파일업로드 계열 아톰의 정보도 저장한다.
 */
PQScript.prototype._handleUploadFileResult = function (xnResult)
{
	var xnScriptResult = HandleResult.getScriptNode(xnResult);
	if (null == xnScriptResult)
	{
		return;
	}
	
	var strExecuteSave = xnScriptResult.getAttribute("ExecuteSave");
	if ("-1" != strExecuteSave)
	{
		Model.startWaitMessage("첨부파일을 업로드 중입니다.");
		Model.uploadFile();
		Model.stopWaitMessage();
		
		var bResult = (0 == strExecuteSave)? false : true;
		this._executeSaveAfter(bResult);
	}
}

PQScript.prototype._handleScriptResult = function (xnResult)
{
	var xnScriptResult = HandleResult.getScriptNode(xnResult);
	if (null == xnScriptResult)
	{
		return;
	}
	
	this._handleAttributeResult(xnScriptResult);
	
	this._handleFormCloseResult(xnResult);
	
	this._handlePopupBlockResult(xnScriptResult);
	
	return xnScriptResult.getAttribute("Result");
}

/**
 * 스크립트 동작 결과 중 다른 아톰보다 먼저 실행되어야하는 결과를 처리합니다.
 */
PQScript.prototype._handleFirstResult = function (xnResult)
{
	var xnScriptResult = HandleResult.getScriptNode(xnResult);
	if (null == xnScriptResult)
	{
		return;
	}
	
	this._handleUploadFileResult(xnResult);	
	
	// Web포탈 스크립트 동작중 메세지출력이 있었으면
	var strScriptMessage = xnScriptResult.getAttribute("ScriptMessage");
	if (null != strScriptMessage)
	{
		var arScriptMessageInfo = strScriptMessage.split("$");
		alert(arScriptMessageInfo[1]);
	}
	
	//서버접속 아톰의 스크립트 동작이 있었는가?
	if ("true" == xnScriptResult.getAttribute("IsExecutedWebLoginAtomScript"))
	{
		var strScriptType = xnScriptResult.getAttribute("WebLoginAtomScriptType");
		if ("0" == strScriptType)
		{
			var strLoginID = xnScriptResult.getAttribute("LoginID");
			var strLoginPassword = xnScriptResult.getAttribute("LoginPassword");
			
			WebLoginAtom.login(strLoginID, strLoginPassword);
		}
		else if ("1" == strScriptType)
		{
			WebLoginAtom.logout();
		}
		else if ("2" == strScriptType)
		{
			WebLoginAtom.executeLogin();
		}
	}
}

/**
 * 함수의 인자값 : 스크립트 동작중 저장동작을 수행했는지 결과값
 * true : 저장동작 수행 후 성공
 * false: 저장동작 수행 후 실패
 */
PQScript.prototype._executeSaveAfter = function (bResult)
{
	// 폼_저장완료 스크립트
	ScriptFormEvent.onEndSave();
	
	var objBtnAtom = ButtonAtom.getSaveButtonAtom();	
	// 저장후 화면 보존이 아닐 경우에만 refresh
	if (null != objBtnAtom && false == objBtnAtom.isAfterSave())
	{
		// 화면을 지우지 않고 리프레시를 하면 저장 당시 아톰값이 
		// 리프레시 동작에서 요청으로 갔다가 결과로 다시 나오게 된다.
		g_objModelCore.clearAtomValue();
		Model.executeRefresh();
	}
	
	//폼_저장결과 스크립트. 저장완료후로 바뀌었다고 함.
	ScriptFormEvent.onResultSave(bResult);
}

PQScript.prototype._handleAttributeResult = function (xnScriptResult)
{
	var xnAttributeResult = XmlLib.selectSingleNode(xnScriptResult, "Model");
	if (null == xnAttributeResult)
	{
		return;
	}
	
	if ("true" == xnAttributeResult.getAttribute("CloseForm"))
	{
		// 폼.닫기()
		PQScript.executeFormClose();
	}
	
	if ("true" == xnAttributeResult.getAttribute("AllVanish"))
	{
		// f9 화면전환 처리
		Model.switchAllVanish();
	}
	
	var xlAtomList = xnAttributeResult.childNodes;
	if (null == xlAtomList)
	{
		return;
	}
	
	for (var i = 0, nLen = xlAtomList.length; i < nLen; i++)
	{
		var xnAtom = xlAtomList[i];
		if (null == xnAtom)
		{
			continue;
		}
		
		var strAttributeID = xnAtom.getAttribute("AttributeID");
		if (null == strAttributeID || 0 == strAttributeID.length)
		{
			continue;
		}

		this._handleAttributeList(xnAtom, strAttributeID.split(","));
		
		xnAtom.setAttribute("AttributeID", "");
	}
	
	var strScriptAttribute = XmlLib.serializeToString(xnAttributeResult);
	m_xnScriptAttribute = XmlLib.loadXMLFromString(strScriptAttribute);
}

PQScript.prototype._handleAttributeList = function (xnAtom, arAttributeID)
{
	var nLen = arAttributeID.length;
	for (var i = 0; i < nLen; i=i+1)
	{
		// TODO 조영운 해당 속성은 BOS2Key에 정의되어 있습니다.
		switch (arAttributeID[i])
		{
			case "253": // 비활성화
			{
				this._handleDisableAttribute(xnAtom);
				break;
			}
			case "203": // 값
			case "279": // 제목
			{
				this._handleTitleAttribute(xnAtom);
				break;
			}
			case "263": // 배경색
			{
				this._handleBGColorAttribute(xnAtom);
			}
			case "286": // 화면감춤
			{
				this._handleVisibleAttribute(xnAtom);
				break;
			}
			case "288": // 글꼴
			{
				this._handleFontAttribute(xnAtom);
				break;
			}
			case "300": // 너비
			{
				this._handleWidthAttribute(xnAtom);
				break;
			}
			case "301": // 높이
			{
				this._handleHeightAttribute(xnAtom);
				break;
			}
			case "303":	// 참조아톰
			{
				this._handleReferenceAtomAttribute(xnAtom);
				break;
			}
			case "304": // 실행모델명
			{
				this._handleExcuteModelNameAttribute(xnAtom);
				break;
			}
			case "325": // 읽기전용
			{
				this._handleReadonlyAttribute(xnAtom);
				break;
			}
			case "475":	// 트리전개
			{
				this._handleTreeAttribute(xnAtom, arAttributeID[i]);
				break;
			}
			case "483": // 선택인덱스
			{
				this._handleSelectRowAttribute(xnAtom);
				break;
			}
			case "521":	// 확장그리드
			{
				this._handleGridExAttribute(xnAtom, arAttributeID[i]);
				break;
			}
			case "712": //발신명의
			case "714": //직인코드
			case "715": //직인속성
			{
				this._handleSenderAtomAttribute(xnAtom, arAttributeID[i]);
				break;
			}
			case "344":	// 초점주기, 이것은 Action이지만 Applet에서 처리할 수 없기 때문에 Attribute와 같이 처리한다.
			{
				this._handleFocus(xnAtom);
				break;
			}
			default:
			{
				break;
			}
		}
	}
}

/**
 *	스크립트 속성 : 값, 제목을 처리한다.
 *	@param xnAtom - 아톰의 속성정보가 담긴 XML노드
 */
PQScript.prototype._handleTitleAttribute = function (xnAtom)
{
	var strAtomType = xnAtom.nodeName
	
	if ("RectangleAtom" == strAtomType)
	{
		var xnReferenceAttrib = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib");
		var strVarName = xnReferenceAttrib.getAttribute("VarName");
		var objAtom = RectangleAtom.getAtom(strVarName);
		
		var xnTitle = XmlLib.selectSingleNode(xnAtom, "TitleAttrib");
		var strTitle = XmlLib.getTextValue(xnTitle);
		
		objAtom.setValue(strTitle);
	}
}

PQScript.prototype._handleDisableAttribute = function (xnAtom)
{
	// TODO 조영운 heAtom이 null일 경우에는 처음 페이지 로딩부터 잘못된 것입니다. 그냥 넘어갈지, 예외를 뿌릴지 결정하고 처리해야 합니다.
	var heAtom = this._getAtomHTML(xnAtom);
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	var strScrollName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("ScrollName");
	
	if (null == heAtom)
	{
		return;
	}

	var xnDispAttrib = XmlLib.selectSingleNode(xnAtom, "DisplayAttrib");
	if (null == xnDispAttrib)
	{
		return;
	}

	// "Y"이면 비활성화이다.
	var bDisable = "Y" == xnDispAttrib.getAttribute("Disabled"); 
	
	var strAtomType = xnAtom.nodeName
	if ("InputData" == strAtomType)
	{
		heAtom.readOnly = bDisable;
	}
	else if ("Combo" == strAtomType)
	{
		var objAtom = Model.getAtom(strVarName, strScrollName, heAtom);
		if (null != objAtom)
		{
			objAtom.setDisabled(bDisable);
		}
	}
	else if ("Button" == strAtomType)
	{
		var objAtom = ButtonAtom.getAtom(strVarName);
		if (null != objAtom)
		{
			objAtom.setDisabled(bDisable);
		} 
	}
	else if ("WebDHtmlEditAtom" == strAtomType)
	{
		WebDHtmlEditAtom.getAtom(strVarName).setDisabled(bDisable);
	}
	else
	{
		heAtom.disabled = bDisable;
	}
}

PQScript.prototype._handleReadonlyAttribute = function (xnAtom)
{
	var heAtom = this._getAtomHTML(xnAtom);
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	
	if (null == heAtom)
	{
		return;
	}
			
	var xnInputAttrib = XmlLib.selectSingleNode(xnAtom, "InputAttrib");
	if (null == xnInputAttrib)
	{
		return;
	}
	
	// "Y"이면 비활성화이다.
	var bReadonly = ("Y" == xnInputAttrib.getAttribute("Readonly")) ? true : false; 
	
	var strAtomType = xnAtom.nodeName
	if ("InputData" == strAtomType)
	{
		heAtom.readOnly = bReadonly;
	}
}


PQScript.prototype._handleBGColorAttribute = function (xnAtom)
{
	var heAtom = this._getAtomHTML(xnAtom);
	var xnBGAttrib = XmlLib.selectSingleNode(xnAtom, "BackgroundAttrib");
	if (null != heAtom && null != xnBGAttrib && heAtom.fillcolor)
	{
		var strColor = xnBGAttrib.text;
		heAtom.fillcolor = strColor;
	}
}

/**
 * 초점주기, 초점주기는 Action이지만 Applet에서 처리 할 수 없으므로 Attribute와 같이 처리 한다.
 */ 
PQScript.prototype._handleFocus = function (xnAtom)
{
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	var objAtom = Model.getAtom(strVarName);

	if (null == objAtom)
	{
		return;
	}
	
	var strAtomType = xnAtom.nodeName;
	
	// 콤보일때는 콤보헤더의 Edit영역에 Focus를 준다.
	if ("Combo" == strAtomType || "InputData" == strAtomType)
	{
		if(objAtom.isFocusable())
		{
			objAtom.setFocus();
		}
	}
	else
	{
		var heAtom = this._getAtomHTML(xnAtom);
		
		// 사용 가능 할 때만
		if (heAtom && !heAtom.disabled)
		{
			heAtom.focus();
		}
	}
}

/**
 * 화면감춤 속성 처리
 */
PQScript.prototype._handleVisibleAttribute = function (xnAtom)
{
	var heAtom = this._getAtomHTML(xnAtom);
	if (!heAtom)
	{
		return;
	}
	
	var xnDispAttrib = XmlLib.selectSingleNode(xnAtom, "DisplayAttrib");
	if (!xnDispAttrib)
	{
		return;
	}
	
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	var bHidden = "true" == xnDispAttrib.getAttribute("Hidden");
	
	// 화면감춤 속성이 true이면 감춘다.
	if (bHidden)
	{
		heAtom.style.visibility = "hidden";
		
		// 콤보아톰일 때는 OPTION LIST도 hidden시켜야 하므로, body에서 찾아 속성을 바꾼다.
		if ("Combo" == xnAtom.nodeName)
		{
			var heComboBody = document.getElementById("__COMBO_BODY_" + strVarName);
			if (heComboBody)
			{
				heComboBody.style.visibility = "hidden";
			}
		}
		else if ("InputTime" == xnAtom.nodeName)
		{
			heAtom.style.display = "none";
		}
	}
	else
	{
		if ("Button" == xnAtom.nodeName)
		{
			var objAtom = ButtonAtom.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.setVisible();
			}
		}
		else
		{
			heAtom.style.visibility = "visible";
			
			// 콤보아톰일 때는 OPTION LIST도 hidden시켜야 하므로, body에서 찾아 속성을 바꾼다.
			if ("Combo" == xnAtom.nodeName)
			{
				// 단순형일 경우만 바디를 보이게 한다.
				if (null != heAtom.nextSibling && -1 < heAtom.nextSibling.id.indexOf("__COMBO_BODY_"))
				{
					var heComboBody = document.getElementById("__COMBO_BODY_" + strVarName);
					if (null != heComboBody)
					{
						heComboBody.style.visibility = "visible";
					}
				}
			}
			else if ("InputTime" == xnAtom.nodeName)
			{
				heAtom.style.display = "block";
			}
		}
	}
}

/**
 * 높이 속성 처리
 */
PQScript.prototype._handleHeightAttribute = function (xnAtom)
{
	var xnDispAttrib = XmlLib.selectSingleNode(xnAtom, "DisplayAttrib");
	if (!xnDispAttrib)
	{
		return;
	}
	var strHeight = xnDispAttrib.getAttribute("Height");
	
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	var objAtom = Model.getAtom(strVarName);
	if (null != objAtom)
	{
		objAtom.resizeHeight(parseInt(strHeight));
	}
}

/**
 * 너비 속성 처리
 */
PQScript.prototype._handleWidthAttribute = function (xnAtom)
{
	var xnDispAttrib = XmlLib.selectSingleNode(xnAtom, "DisplayAttrib");
	if (!xnDispAttrib)
	{
		return;
	}
	var strWidth = xnDispAttrib.getAttribute("Width");
	
	var strVarName = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib").getAttribute("VarName");
	var objAtom = Model.getAtom(strVarName);
	if (null != objAtom)
	{
		objAtom.resizeWidth(parseInt(strWidth));
	}
}

PQScript.prototype._handleFontAttribute = function (xnAtom)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	
	var xnFont = XmlLib.selectSingleNode(xnAtom, "./Font");
	var objAtom = null;
	if ("RectangleAtom" == strAtomType)
	{
		objAtom = RectangleAtom.getAtom(strVarName);
	}
	else if ("InputData" == strAtomType)
	{
		objAtom = InputDataAtom.getAtom(strVarName);
	}
	
	if (null != objAtom)
	{
		var strSize = xnFont.getAttribute("Size");
		if (null != strSize && 0 < strSize.length)
		{
			objAtom.setFont("Size", Number(strSize));
		}
		
		var strBold = xnFont.getAttribute("Bold");
		if (null != strBold && 0 < strBold.length)
		{
			objAtom.setFont("Bold", "true" == strBold);
		}
		
		var strItalic = xnFont.getAttribute("Italic");
		if (null != strItalic && 0 < strItalic.length)
		{
			objAtom.setFont("Italic", "true" == strItalic);
		}
		
		var strUnderLine = xnFont.getAttribute("UnderLine");
		if (null != strUnderLine && 0 < strUnderLine.length)
		{
			objAtom.setFont("UnderLine", "true" == strUnderLine);
		}
		
		var strStrikeOut = xnFont.getAttribute("StrikeOut");
		if (null != strStrikeOut && 0 < strStrikeOut.length)
		{
			objAtom.setFont("StrikeOut", "true" == strStrikeOut);
		}
		
		var strFamily = xnFont.getAttribute("Family");
		if (null != strFamily && 0 < strFamily.length)
		{
			objAtom.setFont("Family", strFamily);
		}
		
		var strColor = xnFont.getAttribute("Color");
		if (null != strColor && 0 < strColor.length)
		{
			objAtom.setFont("Color", strColor);
		}
	}
}

PQScript.prototype._handleSelectRowAttribute = function (xnAtom)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	var objAtom = null;
	if ("Combo" == strAtomType)
	{
		objAtom = ComboAtom.getAtom(strVarName);
		if (null != objAtom)
		{
			var xnComboAttribNode = XmlLib.selectSingleNode(xnAtom, "ComboAttrib");
			if (null != xnComboAttribNode)
			{
				var nIndex = parseInt(xnComboAttribNode.getAttribute("SelectRow"));
				if (!isNaN(nIndex))
				{
					objAtom.selectRow(nIndex);
				}
			}
		}
	}
	else if ("GanttChart" == strAtomType)
	{
		objAtom = Model.getAtom(strVarName);
		if (null != objAtom)
		{
			var xnGanttAttribNode = XmlLib.selectSingleNode(xnAtom, "GanttAttrib");
			if (null != xnGanttAttribNode)
			{
				var nIndex = parseInt(xnGanttAttribNode.getAttribute("SelectIndex"));
				if (!isNaN(nIndex))
				{
					objAtom.setSelectIndex(nIndex);
				}
			}
		}
	}
}

/**
 * 참조아톰 스크립트 처리
 */
PQScript.prototype._handleReferenceAtomAttribute = function (xnAtom)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var objAtom = Model.getAtom(strVarName);
	
	if (null != objAtom)
	{
		var strRefVarName = xnRefAtt.getAttribute("RefVarName");
		
		objAtom.setRefVarName(strRefVarName);
	}
}

/**
 * 실행모델명 스크립트 처리
 */
PQScript.prototype._handleExcuteModelNameAttribute = function (xnAtom)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	
	var objAtom = null;
	if ("Button" == strAtomType)
	{
		objAtom = ButtonAtom.getAtom(strVarName);
	}
	else if ("ReportBrowse" == strAtomType)
	{
		objAtom = ReportBrowseAtom.getAtom(strVarName);
	}
	else if ("Popup" == strAtomType)
	{
		//objAtom = PopupAtom.getAtom(strVarName);
	}
	else if ("WebBoard" == strAtomType)
	{
		objAtom = WebBoardAtom.getAtom(strVarName);
	}
	
	if (null != objAtom)
	{
		var strModelName = xnRefAtt.getAttribute("ModelName");
		
		objAtom.setConnectionModelName(strModelName);				
	}
}

/**
 * 확장 그리드 아톰의 스크립트를 처리한다.
 */
PQScript.prototype._handleGridExAttribute = function (xnAtom, strAttributeID)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	
	var objAtom = null;
	if ("GridEx" == strAtomType)
	{
		objAtom = GridExAtom.getAtom(strVarName);
	}
	
	if (null != objAtom)
	{
		if ("521" == strAttributeID)	// 자동 열길이 조정
		{
			var xnGridAttr = XmlLib.selectSingleNode(xnAtom, "./GridExAttrib");
			var nColumn = xnGridAttr.getAttribute("AutoLength");
			
			objAtom.doColumnAutoLength(parseInt(nColumn));
		}
	}
}

/**
 * 트리 아톰의 스크립트를 처리한다.
 */
PQScript.prototype._handleTreeAttribute = function (xnAtom, strAttributeID)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	
	var objAtom = null;
	if ("Tree" == strAtomType)
	{
		objAtom = TreeAtom.getAtom(strVarName);
	}
	
	if (null != objAtom)
	{
		if ("475" == strAttributeID)	// 트리전개
		{
			var xnGridAttr = XmlLib.selectSingleNode(xnAtom, "./TreeAttrib");
			var strAttr = xnGridAttr.getAttribute("TreeExpand");
			
			objAtom.expandNode(strAttr);
		}
	}
}

/**
 * 발신자명의 아톰의 스크립트를 처리한다.
 */
PQScript.prototype._handleSenderAtomAttribute = function (xnAtom, strAttributeId)
{
	var xnRefAtt = XmlLib.selectSingleNode(xnAtom, "./ReferenceAttrib");
	var strVarName = xnRefAtt.getAttribute("VarName");
	var objAtom = SenderAtom.getAtom(strVarName);
	if (null != objAtom)
	{
		var xnSenderAttribNode = XmlLib.selectSingleNode(xnAtom, "SenderAttrib");
		if (null != xnSenderAttribNode)
		{
			var strValue = "";
			switch (strAttributeId)
			{
				case "712":
				{
					strValue = xnSenderAttribNode.getAttribute("SenderName");
					objAtom.setSenderName(strValue);
					break;
				}
				case "714":
				{
					strValue = xnSenderAttribNode.getAttribute("SealCode");
					objAtom.setSealCode(strValue);
					break;
				}
				case "715":
				{
					strValue = xnSenderAttribNode.getAttribute("SealAttrib");
					var nSealAttrib = parseInt(strValue);
					if (!isNaN(nSealAttrib))
					{
						objAtom.setSealAttrib(nSealAttrib);
					}
					break;
				}
				default:
				{
					break;
				}
			}
		}
	}
}

PQScript.prototype._getAtomHTML = function (xnAtom)
{		
	var xnReferAttrib = XmlLib.selectSingleNode(xnAtom, "ReferenceAttrib");
	var strVarName = xnReferAttrib.getAttribute("VarName");
	var strAtomType = xnAtom.nodeName;
	
	var strScrollName = xnReferAttrib.getAttribute("ScrollName");
	var strRowIndex = xnReferAttrib.getAttribute("ScrollRowIndex");
	var objAtom = null;
	
	if (strScrollName && strRowIndex)
	{
		objAtom = this._getScrollBindAtomObject(strVarName, strScrollName, strRowIndex);
	}
	else
	{
		objAtom = Model.getAtom(strVarName);
	}
	
	return null == objAtom ? null : objAtom.getHTML();
}

PQScript.prototype._getScrollBindAtomObject = function (strVarName, strScrollName, strRowIndex)
{
	var objAtom = null;
	var objScroll = ScrollAtom.getAtom(strScrollName);
	if (null == objScroll)
	{
		return null;
	}
	
	return objScroll.getBindedAtom(strVarName, parseInt(strRowIndex));
}


/**
 * 스크립트 동작.
 */
PQScript.SCRIPT_ACTION = "ScriptAction";
PQScript.INCLUDE_BEFORE_ACTION = true;
PQScript.EXCLUDE_BEFORE_ACTION = false;

PQScript.init = function ()
{
	g_objPQScript = new PQScript();
	// PQ스크립트 함수 테이블을 만드는 전역함수를 호출한다.
	MakePQScriptFunctionTable();
}

/**
 * 부모 윈도우를 setting한다.
 */
PQScript.setParent = function (objParentWnd)
{
	g_objParentWnd = objParentWnd;
}

/**
 * 스크립트를 실행한다.
 */
PQScript.execute = function (nScriptIndex, nEventID, arParam)
{
	// PQScript 자체가 없다면 껍데기이기 때문에 모든 동작을 취소하기 위해, 여기서 -1을 리턴한다.
	if (null == g_objPQScript)
	{
		return -1;
	}
	
	// 진행관리자 전처리 이벤트가 있으면 전처리 + 스크립트을 실행한다.
	if (PQProcessInfo.haveBeforeAction(nScriptIndex, nEventID))
	{
		if (null != g_objPQScript)
		{
			var objReturn = g_objPQScript.execute(nScriptIndex, nEventID, arParam, PQScript.INCLUDE_BEFORE_ACTION);
			
			return objReturn;
		}
	}
	// 진행관리자 전처리가 없으면, 스크리트 유무에 따라 스크립트를 실행하거나 종료한다.
	else
	{
		if(PQScript.findFunction(nScriptIndex, nEventID))
		{
			if (null != g_objPQScript)
			{
				var objReturn = g_objPQScript.execute(nScriptIndex, nEventID, arParam, PQScript.EXCLUDE_BEFORE_ACTION);
				
				return objReturn;
			}
		}
	}
}

/**
 * 프로그램 진행 관리자의 후처리를  실행한다.
 */
PQScript.executeProcessManagerAfterAction = function (nScriptIndex, nEventID, arParam)
{
	if (PQProcessInfo.haveAfterAction(nScriptIndex, nEventID))
	{
		if (null != g_objPQScript)
		{
			return g_objPQScript.executeProcessManagerAfterAction(nScriptIndex, nEventID, arParam);
		}
	}
}

/**
 * 자식폼을 띄운다.
 * 상세폼열기 기능을 이용해서 자식폼을 열 때 사용한다.
 * @param strPath 자식폼 이름(경로포함).
 */
PQScript.createChildForm = function (strPath)
{
	if (null != g_objPQScript)
	{
		return g_objPQScript.createChildForm(strPath);
	}
}


PQScript.setScriptAttribute = function (strVarName, strAttributeName, strValue)
{
	if (null != g_objPQScript)
	{
		g_objPQScript.setScriptAttribute(strVarName, strAttributeName, strValue);
	}
}

var MyChildWindow = null;

/**
 * [객체생성:폼]이 발생하여 자식 윈도우를 오픈 한다.
 * 자식폼의 load가 완료될때 까지 대기하는 것이 특징이다.
 * 이 함수 호출 후에는 반드시 PQScript.executeFormLoadScript()를 호출해야 한다.
 */
PQScript.openChildWindow = function ()
{
	var strModelName = Utils.removePQPath(Utils.getPathString(arguments[0]));
	PQScript.setChildModelName(strModelName);
	PQScript.setOpenChildModel(true);
	
	// 문서모델일 경우에는 프로젝트명을 붙이지 않습니다.
	if (false == PQConnectionModel.getChildModelUseDmt() && 0 < strModelName.indexOf("."))
	{ 
		strModelName = GetProjectName() + "/" + strModelName; 
	}
	
	//객체생성 스크립트는 웹페이지 모델에서는 동작하지 않으므로 애플릿에서 프로젝트명을 가져옵니다.
	MyChildWindow = Utils.openWindow("/ups/Model.html?ModelName=" + strModelName, 1);

	while (false == PQScript.isChildWindowReady())
	{
		PQService.pause(50);
	}

	// 자식 윈도우를 setting한다.
	g_alChildWnd[g_alChildWnd.length] = MyChildWindow;
	
	// 자식 윈도우의 부모에 현재 윈도우를 setting한다.
	var objChildModel = MyChildWindow.frames["__PQModel_Frame"];
	objChildModel.PQScript.setParent(window.parent);
	
	// 자식폼을 제일 위로 올리기 위해서...
	MyChildWindow.focus();
}

/**
 * 출력물 자식폼 윈도우를 생성한다.
 */
PQScript.openReportWindow = function ()
{
	var strModelName = Utils.removePQPath(Utils.getPathString(arguments[0]));
	PQScript.setChildModelName(strModelName);
	PQScript.setOpenChildModel(true);
	
	//객체생성 스크립트는 웹페이지 모델에서는 동작하지 않으므로 애플릿에서 프로젝트명을 가져옵니다.
	Utils.openWindow("/ups/Report.html?ModelName=" + PQService.getProjectName() + "/" + strModelName, 1);
}


/**
 * [객체생성:폼]이 발생하여 자식 윈도우를 오픈한 후 호출되는 함수임.
 * 폼열림 스크립트를 실행한다.
 */
PQScript.executeFormLoadScript = function ()
{
	// 자식폼을 여는 일련의 작업 Model.html윈도우 생성 -> 자식 load완료 대기후
	// 자식 폼의 load가 완료 되면 여러 플래그들을 원상 복귀 시킨다.
	PQScript.setChildModelName("");
	PQScript.setOpenChildModel(false);
	g_bCurrentChildLoaded = false;
	
	var objModelWindow = MyChildWindow.frames["__PQModel_Frame"];
	
	//자식폼의 HTML의 로드가 완료되면 폼_호출확인, 폼_열림 스크립트를 발생시킨다.
	objModelWindow.PQScript.formLoadScript();
	
	// 객체생성으로 열림 폼의 MakeRequest를 수행한다.
	if (null != objModelWindow && !objModelWindow.closed)
	{
		objModelWindow.PQService.scriptMakeRequest(objModelWindow.PQScript.makeRequest())
	}
	
	MyChildWindow = null;
}


PQScript.makeRequest = function ()
{	
	var xnRequest = MakeRequest.createRequestNode();
	GlobalField.setServiceName(PQScript.SCRIPT_ACTION);
	MakeRequest.makeServiceRequest(xnRequest);
	MakeRequest.makeAtomRequest(xnRequest);

	return XmlLib.serializeToString(xnRequest.ownerDocument);
}


PQScript.handleResult = function (strResult)
{
	var xnResultDoc = XmlLib.loadXMLFromString(strResult);
	var xnResult = HandleResult.getResultNode(xnResultDoc);
	
	g_objPQScript.handleResult(xnResult);
}


/**
 * 관계된 폼(부모폼, 자식폼)의 MakeRequest를 한다.
 */
PQScript.makeRequestForRelationWindow = function ()
{
	// 폼이 존재하고 폼이 닫혀있지 않아야한다.
	// 중간에 닫히거나 강제종료되면 Window.closed는 True이다.
	if (null != g_objParentWnd && !g_objParentWnd.closed)
	{
		var objParentModelWindow = g_objParentWnd.frames["__PQModel_Frame"];
		objParentModelWindow.PQService.scriptMakeRequest(objParentModelWindow.PQScript.makeRequest());
	}
	
	var objChildModelWindow = null;
	for (var i=0; i<g_alChildWnd.length; i=i+1)
	{
		// 폼이 존재하고 폼이 닫혀있지 않아야한다.
		// 중간에 닫히거나 강제종료되면 Window.closed는 True이다.
		if (null != g_alChildWnd[i] && !g_alChildWnd[i].closed)
		{
			objChildModelWindow = g_alChildWnd[i].frames["__PQModel_Frame"];
			objChildModelWindow.PQService.scriptMakeRequest(objChildModelWindow.PQScript.makeRequest());
		}
	}	
}

/**
 * 관계된 폼(부모폼, 자식폼)의 HandleResult를 한다.
 */
PQScript.handleResultForRelationWindow = function ()
{
	// 폼이 존재하고 폼이 닫혀있지 않아야한다.
	// 중간에 닫히거나 강제종료되면 Window.closed는 True이다.
	if (null != g_objParentWnd && !g_objParentWnd.closed)
	{
		var objParentModelWindow = g_objParentWnd.frames["__PQModel_Frame"];
		objParentModelWindow.PQService.scriptHandleResult();
	}
	
	var objChildModelWindow = null;
	for (var i=0; i<g_alChildWnd.length; i=i+1)
	{	
		// 폼이 존재하고 폼이 닫혀있지 않아야한다.
		// 중간에 닫히거나 강제종료되면 Window.closed는 True이다.
		if (null != g_alChildWnd[i] && !g_alChildWnd[i].closed)
		{
			objChildModelWindow = g_alChildWnd[i].frames["__PQModel_Frame"];
			objChildModelWindow.PQService.scriptHandleResult();
		}
	}
}

/**
 * 버튼.상세폼열기() 실행.
 * @param strVarName 버튼 아톰명.
 * @param strRefVarName 참조변수명.
 * @param strModelName 연결모델명.
 */
PQScript.executeConnectionModel = function (strVarName, strRefVarName, strModelName)
{
	if (ContainsButtonAtom())
	{
		ButtonAtom.executeConnectionModel(strVarName, strRefVarName, strModelName);
	}
}

/**
 * 버튼.닫기() 또는 폼.닫기() 실행.
 * @param strVarName 버튼 아톰명.
 */
PQScript.executeFormClose = function (strVarName)
{
	if (ContainsButtonAtom() && null != strVarName && 0 < strVarName.length)
	{
		ButtonAtom.executeFormClose(strVarName);
	}
	else
	{
		Utils.close();
	}
}

PQScript.formLoadScript = function ()
{
	ScriptFormEvent.onSetParent();
	ScriptFormEvent.onLoad();
}


var g_bOpenChildModel = false;
PQScript.isOpenChildModel = function ()
{
	return g_bOpenChildModel;
}


PQScript.setOpenChildModel = function (bOpenChildModel)
{
	g_bOpenChildModel = bOpenChildModel;
}


var g_strChildModelName = "";
PQScript.getChildModelName = function ()
{
	return g_strChildModelName;
}


PQScript.setChildModelName = function (strChildModelName)
{
	g_strChildModelName = strChildModelName;
}


PQScript.isChildWindowReady = function ()
{
	return g_bCurrentChildLoaded;
}


/**
 * 부모 폼에게 자신의 로드가 끝났다는 것을 알립니다.
 */
PQScript.modelLoadInform = function ()
{
	var parentWindow = window.top.opener;
	if (null == parentWindow)
	{
		return;
	}
	parentWindow.PQScript.setChildReady();
}


/**
 * 현재 띄우고 있는 자식폼의 로딩 상태를 완료로 바꿉니다.
 * TODO : 동시에 여러 자식모델이 꼬이면 안됨 수정 해야함
 */
PQScript.setChildReady = function ()
{
	g_bCurrentChildLoaded = true;
}

/**
 * PQ스크립트 함수 테이블을 set한다.
 */
PQScript.setFunctionTable = function (htFunctionTable)
{
	g_objPQScript.setFunctionTable(htFunctionTable);
}

/*
 * 스크립트 함수가 있는지 찾는다.
 * 
 * @param nScriptIndex 아톰의 스크립트 인덱스
 * @param nEventID 발생한 이벤트 ID (BOS에서 정의)
 * @return 찾으면 true, 못찾으면 false
 */
PQScript.findFunction = function (nScriptIndex, nEventID)
{
	if (null != g_objPQScript)
	{
		var strMessage = "";
		
		// EVS_TYPE.EVS_F_LOAD = 34;
		// EVS_TYPE.EVS_F_DOC_MASTER = 44;
		if (34 <= nEventID && 44 >= nEventID) // 폼 메세지 호출
		{
			strMessage = "IM" + nEventID;
		}
		else
		{
			strMessage = nScriptIndex + "_" + nEventID;
		}
		
		return g_objPQScript.findFunction(strMessage);
	}
	else
	{
		return false;
	}
}

/**
 * 외부개체연결 아톰의 함수를 호출한다.
 */
PQScript.callOcx = function (arArgs)
{
	if (ContainsOcxAtom())
	{
		OcxAtom.call(arArgs);
	}
}

//============================================================================
//============================================================================

function ScriptEvent ()
{
}

ScriptEvent.SEARCH_END = 1153;
ScriptEvent.PREV_SEARCH_END = 1154;
ScriptEvent.NEXT_SEARCH_END = 1155;

ScriptEvent.SEARCH_SUCCEED = 1;
ScriptEvent.SEARCH_NORESULT = 0;
ScriptEvent.SEARCH_FAILED = -1;

ScriptEvent.makeParameter = function ()
{
	var arParam = new Array();
		
	for (var i = 0; i < arguments.length; i++)
	{
		arParam.push(arguments[i]);
	}
	
	return arParam;
}

/**
 * 스크립트 폼 메시지
 */
function ScriptFormEvent ()
{
}

/**
 * 폼_열림
 * Event ID : 34
 */
ScriptFormEvent.onLoad = function ()
{
	PQScript.execute(-1, 34, null);
}

/**
 * 폼_닫힘
 * Event ID : 35
 */
ScriptFormEvent.onUnload = function ()
{
	PQScript.execute(-1, 35, null);
}

/**
 * 폼_호출확인
 * Event ID : 37
 */
ScriptFormEvent.onSetParent = function ()
{
	PQScript.execute(-1, 37, null);
}

/**
 * 폼_메뉴선택
 * Event ID : 38
 * 
 * 매개변수 
 * (정수) 선택인덱스
 */
ScriptFormEvent.onFormMenuSelect = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[0]);
	PQScript.execute(-1, 38, arParam);
}

/**
 * 폼_저장결과
 * Event ID: 40
 * 매개변수
 * 	(진위수) 저장결과 : 성공 = 1
 */
ScriptFormEvent.onResultSave = function (nSuccess)
{
	var arParam = ScriptEvent.makeParameter(nSuccess ? 1 : 0); 

	PQScript.execute(-1, 40, arParam);
}

/**
 * 폼_저장완료
 * Event ID : 41
 * 
 * 매개변수
 * 	(진위수) 저장결과
 */
ScriptFormEvent.onEndSave = function ()
{
	var arParam = ScriptEvent.makeParameter(1); 

	PQScript.execute(-1, 41, arParam);
}

/**
 * 폼_검색완료
 * Event ID : 42
 *
 * 매개변수
 * 	(정수) 검색유형 : #지금, #이전, #다음
 * 	(정수) 검색결과 : 1-검색성공, 0-검색결과없음, -1-검색실패
 * 	(정수) 탭뷰인덱스 : 탭뷰가 있을 경우 검색완료후 작업할 탭뷰의 인덱스
 */
ScriptFormEvent.onEndSearch = function ()
{
	// TODO 조영운 검색결과, 탭뷰인덱스 매겨변수 구현 안됨
	// TODO 조영운 일반 문서 열릴 때 폼_검색완료 스크립트 실행 안됨
	var arParam = ScriptEvent.makeParameter(arguments[0], arguments[1], 0);
	
	PQScript.execute(-1, 42, arParam);
}

/**
 * 폼_문서대장
 * Event ID : 44
 * 
 * 매개변수
 *  (정수) 키값 : 1300 #결재시작, 1301 #결재완료, 1326 #결재처리, 1341 #결재완료전 
 *  (문자열) 데이터값 : 문서등록번호
 */
ScriptFormEvent.onNtoaMasterDialog = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[0], arguments[1]);
	
	PQScript.execute(-1, 44, arParam);
}

/**
 * 스크립트 아톰 메시지
 */
function ScriptAtomEvent ()
{
}

/**
 * _메뉴선택 (선택인덱스), (선택행, 변수명, 선택인덱스)
 * Event ID : 51
 */
ScriptAtomEvent.onMenuSelect = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		// 일반 입력란
		case 2 : arParam = ScriptEvent.makeParameter(arguments[1]);
				 break;
		
		// 스크롤에 묶인 입력란
		case 4 : arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], arguments[3]);
				 break;
	}
	
	return PQScript.execute(arguments[0], 51, arParam);
}

/**
 * _메뉴선택 - 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onMenuSelectAfter = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		// 일반 입력란
		case 2 : arParam = ScriptEvent.makeParameter(arguments[1]);
				 break;
		
		// 스크롤에 묶인 입력란
		case 4 : arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], arguments[3]);
				 break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 51, arParam);
}
 
/**
 * _누름
 * Event ID : 53
 * 
 * 해당아톰
 * 	검색창, 결재표시란, 콤보, 날짜입력란, 이미지입력란, 통합문서, 데이터입력란, 라디오버튼, 체크박스 ()
 * 	그리드 (행, 열) (X)
 * 	트리 (아이템) (X)
 * 	스크롤 (행, 변수명)
 *	간트차트 (선택인덱스)
 * 매개변수
 * 	(정수) 행 : 그리드의 행번호
 * 	(정수) 열 : 그리드의 열번호
 * 	(문자열) 변수명 : 스크롤에 묶인 입력란의 변수명
 * 	(정수) 아이템 : 트리의 아이템 핸들
 *  (정수) 선택인덱스 : 간트차트중 선택된 차트막대(선택영역)의 인덱스
 *
 *  인자의 Type을 판별 하기 위해서 arParam의 첫번재 인자는 Parameter의 Type을 계산한 값이다.
 *  0: Int,  1: Double,  2: String
 *  자리수 별로 3의 n승의 값을 곱한후, 모두 더한다.
 *  
 * 만약 인자가 Int, String, Double이라면
 * (3^2 * 0) + (3^1 * 2) + (3^0 * 1) 
 */
ScriptAtomEvent.onClick = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
		case 4 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], arguments[3]);
			break;
		case 5 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], arguments[3], arguments[4]);
			break;
	}
	
	return PQScript.execute(arguments[0], 53, arParam);
}

/**
 * 누름 - 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onClickAfter = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 53, arParam);
}

/**
 * _두번누름
 * Event ID : 54
 *
 * 해당아톰
 * 	검색창, 결재표시란, 콤보박스, 날짜입력란, 이미지입력란, 통합문서, 기능버튼, 데이터입력란, 라디오버튼, 체크박스 ()
 * 	그리드 (행, 열) (X)
 * 	트리 (아이템) (X)
 * 	스크롤 (행, 변수명)
 *  간트차트 (선택인덱스)
 *
 * 매개변수
 * 	(정수) 행 : 그리드의 행번호
 * 	(정수) 열 : 그리드의 열번호 
 * 	(문자열) 변수명 : 스크롤에 묶인 입력란의 변수명
 * 	(정수) 아이템 : 트리의 아이템 핸들
 */
ScriptAtomEvent.onDblClick = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.execute(arguments[0], 54, arParam);
}

/**
 * 두번누름 - 프로그램 진행 관리자 후처리.
 */
ScriptAtomEvent.onDblClickAfter = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 54, arParam);
}

/**
 * _초점얻음
 * Event ID : 55
 *
 * 해당아톰
 * 	기능버튼, 체크박스, 콤보박스, 날짜입력란, 데이터입력란 ()
 * 	그리드 (행, 열) (X)
 * 	스크롤 (행번호, 변수명)
 *
 * 매개변수
 * 	(정수) 행번호 : 스크롤의 행번호
 * 	(문자열) 변수명 : 초점을 얻은 아톰의 고유변수명 
 * 	(정수) 행 : 그리드의 행번호
 * 	(정수) 열 : 그리드의 열번호 
 * 	(정수) 아이템 : 트리의 아이템 핸들
 */
ScriptAtomEvent.onFocus = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.execute(arguments[0], 55, arParam);
}

/**
 * _초점얻음 - 프로그램 진행 관리자 후처리 담당.
 */
ScriptAtomEvent.onFocusAfter = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 55, arParam);
}

/**
 * _초점상실
 * Event ID : 56
 *
 * 해당아톰
 * 	입력란 ()
 * 	스크롤 (행번호, 변수명)
 *
 * 매개변수
 * 	(정수) 행번호 : 스크롤의 행번호
 * 	(문자열) 변수명 : 초점을 읽은 아톰의 고유변수명
 */
ScriptAtomEvent.onBlur = function ()
{
	var arParam = null;
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.execute(arguments[0], 56, arParam);
}

/**
 * _초점상실 ScriptAtomEvent.onBlurAfter()의 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onBlurAfter = function ()
{
	var arParam = null;
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 56, arParam);
}

/**
 * _마우스위
 * Event ID : 57
 */
ScriptAtomEvent.onMouseOver = function ()
{
	return PQScript.execute(arguments[0], 57, null);
}

/**
 * _마우스위 ScriptAtomEvent.onMouseOver()의 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onMouseOverAfter = function ()
{
	return PQScript.executeProcessManagerAfterAction(arguments[0], 57, null);
}

/**
 * _저장결과
 * Event ID; 59
 *
 * 해당아톰
 * 	결재기능버튼에서 결재를 제외한 모든 기능에서 버튼 동작후 발생
 *
 * 매개변수
 * 	(불리안) 버튼 동작 결과
 */
ScriptAtomEvent.onSaveResult = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.execute(arguments[0], 59, arParam);
}

/**
 * _키누름
 */
ScriptAtomEvent.onKeyDown = function ()
{

}


/**
 * _입력마침
 * Event ID : 63
 *
 * 해당아톰
 * 	간트차트 (선택인덱스)
 *
 * 매개변수
 *	(정수) 선택인덱스 : 현재 선택된 차트 인덱스 
 */
ScriptAtomEvent.onInputCompletion = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.execute(arguments[0], 63, arParam);
}

ScriptAtomEvent.onInputCompletionAfter = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 63, arParam);
}

/**
 * _탭이동
 * Event ID : 64
 *
 * 해당아톰
 * 	콤보박스, 날짜입력란, 데이터입력란, 라디오버튼, 트리, 체크박스, 그리드 (탭번호, 탭이동유형)
 *
 * 매개변수
 *	(정수) 탭번호 : 팝업에 묶여 있는 경우 다음에 이동할 아톰의 탭번호
 * 	(정수) 탭이동유형 : 1-다음 탭번호로 이동, 1-이전 탭번호로 이동
 */
ScriptAtomEvent.onMoveTab = function ()
{
	var arParam = null;
	
	// 매개변수들 정보를 만들고 있지만 탭뷰 구현부분에서 스크립트 호출시 인자 넘기지 않고 있습니다.
	// TODO 차후에 Javascript단에서 탭번호와 탭이동유형 추가하여 이벤트발생시 인자넘겨야 함
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.execute(arguments[0], 64, arParam);
}

/**
 * ScriptAtomEvent.onMoveTab()의 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onMoveTabAfter = function ()
{
	var arParam = null;
	
	// 매개변수들 정보를 만들고 있지만 탭뷰 구현부분에서 스크립트 호출시 인자 넘기지 않고 있습니다.
	// TODO 차후에 Javascript단에서 탭번호와 탭이동유형 추가하여 이벤트발생시 인자넘겨야 함
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 64, arParam);
}

/**
 * _자동증가
 */
ScriptAtomEvent.onAutoInc = function ()
{
}

/**
 * _키값확인
 *
 * 해당아톰
 * 	데이터입력란 (문자, 문자코드)
 *
 * 매개변수
 * 	(문자열) 문자 : 눌려진 키
 * 	(문자열) 문자코드 : 눌려진 키의 아스키코드 값
 */
ScriptAtomEvent.onCheckKeyValue = function ()
{
	//인자가 2개 필요한 이벤트지만 
	//문자 인자는 백스페이스처럼 xml에 들어갈 수 없는 문자가 있기 때문 문자코드로 Java 단에서 만듭니다. 
	var nASCIICode = arguments[1].keyCode;
	
	var arParam = ScriptEvent.makeParameter(nASCIICode);
	
	return PQScript.execute(arguments[0], 71, arParam);
}

/**
 * ScriptAtomEvent.onCheckKeyValue()의 프로그램 진행 관리자의 후처리 담당.
 */
ScriptAtomEvent.onCheckKeyValueAfter = function ()
{
	var nASCIICode = arguments[1].keyCode;
	
	var arParam = ScriptEvent.makeParameter(nASCIICode);
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 71, arParam);
}

/**
 * _스크롤내이동
 * Event ID : 65
 *
 * 해당아톰
 * 	날짜입력란, 데이터입력란, 라디오버튼, 체크박스 (키값)
 *
 * 매개변수
 * 	(정수) 키값 : 1-Tav/Enter, 2-Shaft+Tab, 3-오른쪽, 4-왼쪽, 5-위, 6-아래
 */
ScriptAtomEvent.onMoveScroll = function ()
{
	var arParam = null;
	
	// 매개변수들 정보를 만들고 있지만 탭뷰 구현부분에서 스크립트 호출시 인자 넘기지 않고 있습니다.
	// TODO 차후에 Javascript단에서 키값 추가하여 이벤트발생시 인자넘겨야 함
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.execute(arguments[0], 65, arParam);
}

/**
 * _스크롤내이동 - 프로그램 진행 관리자 후처리.
 */
ScriptAtomEvent.onMoveScrollAfter = function ()
{
	var arParam = null;
	
	// 매개변수들 정보를 만들고 있지만 탭뷰 구현부분에서 스크립트 호출시 인자 넘기지 않고 있습니다.
	// TODO 차후에 Javascript단에서 키값 추가하여 이벤트발생시 인자넘겨야 함
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.executeProcessManagerAfterAction(arguments[0], 65, arParam);
}

/**
 * _문서선택
 */
ScriptAtomEvent.onSelectDocument = function ()
{
}

/**
 * _행추가
 * Event ID : 61
 *
 * 해당아톰
 * 	스크롤 (행번호)
 *
 * 매개변수
 * 	(정수) 행 : 스크롤의 행번호
 */
ScriptAtomEvent.onInsertRow = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[1]);
	
	return PQScript.execute(arguments[0], 61, arParam);
}

/**
 * _행삭제
 * Event ID : 62
 *
 * 해당아톰
 * 	스크롤 (행번호)
 *
 * 매개변수
 * 	(정수) 행 : 스크롤의 행번호
 */
ScriptAtomEvent.onDeleteRow = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[1]);
	
	return PQScript.execute(arguments[0], 62, arParam);
}

/**
 * _행삭제 - 프로그램 진행 관리자 후처리.
 */
ScriptAtomEvent.onDeleteRowAfter = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[1]);
	
	PQScript.executeProcessManagerAfterAction(arguments[0], 62, arParam);
}

/**
 * _탭뷰전환
 * Event ID : 67
 *
 * 해당아톰
 * 	탭뷰 (이전탭, 현재탭, 전후여부, 탭누름)
 *
 * 매개변수
 * 	(정수) 이전탭 : 전환 전 탭 번호
 * 	(정수) 현재탭 : 전환 후 탭 번호
 * 	(진위수) 전후여부 : 전환 전일 경우 참, 후일 경우 거짓
 *	(진위수) 탭누름 : 탭을 눌러서 전환한 경우 참, 그 외의 경우 저짓
 */
ScriptAtomEvent.onMoveTabView = function ()
{
	// TODO 조영운 전후여부, 탭누름 매개변수는 구현 안됨
	var arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], 1, 1);
	
	PQScript.execute(arguments[0], 67, arParam);
}

/**
 * _탭뷰전환 - 프로그램 진행 관리자 후처리.
 */
ScriptAtomEvent.onMoveTabViewAfter = function ()
{
	// TODO 조영운 전후여부, 탭누름 매개변수는 구현 안됨
	var arParam = ScriptEvent.makeParameter(arguments[1], arguments[2], 1, 1);
	
	PQScript.executeProcessManagerAfterAction(arguments[0], 67, arParam);
}

/**
 * _선택변경
 * Event ID : 52
 *
 * 해당아톰
 * 	검색창 ()
 * 	트리 ()
 * 	콤보박스 () 
 */
ScriptAtomEvent.onChangeSelect = function ()
{
	PQScript.execute(arguments[0], 52);
}

/**
 * _선택변경 - 프로그램 진행 관리자 후처리. 
 */
ScriptAtomEvent.onChangeSelectAfter = function ()
{
	PQScript.executeProcessManagerAfterAction(arguments[0], 52);
}

/**
 * _선택변경완료
 * Event ID : 83
 *
 * 해당아톰
 * 	검색창 ()
 *
 * (메시지함수 호출순서 : 누름->선택변경->선택변경완료)
 */
ScriptAtomEvent.onEndChangeSelect = function ()
{
	PQScript.execute(arguments[0], 83);
}

/**
 * _검색완료 - 프로그램 진행 관리자 후처리.
 */
ScriptAtomEvent.onEndSearchAfter = function ()
{
	PQScript.executeProcessManagerAfterAction(arguments[0], 80);
}

/**
 * _팝업동작
 * Event ID : 81
 *
 * 해당아톰
 * 	데이터입력란 () (X)
 * 	팝업묶기 (검색결과, 선택값)
 *
 * 매개변수
 * 	(진위수) 검색결과 : 데이터를 선택하고 팝업창을 닫으면 참, 데이터를 선택하지 않고 팝업창을 닫거나 취소버튼을 누르면 거짓입니다.
 * 	(문자열) 선택값 : 팝업에서 선택한 데이터값입니다.
 */
ScriptAtomEvent.onExecutePopup = function ()
{
	var arParam = null;
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	PQScript.execute(arguments[0], 81, arParam);
}

/**
 * _팝업동작 - 프로그램 진행관리자 후처리.
 */
ScriptAtomEvent.onExecutePopupAfter = function ()
{
	var arParam = null;
	switch (arguments.length)
	{
		case 3 :
			arParam = ScriptEvent.makeParameter(arguments[1], arguments[2]);
			break;
	}
	
	PQScript.executeProcessManagerAfterAction(arguments[0], 81, arParam);
}

// TODO 메뉴얼에 없는 스크립트 이벤트입니다.
/**
 * _팝업완료
 * Evnet ID : 85
 *
 * 해당아톰
 *
 * 매개변수
 */
/*ScriptAtomEvent.onEndPopup = function ()
{
	var arParam = ScriptEvent.makeParameter(arguments[1]);
	
	PQScript.execute(nScriptIndex, 85, arParam);
}*/


/**
 * _파일열림
 * Event ID : 74
 *
 * 매개변수
 * 	(문자열) 파일경로
 */
ScriptAtomEvent.onOpenFile = function ()
{
	var arParam = null;
	
	switch (arguments.length)
	{
		case 2 :
			arParam = ScriptEvent.makeParameter(arguments[1]);
			break;
	}
	
	return PQScript.execute(arguments[0], 74, arParam);
}

var g_objProcessInfo = new PQProcessInfo();

/**
 * 프로그램 진행관리자의 후처리에 관한 정보를 관리한다.<b>
 * 
 * 아래와 같은 정보를 같는 Hashtable을 관리한다.
 * Key    : 아톰의 ScriptIndex (String)
 * Object : 아톰의 Event별 후처리 존재 여부 (Hashtable) 
 */
function PQProcessInfo ()
{
	this.m_htBeforeActionTable = new Hashtable();
	this.m_htAfterActionTable = new Hashtable();
}


/**
 * 해당 아톰의 전처리 이벤트 정보를 넣는다.
 */
PQProcessInfo.prototype.addBeforeActionInfo = function (strScriptIndex, htBeforeActionInfo)
{
	this.m_htBeforeActionTable[strScriptIndex] = htBeforeActionInfo;
}

/**
 * 해당 아톰의 후처리 이벤트 정보를 넣는다.
 */
PQProcessInfo.prototype.addAfterActionInfo = function (strScriptIndex, htAfterActionInfo)
{
	this.m_htAfterActionTable[strScriptIndex] = htAfterActionInfo;
}

/**
 * 해당 아톰의 ScriptInde, 발생한 EventId를 가지고 전처리 이벤트가 있는지 판단한다.
 */
PQProcessInfo.prototype.haveBeforeAction = function (strScriptIndex, nEventId)
{
	var htBeforeActionInfo = this.m_htBeforeActionTable[strScriptIndex];
	if (null == htBeforeActionInfo)
	{
		return false;
	}
	
	var bHaveBeforeAction = htBeforeActionInfo[nEventId];
	if (null == bHaveBeforeAction)
	{
		return false;
	}
	
	if (true == bHaveBeforeAction)
	{
		return true;
	}
	else
	{
		return false;
	}	
}

/**
 * 해당 아톰의 ScriptInde, 발생한 EventId를 가지고 후처리 이벤트가 있는지 판단한다.
 */
PQProcessInfo.prototype.haveAfterAction = function (strScriptIndex, nEventId)
{
	var htAfterActionInfo = this.m_htAfterActionTable[strScriptIndex];
	if (null == htAfterActionInfo)
	{
		return false;
	}
	
	var bHaveAfterAction = htAfterActionInfo[nEventId];
	if (null == bHaveAfterAction)
	{
		return false;
	}
	
	if (true == bHaveAfterAction)
	{
		return true;
	}
	else
	{
		return false;
	}
}


///////////////////////////////////
// statsic method
//

/**
 * 해당 아톰의 전처리 이벤트 정보를 넣는다.
 */
PQProcessInfo.addBeforeActionInfo = function (strScriptIndex, htBeforeActionInfo)
{
	g_objProcessInfo.addBeforeActionInfo(strScriptIndex, htBeforeActionInfo);
}

/**
 * 해당 아톰의 후처리 이벤트 정보를 넣는다.
 */
PQProcessInfo.addAfterActionInfo = function (strScriptIndex, htAfterActionInfo)
{
	g_objProcessInfo.addAfterActionInfo(strScriptIndex, htAfterActionInfo);
}

/**
 * 해당 아톰의 ScriptIndex, 발생한 EventId를 가지고 전처리 이벤트가 있는지 판단한다.
 */
PQProcessInfo.haveBeforeAction = function (strScriptIndex, nEventId)
{
	return g_objProcessInfo.haveBeforeAction(strScriptIndex, nEventId);
}

/**
 * 해당 아톰의 ScriptIndex, 발생한 EventId를 가지고 후처리 이벤트가 있는지 판단한다.
 */
PQProcessInfo.haveAfterAction = function (strScriptIndex, nEventId)
{
	return g_objProcessInfo.haveAfterAction(strScriptIndex, nEventId);
}

PQProcessInfo.addPrePMInfo = function (nScriptIndex, objKey, arPMInfo)
{
	if (g_bQWPClientMode && null != g_objDoc)
	{
		g_objDoc.addPrePMInfo(nScriptIndex, objKey, arPMInfo);
	}
}

PQProcessInfo.addPostPMInfo = function (nScriptIndex, objKey, arPMInfo)
{
	if (g_bQWPClientMode && null != g_objDoc)
	{
		g_objDoc.addPostPMInfo(nScriptIndex, objKey, arPMInfo);
	}
}
