
function LightJDoc ()
{
	this.m_objFormExe = null;
	
	this.m_htSearchAtoms = new Hashtable();
	
	this.m_htPrePMInfos = new Hashtable();		// 전처리 스크립트 이벤트
	this.m_htPostPMInfos = new Hashtable();		// 후처리 스크립트 이벤트
	
	this.m_htPMVariable = new Hashtable();
	this.m_objExeScript = new ExeScript();
	
	this.m_htQueryResultDTS = new Hashtable();
	
	this.m_objKeyTranAtom = null;		// 배열로된 자동증가 쿼리 실행시, 기본검색키 아톰
}

LightJDoc.prototype.setFormExe = function (objFormExe)
{
	this.m_objFormExe = objFormExe;
}

/**
 * @return 자연어 스크립트인지 여부
 */
LightJDoc.prototype.isEBLSource = function ()
{
	return true;
}

LightJDoc.prototype.getRealIndex = function (nIndex)
{
	var nRealIndex = nIndex;

	if (this.isEBLSource() == true && 0 < nRealIndex)
	{
		nRealIndex -= 1;
	}

	return nRealIndex;
}

LightJDoc.prototype.getExeScript = function ()
{
	return this.m_objExeScript;
}

LightJDoc.prototype.onLoad = function (strModelName)
{
	g_objModelCore._checkEmbededModel();
	g_objModelCore._initWindowSize(strModelName);
	
	MakePQScriptObject();
	MakePQScriptVarInfo();
	
	g_objDoc.prepareScript();
	
	this._initGlobalTool();
	
	ModelCore.getPortalUserData();
	
	g_objModelCore._initAtom(); // 아톰 초기화
	
	g_objModel._initParentData();
	
	this.preExecute();
	
	this.directExecute();		// 검색계열 아톰 즉시 실행
	
	this.loadData(true, SQL_RECORD_TYPE.EQUAL_RECORD); // 데이터 로드

	if (ContainsComboAtom())
	{
		this.loadComboAtom(SQL_RECORD_TYPE.EQUAL_RECORD);
	}
	
	if (IsWebModel())
	{
		if (ContainsWebModelAtom())
		{
			WebModelAtom.init();
		}
		if (ContainsWebHtmlModelAtom())
		{
			WebHtmlModelAtom.init();
		}
		
		PQScript.execute(-1, 34, null);
		
		//웹편집기 아톰은 모든 DBIO동작이 끝난후에 초기화
		if (ContainsWebDHtmlEditAtom())
		{
			WebDHtmlEditAtom.init();
		}
		
		g_objModelCore._setMyAddress();
		
		setTimeout(
			function ()
			{
				if (GlobalField.isEmbededModel())
				{
					window.parent.WebModelAtom.setWebModelScroll();
				}
			}, 1 // 0.001 초 후에
		);
		
		//웹퀵링크 아톰의 움직임을 부드럽게 하기 위해서 ...
		if (ContainsWebQuickLinkAtom())
		{
			window.setTimeout("WebQuickLinkAtom.repositionYPos()", 500);
		}
	}
}

LightJDoc.prototype.onUnload = function ()
{
	
}

LightJDoc.prototype._initGlobalTool = function ()
{
	MakeRequest.init();
	HandleResult.init();
	
	PQService.init();
	
	// 현재 모델이 웹 포탈이면
	if (IsWebModel())
	{
		// PQPortalService를 만든다.
		PQPortalService.init();
		
		// Query정보를 만든다.
		MakePQQuery();
		
		g_objPQQuery.initQueryGenerator();
	}
	
	PQOperation.init();
	
	PQConnectionInput.init();
	PQConnectionSearch.init();
	PQConnectionModel.init();
	
	if (IsNtoaModel())
	{
		g_objModel = new NtoaModel();
	}
	else
	{
		g_objModel = new Model();
	}
	
	g_objModel.initModel();
	
	PQScript.init();
	
	// 진행관리자 전처리 정보를 만든다.
	MakeProcessManagerBeforeActionInfoTable();
	
	// 진행관리자 후처리 정보를 만든다.
	MakeProcessManagerAfterActionInfoTable();
	
	// 팝업차단 정보 읽음
	GlobalField.initPopupBlockInfo();
	
	g_objPQQuery.initServerQueryLinkedVar();
}

LightJDoc.prototype.preExecute = function ()
{
	for (var strVarName in Model._atoms)
	{
		var objAtom = Model._atoms[strVarName];
		
		if (objAtom.getAtomType)
		{
			var strType = objAtom.getAtomType();
			if ("WebBoardAtom" == strType || "WebTableAtom" == strType)
			{
				this.m_htSearchAtoms[strVarName] = objAtom;
			}
		}
	}
}

/**
 * 즉시실행
 */
LightJDoc.prototype.directExecute = function ()
{
	for (var strVarName in this.m_htSearchAtoms)
	{
		var objAtom = this.m_htSearchAtoms[strVarName];
		
		if (objAtom.isDirectExec())
		{
			objAtom.browseStart(true);
		}
	}
}

LightJDoc.prototype.executeSearchAtom = function (strVarName)
{
	var objAtom = this.m_htSearchAtoms[strVarName];
	
	if (null != objAtom)
	{
		objAtom.browseStart(true);
	}
}

/**
 * 조회동작 
 */
LightJDoc.prototype.loadData = function (bLoadData, nDBOperation)
{
	var nDBIOOption = nDBOperation;
	if (false == bLoadData && (SQL_RECORD_TYPE.UPDATE_RECORD == nDBOperation || SQL_RECORD_TYPE.UPDATE_RECORD_EX == nDBOperation))
	{
		nDBIOOption = SQL_RECORD_TYPE.EQUAL_RECORD;
	}
	
	if (false == this._prepareDBIO (nDBOperation))
	{
		if (bLoadData)
		{
		    //this.LoadEnding (pMsgAtom);
		
		    // Call 폼_검색완료 () 
		    //CallSearchEndMessage (nDBIOOption, nResult, nSelectTab);
		}
		
		return 1;
	}
	
	var nRealOperation = (bLoadData) ? nDBIOOption : nDBOperation;
	var nResult = this._beginDBIO (bLoadData, nRealOperation);
}

var g_bRemainSearchData = 1;

LightJDoc.prototype._prepareDBIO = function (nDBOperation)
{
	g_bRemainSearchData = 1;
	var strLastNumb = this._getLastNumber();
    if (Utils.isEmpty (strLastNumb) && false == ContainsScrollAtom()) // 주 필드에 데이터가 없는 경우 그냥 리턴한다..
        return false;
	
	if (0 == g_bRemainSearchData) //  자동증가 일경우..  //
	{
	    //pSelectView.RefreshAtomList (pmlLoadFieldAtom, false);
	
	    // <2002. 08. 06. cys> 연산식을 발생한 후.. 화면의 값들을 지워주기 때문에.. 기존에 발생된 연산식이 
	    // 사라지는 현상발생하므로.. 순서를.. 바꿔줌.. 즉, 기존 데이터를 먼저 지워준 후... 연산식을 발생시켜준다...
	    // 기존에 Load되어 있는 값들을 지워주기위한 동작이다..
	    if (-1 != nDBOperation)
	    {
//	        foreach (CLightDMTView pView in m_pViewList)
//	        {
//	            if (null != pView)
//	                pView.EmptyAtomList (null, LightDef.CLEAR_REFRESH | LightDef.CLEAR_ALLCLEAR | LightDef.CLEAR_NOTPOPUPDATA);
//	        }
	    }
	
	    // 연산식 발생..
	    for (var i = 0; i < g_htDefaultKeyAtom.length; i++)
		{
			var objAtom = g_htDefaultKeyAtom[i];
	        if (null == objAtom)
	            continue;
	        var strProperVar = objAtom.getVarName();
	        if (Utils.isEmpty (strProperVar))
	            continue;
			
	        if (objAtom instanceof InputDataAtom || objAtom instanceof InputTimeAtom)
	        {
	        	objAtom.setSaveType("INSERT");
	        	
	        	PQOperation.execute(objAtom);
	        }
	    }
	    
	    return false;
	}
	else if (-1 == g_bRemainSearchData)
	{
	    nDBOperation = SQL_RECORD_TYPE.EQUAL_RECORD;
	}
	
	return true;
}

LightJDoc.prototype._beginDBIO = function (bLoadData, nDBOperation)
{
	if (bLoadData)
	{
		var nResult = this.loadRecord (nDBOperation);
	}
}

LightJDoc.prototype.loadRecord = function (nDBOperation)
{
	var nSearchOper = nDBOperation;
	
	// 현재 View의 내용을 지워준다..
//	if (false == b2stLoad && null != pmlAtoms && SQL_RECORD_TYPE.PREV_RECORD != nSearchOper && SQL_RECORD_TYPE.NEXT_RECORD != nSearchOper && SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper)
//	{
//		EmptyAtomList (pmlAtoms, LightDef.CLEAR_NOTPOPUPDATA | LightDef.CLEAR_REFRESH);
//	}

	var htAlreadyLoadAtoms = new Object ();
	
	for (var j = 0; j < g_arDefaultKeyVarName.length; j++)
	{
		var arGroup = g_arDefaultKeyVarName[j];
		var strScrollName = arGroup[0];
		
		for (var i = 1; i < arGroup.length; i++)
		{
			var strVarName = arGroup[i];
			var objLoadAtom = Model.getAtom(strVarName, strScrollName);
			
			// 스크롤은 Load Field 이더라도 나중에 Load를 한다..
			if (null == objLoadAtom || objLoadAtom.isScroll() || "ScrollAtom" == objLoadAtom.getAtomType())
				continue;
		
			var strProperVar = objLoadAtom.getVarName();
			var	nSQLIndex	 = objLoadAtom.getSQLIndex ();
			if (-1 >= nSQLIndex || Utils.isEmpty(strProperVar))
			{
				// 기본검색키를 갖는 아톰중에 SQLIndex를 갖지 않는 아톰의 경우에는 연산식만 발생해 준다..
				if (null == objLoadAtom)
					continue;
				
				PQOperation.execute(objLoadAtom);					
				continue;
			}
		
			var nLoadSuccess = this.touchLoadRecord (objLoadAtom, nSearchOper);
			htAlreadyLoadAtoms[strProperVar] = 1;
			
			this._setSaveType(arGroup, nLoadSuccess);
			
			if (SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper)
			{
				// 앞장/뒷장일 경우 첫 Load에서 Data가 없으면 그냥 Return 한다.. 
				if ((SQL_RECORD_TYPE.PREV_RECORD == nSearchOper || SQL_RECORD_TYPE.NEXT_RECORD == nSearchOper) &&  
					0 == nLoadSuccess)
				{
					return AtomDefine._DB_ERR_NOT_EXIST_RECORD_;
				}
		
				// 앞장 뒷장 버튼으로 검색시 DB와 연결되지 않은 아톰의 값을 지우지 못하다.
				if ((SQL_RECORD_TYPE.PREV_RECORD == nSearchOper || SQL_RECORD_TYPE.NEXT_RECORD == nSearchOper) &&  
					0 != nLoadSuccess)
				{
					//ClearContentString ();
				}
		
				if (-1 != nLoadSuccess)
				{
					if( null != objLoadAtom && objLoadAtom instanceof InputDataAtom)
					{
						PQOperation.execute(objLoadAtom);
					}
				}
//				if (SQL_RECORD_TYPE.EQUAL_RECORD == nDBOperation && AtomDefine._DB_ERR_NOT_EXIST_RECORD_ == nLoadSuccess)
//					bLoadScroll = true;//result 가 0이면 현행데이터를 가져올때(nOperation이 0일때) 문제가 생긴다. 헤더와 아이템으로 묶여 있는경우.. load 값이 null 이면 문제가 아이템 검색을 하지 않게 된다,그것때문에 무조건 TRUE.2005.8.29 PTJ
			}
			break;
		}
	}
	
	if (SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper)
	{
//		if (-100 == nDBReturn)
//			nDBReturn = nLoadSuccess;
	
		nSearchOper = SQL_RECORD_TYPE.EQUAL_RECORD;
		if (SQL_RECORD_TYPE.PREV_RECORD == nDBOperation || SQL_RECORD_TYPE.NEXT_RECORD == nDBOperation)
			nSearchOper = -1;
	}
	
	for (var i = 0; i < g_htDefaultKeyAtom.length; i++)
	{
		var objDBAtom = g_htDefaultKeyAtom[i];
		
		// Scroll에 묶인 경우는 Scroll의 Load를 호출하고, 그렇지 않은 경우는 자신의 Load 함수를 호출한다..
		// Lock 처리시에는.. 스크롤만 처리해 준다..(추가검색은 안함)
		var objLoadAtom = objDBAtom.getScrollAtom();
		if (null != objLoadAtom)
		{
			if (false == objDBAtom.isDefaultKey() && false == objLoadAtom.isDBIO())
				continue;
		}
		else if (null == objLoadAtom && SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper)
		{
			objLoadAtom = objDBAtom;
		}
		
		if (null == objLoadAtom)
		{
			continue;
		}
		
		var nSQLIndex = objLoadAtom.getSQLIndex();
		var strVarName = objLoadAtom.getVarName();
		
		if (-1 == nSQLIndex || 1 == htAlreadyLoadAtoms[strVarName])
			continue;
		
		if (SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper)
		{
			nSearchOper = SQL_RECORD_TYPE.EQUAL_RECORD;
			if (SQL_RECORD_TYPE.PREV_RECORD == nDBOperation || SQL_RECORD_TYPE.NEXT_RECORD == nDBOperation)
				nSearchOper = -1;
		}
		
		if (objLoadAtom.loadRecord)
		{
			var nReturn = objLoadAtom.loadRecord (nSearchOper);
			htAlreadyLoadAtoms[strVarName] = 1;
			
			if (SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper && AtomDefine._DB_ERR_FAILURE_ != nReturn)
			{
				if (objDBAtom.isScroll())
				{
					if (objLoadAtom instanceof WebScrollAtom)
					{
						objLoadAtom.executeChangeOperation();
					}
				}
			}
		}
	}
	
	if (SQL_RECORD_TYPE.LOCK_RECORD != nSearchOper && 7 != nDBOperation)
	{
		//LoadEndingNtoa ();	// Ntoa atom의 데이터를 분리한다.
		
		if (ContainsWebDHtmlEditAtom())
		{
			for (var strVarName in WebDHtmlEditAtom._atoms)
			{
				WebDHtmlEditAtom._atoms[strVarName].loadEnding();
			}
		}
		if (ContainsWebFileAttachAtom())
		{
			for (var strVarName in WebFileAttachAtom._atoms)
			{
				WebFileAttachAtom._atoms[strVarName].loadEnding();
			}
		}
	}
}

/**
 * 기본검색키 아톰의 저장모드를 설정한다.
 */
LightJDoc.prototype._setSaveType = function (arGroup, nLoadSuccess)
{
	var strSaveType = (nLoadSuccess == 1) ? "UPDATE" : "INSERT";
	var strScrollName = arGroup[0]
	 
	for (var i = 1; i < arGroup.length; i++)
	{
		var strVarName = arGroup[i];
		var objLoadAtom = Model.getAtom(strVarName, strScrollName);
		
		if (objLoadAtom.setSaveType)
		{
			objLoadAtom.setSaveType(strSaveType);
		}
	}
}

LightJDoc.prototype._getLastNumber = function ()
{
	var strContent = "";
	
	for (var i = 0; i < g_htDefaultKeyAtom.length; i++)
	{
		var objAtom = g_htDefaultKeyAtom[i];
		
		if (objAtom.isScroll && objAtom.isScroll())
		{
			continue;
		}
		
		var strLoad = objAtom.getValue();
		if (null == strLoad)
		{
			strLoad = "";
		}
		
		var bValid = false;
		if (0 < strLoad.length)
		{
			bValid = this._formatLoadField(objAtom, strLoad, false);
		}
		
		if (bValid)
		{
			strLoad = objAtom.getValue();
		}
		else if (false == bValid && objAtom.isAutoLoad())
		{
			g_bRemainSearchData = -1; 
			if (0 == strLoad.length && objAtom.isAutoInc())
			{
				g_bRemainSearchData = 0;
			}
						
			strLoad = this._loadLastNumb (objAtom, true);
		}
		
		strContent += strLoad;
	}
	
	return strContent;
}

LightJDoc.prototype._formatLoadField = function (objAtom, strValue, bInc)
{
	var lNumb = 0;
	
	if (0 < strValue.length)
	{
		if (Utils.isDigit(strValue.charAt(0)))
		{
			lNumb = Utils.parseInt(strValue);
		}
	}
	
	var bAutoInc = objAtom.isAutoInc();
	if (bInc && bAutoInc)
	{
		lNumb++;
	}
	
	var nFieldLen = objAtom.getFieldLen();
	
	if (bAutoInc)
	{
		if (0 == lNumb)
			return false;
		
		strValue = lNumb + "";
		var nLen = strValue.length;
		if (nLen < nFieldLen)
		{
			var strZero = "";
			for(var k = 0; k < nFieldLen - nLen; k++)
			{
				strZero += "0";
			}
			strValue = strZero + strValue;
		}
	}
	
	objAtom.setValue(strValue);
	return true;
}

/**
 * 자동 검색일 경우 채번 수행
 */
LightJDoc.prototype._loadLastNumb = function (objLoadAtom, bMaxNum)
{
	if (null == objLoadAtom)
		return "";
	
	var strQuery = this.getMaxQuery(objLoadAtom.getVarName());
	var strValue = "";
	
	if (false == Utils.isEmpty(strQuery))
	{
		try
		{
			var nDBIndex = objLoadAtom.getDBIndex();
			var strModuleKey = PQQuery.getModuleKey(nDBIndex);
			
			strValue = g_objDataService.executeOpenScalarX(strQuery, 11, nDBIndex, strModuleKey);
		}
		catch(e)
		{
		}
	}
	
	if (Utils.isEmpty(strValue) && objLoadAtom.isAutoInc())
	{
		strValue = "0";
	}
	else if (objLoadAtom instanceof InputDataAtom)
	{
		var strPrefix = Utils.getPrefix(objLoadAtom.getPrefix());
		
		strValue = strValue.substring(strPrefix.length);
	}
	
	objLoadAtom.setValue(strValue);
	
	this._formatLoadField (objLoadAtom, strValue, true);
	
	return objLoadAtom.getValue();
}

LightJDoc.prototype.getMaxQuery = function (strVarName)
{
	var objMaxQuery = g_objPQQuery.getMaxQuery(strVarName);
	if (null == objMaxQuery)
	{
		return "";
	}

	var strQuery = objMaxQuery.getMaxQuery();
	if (Utils.isEmpty(strQuery))
	{
		return "";
	}

	var arAtomVariableList = objMaxQuery.getOutputAtomList();
	for (var i = 0; i < arAtomVariableList.length; i++)
	{
		var strVar = arAtomVariableList[i].getVarName();

		if (Utils.isEmpty(strVar))
		{
			continue;
		}

		var strVal = this._getRequestKey(strVar);

		if (Utils.isEmpty(strVal))
		{
			strVal = "";
		}

		var strTmp = "[" + strVar + "]";
		if (-1 < strQuery.indexOf(strTmp))
		{
			strQuery = strQuery.replace(strTmp, strVal);
		}
	}

	return g_objPQQuery.convertQuery(strQuery);
}

LightJDoc.prototype._getRequestKey = function (strVarName)
{
	var strValue = Model.getAtom(strVarName).getValue();

	if (null == strValue)
	{
		strValue = "";
	}
	return strValue;
}

LightJDoc.prototype.prepareScript = function ()
{
	// 스크립트 정보가 있을경우
	if (null != this.m_objFormExe)
	{
		if (false == this.m_objFormExe.initServerSymbol(this))
		{
			return false;
		}
	
		this.m_objFormExe.setUseEBLSource(true);
	
		//this.m_objFormExe.execute();
		
		this.m_objFormExe.makeFunctionMap();
	}
}

/**
 * 기본검색키 아톰 쿼리 실행
 */
LightJDoc.prototype.touchLoadRecord = function (objAtom, nSearchOp)
{
	var nSQLIndex = objAtom.getSQLIndex();
	if (nSQLIndex < 0)
	{
		return 0;
	}
	
	var objSelectQuery = g_objPQQuery.getSelectQuery(nSQLIndex);
	
	var strQuery = g_objQueryAtom.getSelectQueryString(objSelectQuery, nSearchOp);
	
	var nResult = 0;
	var arValue = null;

	if (false == Utils.isEmpty(strQuery) && -1 == strQuery.indexOf("@.@"))
	{
		try
		{
			var nDBIndex = objAtom.getDBIndex();
			var strModuleKey = PQQuery.getModuleKey(nDBIndex);
			
			arValue = g_objDataService.executeOpenRowX(strQuery, 11, nDBIndex, strModuleKey);
			
			nResult = this.handleTouchLoadResult (arValue, objSelectQuery);
		}
		catch (e)
		{
			nResult = 0;
			alert(e.message);
		}
	}
	
	return nResult;
}

LightJDoc.prototype.handleTouchLoadResult = function (arValue, objSelectQuery)
{
	var arVariableList = objSelectQuery.getOutputAtomList();
	if (null == arVariableList || null == arValue)
	{
		return 0;
	}
	
	var nColLen = arValue.length;
	if (nColLen != arVariableList.length)
	{
		return 0;
	}
	
	for (var i = 0; i < nColLen; i++)
	{
		var strVarName = arVariableList[i].getVarName();
		var strAtomType = arVariableList[i].getAtomType();

		if (strAtomType == "Scroll") // 스크롤이면 TouchAtomParam을 만들지 않는다.
		{
			continue;
		}

		var strValue = (null == arValue[i]) ? "" : Utils.trim(arValue[i]);

		// 검색된 값이 없을 때
		if (Utils.isEmpty(strValue))
		{
			// 날짜입력란의 경우, Request값으로 유지시킨다.
			if (strAtomType == "InputTime")
			{
				strValue = Model.getAtomValue(strVarName); 
			}
		}

		// TOA_DOC P12에 관련되는 OA 아톰은 따로 DBIO하므로 여기서 제외시킨다.
		if (strAtomType != "Receive")
		{
			// 입력란의 접두어 처리
			if (strAtomType == "InputData")
			{
				var objAtom = Model.getAtom(strVarName);
				
				if (null != objAtom)
				{
					var strPrefix = Utils.getPrefix(objAtom.getPrefix());
					
					if (strValue.length >= strPrefix.length)
					{
						strValue = strValue.substring(strPrefix.length);
					}
					
					var strFieldType = objAtom.getFieldType();
					if (strFieldType == "float" || strFieldType == "double")
					{
						/* 실수형일 경우 소수점 처리
						var strPeriod = objAtom.getPeriod();
						if (null != strPeriod && 0 < strPeriod.length)
						{
							var arPeriod = strPeriod.split(":");
							
							strValue = ExpressionFormatter.periodType(strValue, Utils.parseInt(arPeriod[0]), arPeriod[1]);
						}
						 */
					}
				}
			}
				
			var objAtom = Model.getAtom(strVarName);
			
			if (null != objAtom)
			{
				if ("Radio" == objAtom.getAtomType())
				{
					objAtom.setSelectValue(strValue);
				}
				else
				{
					objAtom.setValue(strValue);
				}
			}
		}
	}
	return 1;
}

LightJDoc.prototype.loadComboAtom = function (nSearchOp)
{
	for (var strVarName in ComboAtom._atoms)
	{
		var objCombo = ComboAtom._atoms[strVarName];
		
		var nSQLIndex = objCombo.getSQLIndex();
		
		if (-1 < nSQLIndex)
		{
			this._executeComboQuery(nSQLIndex, objCombo)
		}
	}
}

LightJDoc.prototype._executeComboQuery = function (nSQLIndex, objAtom)
{
	var objOuterQuery = g_objPQQuery.getOuterQueryByIndex(nSQLIndex);
	
	var strQuery = objOuterQuery.getQueryStatement();
	
	strQuery = g_objPQQuery.convertQuery(strQuery);
	
	strQuery = g_objQueryAtom.replaceSearchQuery(strQuery);
	
	if (false == Utils.isEmpty(strQuery) && -1 == strQuery.indexOf("@.@"))
	{
		try
		{
			var nDBIndex = objOuterQuery.getDBIndex();
			var strModuleKey = PQQuery.getModuleKey(nDBIndex);
			
			var dtResult = g_objDataService.executeOpenX(strQuery, 13, nDBIndex, strModuleKey);
			
			if (null != dtResult && 0 < dtResult.getRowCount())
			{
				objAtom.handleDataResult(dtResult);
			}
		}
		catch (e)
		{
			alert(e.message);
		}
	}
}

LightJDoc.prototype.executeSave = function ()
{
	var arUploadList = this._getUploadedFilepathList();
	
	var arTransactionQuery = this.extractTransactionEx();
	
	this.executeTransactionEx(arTransactionQuery);
	this._executeGridTransaction();

	this._saveEnding();
	
	this._executeRenameFilePath(arUploadList);
}

LightJDoc.prototype.extractTransactionEx = function ()
{
	var bSaveAllView = IsAllSave();
	var strCurrentTabId = "";
	if (false == bSaveAllView)
	{
//		TabviewAtom objTabviewAtom = new TabviewAtom(objServiceParameter, m_objStateManager, m_objSQLModel);
//		strCurrentTabId = objTabviewAtom.getCurrentTabId();
	}
	
	this.m_objKeyTranAtom = null;
	var arTransactionQuery = new Array();
	
	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);
		
		//개별뷰 동작일 때는 해당 탭뷰만 동작시킨다.
		if (false == bSaveAllView && strCurrentTabId != objLoadAtom.getTabId())
		{
			continue;
		}
		
		if (objLoadAtom.isScroll())
		{
//			ScrollAtom objScrollAtom = new ScrollAtom(objServiceParameter);
//			objScrollAtom.init(objServiceParameter, objDefaultKeyGroup, arTransactionQuery, m_objSQLModel);
//
//			// 스크롤 저장 쿼리로, 자동증가를 수행할 경우
//			if (0 == arTransactionQuery.size())
//			{
//				objScrollAtom.setAutoIncParam(m_objKeyAtomParam);
//			}
//
//			objScrollAtom.extractSaveQuery();
		}
		else
		{
			var nQueryKind = (objLoadAtom.getSaveType() == "UPDATE") ? FORMQUERY_KIND.UPDATE : FORMQUERY_KIND.INSERT;
			if (nQueryKind == FORMQUERY_KIND.INSERT)
			{
				// 기본검색키, 자동증가인 필드를 찾는다.
				this.setIncreaseKeyField(objLoadAtom);
			}
			
			this.extractTouchSaveQuery(objLoadAtom, arTransactionQuery, nQueryKind);
		}
	}
	
	return arTransactionQuery;
}

/**
 * 기본키필드가 자동실행, 자동증가일 경우, key값을 증가시키며 저장하기 위해
 * 해당하는 AtomParam을 찾는다.
 */
LightJDoc.prototype.setIncreaseKeyField = function (objLoadAtom)
{
	// 저장시 Unique Key에 의한 충돌이 발생 했을경우, 값을 증가 시겨서 저장을 하게 되는데
	// 이때 증가할 해당 객체는 로드필드, 보임속성, 자동증가 이어야 한다.
	if (objLoadAtom.isAutoLoad() && objLoadAtom.isAutoInc())
	{
		var strVarName = objLoadAtom.getVarName();
		
		if (objLoadAtom instanceof InputDataAtom)
		{
			this.m_objKeyTranAtom = objLoadAtom;
		}
	}
}

LightJDoc.prototype.extractTouchSaveQuery = function (objLoadAtom, arTransactionQuery, nQueryKind)
{
	var objTransactionQuery = g_objPQQuery.getTransactionQuery(objLoadAtom.getTableName(), nQueryKind);
	if (null == objTransactionQuery)
	{
		return;
	}
	
	var strQuery = objTransactionQuery.getTransactionQuery();
	strQuery = g_objPQQuery.convertQuery(strQuery);
		
	if (Utils.isEmpty(strQuery))
	{
		return;
	}

	strQuery = g_objQueryLib.replaceAtomVarName(strQuery, nQueryKind == FORMQUERY_KIND.INSERT); 
	arTransactionQuery.push(strQuery);
	
	return;
}

/**
 * 배열로된 트랜잭션 쿼리 실행
 * 저장, 삭제 버튼을 눌렀을 경우에만 동작한다.
 */
LightJDoc.prototype.executeTransaction = function (arTransactionQuery)
{
	if (0 == arTransactionQuery.length)
	{
		return;
	}
	
	var strQueries = "";
	for (var i = 0; i < arTransactionQuery.length; i+=1)
	{
		strQueries += arTransactionQuery[i] + ";"; 
	}
	
	var arGroup = g_arDefaultKeyVarName[0];
	var objLoadAtom = Model.getAtom(arGroup[1], arGroup[0]);
	
	var nDBIndex = objLoadAtom.getDBIndex();
	var strModuleKey = PQQuery.getModuleKey(nDBIndex);
	
	try
	{
		g_objDataService.executeTranSQL(strQueries, 14, nDBIndex, strModuleKey);
	}
	catch (e)
	{
		alert("LightJDoc.executeTransactionEx:" + e.message);
	}
}

/**
 * 배열로된 트랜잭션 쿼리 실행
 * 저장, 삭제 버튼을 눌렀을 경우에만 동작한다.
 * 
 * 기본검색키가 자동증가인 경우에는 따로 executeKeySQL 서비스를 사용해서 키값을 증가시키며 쿼리를 실행한다.
 * 키값이 변경되면 연산식 실행후, 나머지 쿼리를 다시 생성한다.
 * 쿼리 실행 결과가 없을 경우에는 roll-back 한다.
 */
LightJDoc.prototype.executeTransactionEx = function (arTransactionQuery)
{
	if (0 == arTransactionQuery.length)
	{
		return;
	}
	
	var nCount = 0;
	if (null != this.m_objKeyTranAtom)
	{
		// 자동증가 쿼리 수행
		var strValue = this.m_objKeyTranAtom.getValue();
		var strRealValue = "_CheckDuplicate_";

		try
		{
			var nDBIndex = this.m_objKeyTranAtom.getDBIndex();
			var strModuleKey = PQQuery.getModuleKey(nDBIndex);
			
			var strResult = g_objDataService.executeKeySQL(arTransactionQuery[0], 14, nDBIndex, strModuleKey, strRealValue, true);
			
			// 키값이 증가되었을 경우
			if (!Utils.isEmpty(strResult) && strResult != strValue)
			{
				this.m_objKeyTranAtom.setValue(strResult);
				
				PQOperation.execute(this.m_objKeyTranAtom);
				
				arTransactionQuery = null;
				arTransactionQuery = this.extractTransactionEx();
			}
			nCount ++;
		}
		catch (e)
		{
			alert("LightJDoc.executeTransactionEx:" + e.message);
			return;
		}
	}

	// 나머지 저장 쿼리 실행
	var strQueries = "";
	for (var i = nCount; i < arTransactionQuery.length; i+=1)
	{
		strQueries += arTransactionQuery[i] + ";"; 
	}
	
	try
	{
		if (0 < strQueries.length)
		{
			var arGroup = g_arDefaultKeyVarName[0];
			var objLoadAtom = Model.getAtom(arGroup[1], arGroup[0]);
			
			var nDBIndex = objLoadAtom.getDBIndex();
			var strModuleKey = PQQuery.getModuleKey(nDBIndex);
			
			g_objDataService.executeTranSQL(strQueries, 14, nDBIndex, strModuleKey);
		}
	}
	catch (e)
	{
		alert("LightJDoc.executeTransactionEx:" + e.message);
	}
}

LightJDoc.prototype._executeGridTransaction = function ()
{
	if (ContainsGridExAtom())
	{
		GridExAtom.executeTransaction();
	}
}

LightJDoc.prototype._saveEnding = function ()
{
	for (var strVarName in Model._atoms)
	{
		var objAtom = Model._atoms[strVarName];
		
		if (null != objAtom.getAtomType && (objAtom.getAtomType() == "WebDHtmlEditAtom" || objAtom.getAtomType() == "WebFileAttachAtom"))
		{
			objAtom.saveEnding ();
		}
	}
}

/**
 * @param objServiceParameter
 * @return
 */
LightJDoc.prototype._getUploadedFilepathList = function ()
{
	var alDataList = new Array();
	var alDataTemp = new Array();
	
	if (ContainsWebDHtmlEditAtom())
	{
		for (var strVarName in WebDHtmlEditAtom._atoms)
		{
			var objAtom = WebDHtmlEditAtom._atoms[strVarName];
			var strData = objAtom.makeInsertedImageString();
			
			alDataTemp.push(strData);
		}
	}
	
	if (ContainsWebPictureAtom())
	{
		for (var strVarName in WebPictureAtom._atoms)
		{
			var objAtom = WebPictureAtom._atoms[strVarName];
			var strData = objAtom.getValue();
			
			alDataTemp.push(strData);
		}
	}
	
	if (ContainsWebFileAttachAtom())
	{
		for (var strVarName in WebFileAttachAtom._atoms)
		{
			var objAtom = WebFileAttachAtom._atoms[strVarName];
			var strData = objAtom.getRequestFileInfo();
			
			alDataTemp.push(strData);
		}
	}
	
	for (var i = 0; i < alDataTemp.length; i+=1)
	{
		var strData = alDataTemp[i];
		if (strData == "$")
		{
			continue;
		}
		
		if (0 < strData.length)
		{
			var arTempNameList = strData.split(";");
			for (var j = 0, nLen = arTempNameList.length; j < nLen; j++)
			{
				var strFiles = arTempNameList[j].split("$");						
				alDataList.push(strFiles[0]);
			}
		}
	}
	
	return alDataList;
}

LightJDoc.prototype._executeRenameFilePath = function (alDataList)
{
	var xnRequest = MakeRequest.createRequestNode();
	
	for (var i = 0; i < alDataList.length; i+=1)
	{
		XmlLib.createChildWithValue(xnRequest, "Data", alDataList[i])
	}
	
	g_objPQPortalService.executeRenameUploadPathService(xnRequest.ownerDocument);
}

LightJDoc.prototype.executeDelete = function ()
{
	var arTransactionQuery = this.extractDeleteQuery();
	
	this.executeTransaction(arTransactionQuery);
}

LightJDoc.prototype.extractDeleteQuery = function ()
{
	var arTransactionQuery = new Array();
	var nLen = g_arDefaultKeyVarName.length;
	
	/**
	 * PQ 논리상 header의 tab order가 먼저 옵니다.
	 * XML에 DefaultKey는 tab order 순서대로 저장됩니다.
	 * 
	 * header - detail 관계 table에서 detail먼저 지우기 위해 탭순서 반대로 삭제한다.
	 */
	for (var j = nLen - 1; j >= 0; j-=1)
	{
		var arGroup = g_arDefaultKeyVarName[j];
		
		var objLoadAtom = Model.getAtom(arGroup[1], arGroup[0]);
		
		if (objLoadAtom.isScroll())
		{
		}
		else
		{
			this.extractTouchSaveQuery(objLoadAtom, arTransactionQuery, FORMQUERY_KIND.DELETE);
		}
	}

	return arTransactionQuery;
}

LightJDoc.prototype.executeScript = function (nScriptIndex, nEventID, arParam, bIncludeBeforeAction)
{
	if (bIncludeBeforeAction)
	{
		if (-1 != this.executeProcessManagerBeforeAction(nScriptIndex, nEventID, arParam))
		{
			return this.callMsgHandler(nScriptIndex, nEventID, arParam, new CVariantX());
		}
	}
	else
	{
		return this.callMsgHandler(nScriptIndex, nEventID, arParam, new CVariantX());
	}
}

LightJDoc.prototype._getMessage = function (nScriptIndex, nEventID)
{
	var strMessage = "";
	// 폼메시지 함수 호출시
	if (EVS_TYPE.EVS_F_LOAD <= nEventID && nEventID <= 46)
	{
		strMessage = "IM" + nEventID;
	}
	// 이벤트 호출시
	else
	{
		strMessage =  nScriptIndex + "_" + nEventID;
	}

	return strMessage;
}

LightJDoc.prototype.makeArgs = function (nLen)
{
	var arArgs = new Array(nLen);
	 
	for (var i = 0; i < nLen; i++)
	{
		arArgs[i] = new CVariantX();
	}

	return arArgs;
}

/**
 * 스크립트 이벤트 마다 발생하는 인자를 대입 시켜줍니다. 스크립트 이벤트 번호는 BosKey를 참조하십시오.
 * @return
 */
LightJDoc.prototype._extractEventParamter = function (arParam, nEventID)
{
	if (null == arParam)
	{
		return null;
	}

	var arArgs = null;
	var nParamTypeCount = 3; // 누름 이벤트에서 쓰이는 Param의 Type 수, 3가지 (0:int, 1:double, 2:string)

	/**
	 * 폼_저장완료, 폼_저장결과
	 * 
	 * [ 0: Param 개수, 1:Integer, 2:Integer ]
	 */
	if (nEventID == 40 || nEventID == 41)
	{
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(3);

			arArgs[0].setValueType(CVariantX._vtInt, 2);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
		}
	}
	/**
	 * 폼_검색완료
	 * 
	 * [ 0: Param 개수, 1:Integer, 2:Integer, 3:Integer ]
	 */
	else if (nEventID == 42)
	{
		if (3 == arParam.length)
		{
			arArgs = this.makeArgs(4);

			arArgs[0].setValueType(CVariantX._vtInt, 3);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
			arArgs[2].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[1]));
			arArgs[3].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[2]));
		}
	}
	
	/**
	 * 폼_문서대장
	 * [ 0: Param 개수, 1:Integer, 2:String]
	 */
	else if (nEventID == 44)
	{
		if (2 == arParam.length)
		{
			arArgs = this.makeArgs(3);

			arArgs[0].setValueType(CVariantX._vtInt, 2);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
			arArgs[2].setValueType(CVariantX._vtString, arParam[1]);
		}
	}

	/**
	 * 51:메뉴선택
	 * 
	 * [0: Param 개수, 1:Integer] or [0:Param 개수, 1:Integer, 2:String, 3:Integer]
	 */
	else if (nEventID == 51)
	{
		// 일반입력란_메뉴선택 (선택인덱스)
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(2);
			arArgs[0].setValueType(CVariantX._vtInt, 1);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
		}
		// 스크롤묶인입력란_메뉴선택 (선택행, 변수명, 선택인덱스)
		else if (3 == arParam.length)
		{
			arArgs = this.makeArgs(4);
			arArgs[0].setValueType(CVariantX._vtInt, 3);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
			arArgs[2].setValueType(CVariantX._vtString, arParam[1]);
			arArgs[3].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[2]));
		}
	}

	/**
	 * 53:누름
	 */ 
	else if (nEventID == 53)
	{
		if (1 < arParam.length)
		{
			var nCount = arParam.length - 1;
			var nType = Utils.parseInt(arParam[0]);
			var nTemp = nType;

			arArgs = this.makeArgs(nCount + 1);
			arArgs[0].setValueType(CVariantX._vtInt, nCount);

			for (var i = 1; i <= nCount; i++)
			{
				var nCurType = Math.floor(nTemp % nParamTypeCount); 
				nTemp = nTemp / nParamTypeCount;

				if (0 == nCurType)
				{
					arArgs[i].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[i]));
				}
				else if (1 == nCurType)
				{
					arArgs[i].setValueType(CVariantX._vtReal, parseFloat(arParam[i]));
				}
				else if (2 == nCurType)
				{
					arArgs[i].setValueType(CVariantX._vtString, arParam[i]);
				}
			}
		}
	}

	/**
	 * 54:두번누름 , 55:초점얻음 , 56:초점상실, 81:팝업동작
	 * 
	 * [0: Param 개수, 1:Integer]
	 * [ 0: Param 개수, 1:Integer, 2:String ]
	 */
	else if (nEventID == 54 || nEventID == 55 || nEventID == 56 || nEventID == 81)
	{
		// 간트차트 _누름, _두번누름 (선택인덱스)
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(2);
			arArgs[0].setValueType(CVariantX._vtInt, 1);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
		}
		else if (2 == arParam.length)
		{
			arArgs = this.makeArgs(3);

			arArgs[0].setValueType(2);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
			arArgs[2].setValueType(CVariantX._vtString, arParam[1]);
		}
	}
	/**
	 * 59: _저장결과
	 * 
	 * [ 0: Param 개수, 1:boolean]
	 */
	else if (nEventID == 59)
	{
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(2);

			arArgs[0].setValueType(CVariantX._vtInt, 1);
			arArgs[1].setValueType(CVariantX._vtInt, arParam[0]);
		}
	}
	/**
	 * 61:행추가, 62:행삭제, 63:입력마침
	 * 
	 * [ 0: Param 개수, 1:Integer]
	 */
	else if (nEventID == 61 || nEventID == 62 || nEventID == 63)
	{
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(2);

			arArgs[0].setValueType(CVariantX._vtInt, 1);
			arArgs[1].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[0]));
		}
	}
	/**
	 * 67:탭뷰전환
	 * 
	 * [ 0: Param 개수, 1:Integer, 2:integer, 3:Int, 4:int]
	 */
	else if (nEventID == 67)
	{
		if (4 == arParam.length)
		{
			arArgs = this.makeArgs(5);

			arArgs[0].setValueType(CVariantX._vtInt, 4);
			arArgs[1].setValueType(CVariantX._vtInt, this._getRealReturnIndex(Utils.parseInt(arParam[0])));
			arArgs[2].setValueType(CVariantX._vtInt, this._getRealReturnIndex(Utils.parseInt(arParam[1])));
			arArgs[3].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[2]));
			arArgs[4].setValueType(CVariantX._vtInt, Utils.parseInt(arParam[3]));
		}
	}
	/**
	 * 70:자동증가
	 * 
	 * [ 0:Param개수, 1:String, 2:String]
	 */
	else if (nEventID == 70)
	{
		if (4 == arParam.length)
		{
			arArgs = this.makeArgs(3);

			arArgs[0].setValueType(CVariantX._vtInt, 2);
			arArgs[1].setValueType(CVariantX._vtString, arParam[0]);
			arArgs[2].setValueType(CVariantX._vtString, arParam[1]);
		}
	}
	/**
	 * 71:키값확인
	 * 
	 * [ 0:Param개수(2) , 1:String , 2:String ]
	 */
	else if (nEventID == 71)
	{
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(3);
			var strASCIICode = arParam[0];
			var chKey = Utils.parseInt(strASCIICode);
			
			arArgs[0].setValueType(CVariantX._vtInt, 2);
			arArgs[1].setValueType(CVariantX._vtString, chKey + "");
			arArgs[2].setValueType(CVariantX._vtString, strASCIICode);
		}
	}
	/**
	 * 74:파일열림
	 * 
	 * [ 0:Param개수, 1:String]
	 */
	else if (nEventID == 74)
	{
		if (1 == arParam.length)
		{
			arArgs = this.makeArgs(2);

			arArgs[0].setValueType(CVariantX._vtInt, 1);
			arArgs[1].setValueType(CVariantX._vtString, arParam[0]);
		}
	}

	return arArgs;
}

LightJDoc.prototype._getRealReturnIndex = function (nIndex)
{
	var nRealReturnIndex = nIndex;

	if (this.isEBLSource() == true && 0 <= nRealReturnIndex)
	{
		nRealReturnIndex++;
	}

	return nRealReturnIndex;
}

LightJDoc.prototype.callMsgHandler = function (nScriptIndex, nEventID, arParam, objReturnValue)
{
	var strMessage = this._getMessage(nScriptIndex, nEventID);
	var arArgs = this._extractEventParamter(arParam, nEventID);
	
	var bResult = (null != this.m_objFormExe) ? this.m_objFormExe.callMsgHandler(strMessage, arArgs, objReturnValue) : false;

	return objReturnValue.toInt();
}

LightJDoc.prototype.callMessagHandler = function (strMessage, arParam, objReturnValue)
{
	var bResult = (null != this.m_objFormExe) ? this.m_objFormExe.callMsgHandler(strMessage, arParam, objReturnValue) : false;

	return objReturnValue.toInt();
}

LightJDoc.prototype.addPrePMInfo = function (nScriptIndex, objKey, arPMInfo)
{
	var strKey = nScriptIndex + "_" + objKey;
	this.m_htPrePMInfos[strKey] = arPMInfo;
}

LightJDoc.prototype.addPostPMInfo = function (nScriptIndex, objKey, arPMInfo)
{
	var strKey = nScriptIndex + "_" + objKey;
	this.m_htPostPMInfos[strKey] = arPMInfo;
}

LightJDoc.prototype.executeProcessManagerBeforeAction = function (nScriptIndex, nEventID, arParam)
{
	return this.executeProcessManager(this.getProcessManagerEvent(0, nScriptIndex, nEventID), nEventID, arParam);
}

LightJDoc.prototype.getProcessManagerEvent = function (nType, nScriptIndex, nEventID)
{
	var strKey = nScriptIndex + "_" + nEventID;
	var arInfos = null;
	
	if (0 == nType)
	{
		arInfos = this.m_htPrePMInfos[strKey];
	}
	else if (1 == nType)
	{
		arInfos = this.m_htPostPMInfos[strKey];
	}
	
	return arInfos;
}

/**
 * 프로그램 진행 관리자를 실행한다.
 * @param arProcessInfos 처리 정보. 
 * @return 실패: -1. 성공: 그 외의 수.
 */
LightJDoc.prototype.executeProcessManager = function (arProcessInfos, nEventID, arParam)
{
	var nFail = -1;
	var objResult = new CVariantX(CVariantX._vtInt, true);

	if (null != arProcessInfos)
	{
		var objPmInfo = null;
		for (var i = 0, nLen = arProcessInfos.length; i != nLen; i++)
		{
			// 진행관리 임시변수 정보를 추출하여 m_htPMVariable에 넣는다.
			this.extractPMTempVariable(nEventID, arParam);

			objPmInfo = arProcessInfos[i];
			//if (null != objPmInfo && objPmInfo.checkCondition())
			if (null != objPmInfo && objPmInfo.compare())
			{
				try
				{
					objResult = objPmInfo.execute();
					if (!objPmInfo.isContinue())
					{
						objResult.setValueType(CVariantX._vtInt, nFail);
						break;
					}
				}
				catch (e)
				{
					objResult.setValueType(CVariantX._vtInt, nFail);
					alert ("LightJDoc.executeProcessManager:" + e.message);
					break;
				}
			}
		}
	}

	return objResult.toInt();
}

/**
 * 진행관리자 전처리, 후처리의 임시변수를 만들어준다. 
 * 이때 발생한 이벤트의 "인자"는 진행관리자의 "@임시변수"값으로 대치된다.
 * 
 * 예) 입력란_메뉴선택(선택인덱스) -> 전처리 실행인자 "@선택인덱스"에 대입된다.
 * 참고) 전처리 실행인자 변수앞에 "@"가 붙으면 임시변수이고 이벤트의 인자에서 값을 받는다.
 * 
 * TODO: 스크립트 관련되어 매개변수 변경이나 이벤트 추가구현시 이곳도 추가 하여야 함 
 */
LightJDoc.prototype.extractPMTempVariable = function (nEventID, arParam)
{
	if (null == arParam)
	{
		return;
	}

	/**
	 * 폼_저장완료, 폼_저장결과(저장결과)
	 */
	if (nEventID == 40 || nEventID == 41)
	{
		if (1 == arParam.length)
		{
			this.setVariableToPMVariable ("@저장결과", ((arParam[0])? true : false));
		}
	}

	/**
	 * 폼_검색완료
	 */
	else if (nEventID == 42)
	{
		if (3 == arParam.length)
		{
			this.setVariableToPMVariable ("@검색유형", arParam[0]);
			this.setVariableToPMVariable ("@검색결과", arParam[1]);
			this.setVariableToPMVariable ("@탭뷰인덱스", arParam[2]);
		}
	}

	/**
	 * 51:메뉴선택(선택인덱스) or (선택행, 변수명, 선택인덱스)
	 */
	else if (nEventID == 51)
	{
		// 일반입력란_메뉴선택 (선택인덱스)
		if (1 == arParam.length)
		{
			this.setVariableToPMVariable ("@선택인덱스", arParam[0]);
		}
		// 스크롤묶인입력란_메뉴선택 (선택행, 변수명, 선택인덱스)
		else if (3 == arParam.length)
		{
			this.setVariableToPMVariable ("@선택행", arParam[0]);
			this.setVariableToPMVariable ("@변수명", arParam[1]);
			this.setVariableToPMVariable ("@선택인덱스", arParam[2]);
		}
	}

	/**
	 * 59: _저장결과
	 * 
	 */
	else if (nEventID == 59)
	{
		if (null != arParam && 1 == arParam.length)
		{
			this.setVariableToPMVariable ("@저장결과", ((arParam[0])? true : false));
		}
	}
	/**
	 * _탭뷰전환
	 */
	else if (nEventID == 67)
	{
		if (4 == arParam.length)
		{
			this.setVariableToPMVariable ("@이전탭", arParam[0]);
			this.setVariableToPMVariable ("@현재탭", arParam[1]);
			this.setVariableToPMVariable ("@전후누름", arParam[2]);
			this.setVariableToPMVariable ("@탭누름", arParam[3]);
		}
	}

	/**
	 * 81:팝업동작
	 */
	else if (nEventID == 85)
	{
		if (null != arParam && 2 == arParam.length)
		{
			this.setVariableToPMVariable ("@검색결과", ((arParam[0])? true : false));
			this.setVariableToPMVariable ("@선택값", arParam[1]);
		}
	}
}

LightJDoc.prototype.setVariableToPMVariable = function (strKey, strValue)
{
	this.m_htPMVariable[strKey] = strValue;
}

LightJDoc.prototype.getVariableToPMVariable = function (strKey)
{
	return this.m_htPMVariable[strKey];
}

LightJDoc.prototype.getSymbolValue = function (nSymbolId)
{
	if (null != this.m_objFormExe)
	{
		return this.m_objFormExe.getSymbol(nSymbolId).toStringX();
	}
	
	return null;
}

/**
 * 외부질의 실행 결과를 유지시킨다. _필드명 형태로 값을 찾아올 경우 사용됨
 */
LightJDoc.prototype.addQueryResult = function (nSQLIndex, objDTServer)
{
	if (objDTServer == null || null == objDTServer.m_objDataTable || objDTServer.m_objDataTable.getRowCount() < 1)
	{
		return;
	}

	this.m_htQueryResultDTS[nSQLIndex] = objDTServer;
}

/**
 * 외부질의 실행 결과중에서, 필드명에 해당하는 DataTaberServer를 리턴한다.
 */
LightJDoc.prototype.findQueryResult = function (strField)
{
	for(var nSQLIndex in this.m_htQueryResultDTS)
	{
		var objDTS = this.m_htQueryResultDTS[nSQLIndex]
		
		if (objDTS.containsColumnName(strField))
		{
			return objDTS;
		}
	}
	
	return null;
}

/**
 * 아톰.값 -> 전역 스크립트 변수로 취급할 수 있도록, 스크립트 전역 변수 관련 요청 정보 생성
 * 서버 스크립트에서 사용되는 전역 변수 값도 클라이언트에서 유지되므로 같이 전송한다. 
 */
LightJDoc.prototype.makeScriptVarRequest = function (xnRequest, strFuncName, arArgs)
{
	var htAtomSymbolMap = g_htScriptAtomSymbolMap[strFuncName];
	
	if (null != htAtomSymbolMap)
	{
		var xnAtomSymbol = XmlLib.selectSingleNode(xnRequest, "./ScriptAtomSymbol");
		if (null == xnAtomSymbol)
		{
			xnAtomSymbol = XmlLib.createChild(xnRequest, "ScriptAtomSymbol");
		}
		
		for (var strKey in htAtomSymbolMap)
		{
			var arValue = htAtomSymbolMap[strKey].split("_");
			var nExeId = Utils.parseInt(arValue[0]);
			var strSymbolId = arValue[1];
			
			var arKey = strKey.split("_");
			var nObjId = Utils.parseInt(arKey[0]);
			var nPropId = Utils.parseInt(arKey[1]);
			var nPropIdEx = (3 == arKey.length) ? Utils.parseInt(arKey[2]) : -1;
			
			var objAtom = this.findAtomByScriptIndex(nObjId);
			var strAtomName = objAtom.getVarName();
			var strValue = objAtom.getValue();
			strValue = Utils.encodeBase64(strValue);
			
			var strType = "char";
			if (null != objAtom.getFieldType)
			{
				strType = objAtom.getFieldType();
			}
			
			var xnSymbol = XmlLib.createChildWithValue(xnAtomSymbol, strAtomName, strSymbolId);
			xnSymbol.setAttribute("Type", strType);
			xnSymbol.setAttribute("ScriptIndex", nObjId);
			xnSymbol.setAttribute("Value", strValue);
		}
	}
	
	this.makeQueryVarRequest(xnRequest, strFuncName, htAtomSymbolMap);
	
	var htIdSymbolMap = g_htScriptIDSymbolMap[strFuncName];
	if (null != htIdSymbolMap)
	{
		var xnIDSymbol = XmlLib.selectSingleNode(xnRequest, "./ScriptIDSymbol");
		if (null == xnIDSymbol)
		{
			xnIDSymbol = XmlLib.createChild(xnRequest, "ScriptIDSymbol");
		}
		
		for (var strKey in htIdSymbolMap)
		{
			var strSymbolId = strKey;
			var nExeId = htIdSymbolMap[strKey];
			
			var objExe = null;
			if (-1 == nExeId)
			{
				objExe = this.m_objFormExe;				
			}
			else
			{
				objExe = this.m_objFormExe.getExecute(nExeId);
			}
			
			if (null != objExe)
			{
				var objSymbol = objExe.getSymbol(Utils.parseInt(strSymbolId));
				
				if (null != objSymbol && objSymbol.getSymbolKind() != ScriptDefine._FUNCTION)
				{
					var nType = objSymbol.getType();
					var objValue = objSymbol.getValue();
					
					var xnSymbol = XmlLib.createChildWithValue(xnIDSymbol, "s" + strSymbolId, nExeId);
					xnSymbol.setAttribute("Type", nType);
					if (null != objValue)
					{
						objValue = Utils.encodeBase64(objValue);
						xnSymbol.setAttribute("Value", objValue);
					}
				}
			}
		}
	}
}

/**
 * 쿼리 구성에 사용되는 아톰 정보 생성
 */
LightJDoc.prototype.makeQueryVarRequest = function (xnRequest, strFuncName, htAtomSymbolMap)
{
	var htServerQueryName = g_htScriptQueryVarMap[strFuncName];
	
	if (null != htServerQueryName)
	{
		for (var strQueryName in htServerQueryName)
		{
			var arQueryInfo = g_objPQQuery.getServerQueryInfo(strQueryName);
			var arLinkedVar = arQueryInfo[0];
			var arWhereVar = arQueryInfo[1];
			var arInsertVar = arQueryInfo[2];
			
			if (null != arLinkedVar && 0 < arLinkedVar.length)
			{
				var xnQueryLinked = XmlLib.selectSingleNode(xnRequest, "./QueryLinkedVar");
				if (null == xnQueryLinked)
				{
					xnQueryLinked = XmlLib.createChild(xnRequest, "QueryLinkedVar");
				}
		
				for (var j = 0; j < arLinkedVar.length; j+=1)
				{
					var strVarName = arLinkedVar[j];
					
					this._makeQueryVarRequest(strVarName, htAtomSymbolMap, xnQueryLinked);
				}
			}
			
			if (null != arWhereVar && 0 < arWhereVar.length)
			{
				var xnQueryWhere = XmlLib.selectSingleNode(xnRequest, "./QueryWhereVar");
				if (null == xnQueryWhere)
				{
					xnQueryWhere = XmlLib.createChild(xnRequest, "QueryWhereVar");
				}
				
				for (var j = 0; j < arWhereVar.length; j+=1)
				{
					var strVarName = arWhereVar[j];
					
					this._makeQueryVarRequest(strVarName, htAtomSymbolMap, xnQueryWhere);
				}
			}
			
			if (null != arInsertVar && 0 < arInsertVar.length)
			{
				var xnQueryInsert = XmlLib.selectSingleNode(xnRequest, "./QueryInsertVar");
				if (null == xnQueryInsert)
				{
					xnQueryInsert = XmlLib.createChild(xnRequest, "QueryInsertVar");
				}
		
				for (var j = 0; j < arInsertVar.length; j+=1)
				{
					var strVarName = arInsertVar[j];
					
					this._makeQueryVarRequest(strVarName, htAtomSymbolMap, xnQueryInsert);
				}
			}
		}
	}
}

LightJDoc.prototype._makeQueryVarRequest = function (strVarName, htAtomSymbolMap, xnParent)
{
	if (null == htAtomSymbolMap[strVarName])
	{
		var objAtom = Model.getAtom(strVarName);
		
		if (null != objAtom)
		{
			var strType = objAtom.getFieldType();
			var strValue = objAtom.getValue();
			strValue = Utils.encodeBase64(strValue);
			
			var xnItem = XmlLib.createChildWithValue(xnParent, strVarName, strValue);
			xnItem.setAttribute("Type", strType);
			xnItem.setAttribute("ScriptIndex", objAtom.getScriptIndex());
		}
		else
		{
			var nSymbolId = g_htScriptVarMap[strVarName];
			if (null != nSymbolId)
			{
				var objSymbol = this.m_objFormExe.getSymbol(nSymbolId);
				var strValue = objSymbol.getValue();
				strValue = Utils.encodeBase64(strValue);
				var nType = objSymbol.getType();
				
				var xnSymbol = XmlLib.createChildWithValue(xnParent, strVarName, strValue);
				xnSymbol.setAttribute("Type", nType);
				xnSymbol.setAttribute("SymbolId", nSymbolId);
			}
		}
	}
}

/**
 * 서버 실행 스크립트 함수 호출 인자 처리
 */
LightJDoc.prototype.makeFuncParamRequest = function (xnRequest, arArgs)
{
	var xnVarParam = XmlLib.selectSingleNode(xnRequest, "./ScriptVarParam");
	if (null == xnVarParam)
	{
		xnVarParam = XmlLib.createChild(xnRequest, "ScriptVarParam");
	}
	
	if (null != arArgs)
	{
		var nCount =  arArgs.length - 1;
		xnVarParam.setAttribute("VarCount", nCount);
		
		for (var i = 0; i < arArgs.length; i+=1)
		{
			var objVariant = arArgs[i];
			
			var xnVariant = XmlLib.createChildWithValue(xnVarParam, "VariantX", objVariant.getValue());
			xnVariant.setAttribute("Type", objVariant.getType());
		}
	}
}

/**
 * QWP 서버 실행 스크립트 동작 결과를 처리한다.
 */
LightJDoc.prototype.handleScriptVarResult = function (xnRequest, strFuncName)
{
	var xnAtomSymbols = XmlLib.selectSingleNode(xnRequest, "./ScriptAtomSymbol");
	if (null != xnAtomSymbols)
	{
		var nLen = xnAtomSymbols.childNodes.length;
		for (var i = 0; i < nLen; i+=1)
		{
			var xnAtom = xnAtomSymbols.childNodes[i];
			
			var strVarName = xnAtom.nodeName;
			var strValue = xnAtom.getAttribute("Value");
			strValue = Utils.decodeBase64(strValue);
			
			var objAtom = Model.getAtom(strVarName);
			objAtom.setValue(strValue);
		}
	}
	
	var xnIdSymbols = XmlLib.selectSingleNode(xnRequest, "./ScriptIDSymbol");
	if (null != xnIdSymbols)
	{
		var nLen = xnIdSymbols.childNodes.length;
		for (var i = 0; i < nLen; i+=1)
		{
			var xnId = xnIdSymbols.childNodes[i];
			
			var strSymbolId = xnId.nodeName.substring(1);
			var nType = Utils.parseInt(xnId.getAttribute("Type"));
			var strValue = xnId.getAttribute("Value");
			strValue = Utils.decodeBase64(strValue);
			
			var objSymbol = this.m_objFormExe.getSymbol(Utils.parseInt(strSymbolId));
			if (null != objSymbol && objSymbol.getSymbolKind() != ScriptDefine._FUNCTION)
			{
				objSymbol.setValueType(nType, strValue);
			}
		}
	}
	
	var xnQueryLinked = XmlLib.selectSingleNode(xnRequest, "./QueryLinkedVar");
	if (null != xnQueryLinked)
	{
		var nLen = xnQueryLinked.childNodes.length;
		for (var i = 0; i < nLen; i+=1)
		{
			var xnItem = xnQueryLinked.childNodes[i];
			
			var strVarName = xnItem.nodeName;
			var strValue = XmlLib.getTextValue(xnItem); 
			strValue = Utils.decodeBase64(strValue);
			
			var objAtom = Model.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.setValue(strValue);
			}
			else
			{
				var strSymbolId = XmlLib.getAttribute(xnItem, "SymbolId");
				if (null != strSymbolId)
				{
					var nSymbolId = Utils.parseInt(strSymbolId);
					var nType = Utils.parseInt(XmlLib.getAttribute(xnItem, "Type"));
					
					var objSymbol = this.m_objFormExe.getSymbol(nSymbolId);
					if (null != objSymbol)
					{
						if (objSymbol.getSymbolKind() == ScriptDefine._FIELD_SYMBOL)
						{
							objSymbol.setValueType(3, strValue);
						}
						else
						{
							objSymbol.setValueType(nType, strValue);
						}
					}
				}
			}
		}
	}
}

LightJDoc.prototype.getProperty = function (nObjID, nPropID, objRetVal)
{
	if (StdCore._INIT_WVALUE == nPropID || null == objRetVal)
	{
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	var nResult = StdCore.S_OK;
	try
	{
		if (-1 == nPropID)
		{
			return StdCore.S_OK;
		}

		if (-1 != nObjID) // 아톰 속성..
		{
			var objAtom = this.findAtomByScriptIndex(nObjID);
			
			if (false)//Search.class == objAtom.getClass())
			{
				var alWhere = this._getConditionWhereForSearch(objAtom);
				nResult = objAtom.getProperty (nPropID , null , objRetVal, alWhere);
			}
			else
			{
				nResult = objAtom.getProperty (nPropID , null , objRetVal);
			}

			// 미구현된 스크립트일 경우
			if (13 == nResult)
			{
				var strAtomType = objAtom.getAtomType();
				alert("미구현된 스크립트입니다. (" + strAtomType + ":" + nPropID + ")");
			}
		}
		else
		{
			nResult = this.getProperty (nPropID, null, objRetVal);
		}				
	}
	catch (e)
	{
		nResult = StdCore.E_NOT_DEF_PROPERTY;
		alert ("LightJDoc.getProperty:" + e.message);
	}

	return nResult;
}
	
LightJDoc.prototype.setProperty = function (nObjID, nPropID, arVarArgs, objValue)
{
	if (StdCore._INIT_WVALUE == nPropID || null == objValue)
	{
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	try
	{
		if (-1 == nPropID)
		{
			return StdCore.S_OK;
		}

		if (-1 != nObjID) // 아톰 속성..
		{
			var objAtom = this.findAtomByScriptIndex(nObjID);

			var nResult = objAtom.setProperty (nPropID, arVarArgs , objValue);

			// 미구현된 스크립트일 경우
			if (StdCore.E_NOT_DEF_PROPERTY == nResult || StdCore.E_NOT_SUPPORT_PROPERTY == nResult)
			{
				var strAtomType = objAtom.getAtomType();
				
				alert("미구현된 스크립트 (setProperty): " + strAtomType + ", nPropID : " + nPropID);
			}
		}
		else
		{
			this.setPropertyL (nPropID, arVarArgs, objValue);
		}
	}
	catch (e)
	{
		alert ("LightJDoc.setProperty:" + e.message);
	}

	return StdCore.S_OK;
}

LightJDoc.prototype.setPropertyL = function (nPropID, arVarArgs, objRetVal)
{
	switch (nPropID)
	{
	default : return StdCore.E_NOT_DEF_PROPERTY;
	}
}

LightJDoc.prototype.set_Property = function (nNameId, arArgs, objValue)
{
	switch (nNameId)
	{
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}
	return StdCore.S_OK;
}

LightJDoc.prototype.action = function (nObjID, nPropID, arVarArgs, objRetVal)
{
	if (StdCore._INIT_WVALUE == nPropID || null == objRetVal)
		return StdCore.E_NOT_DEF_PROPERTY;

	var nResult = StdCore.S_OK;

	try
	{
		if (-1 != nObjID)	// 일반 아톰
		{
			var objAtom = this.findAtomByScriptIndex(nObjID);
			nResult = objAtom.action (nPropID, arVarArgs, objRetVal);

			if (14 == nResult)
			{
				var strAtomType = objAtom.getAtomType();
				//System.out.println("미구현된 함수입니다.");
				//System.out.println("Atom : " + strAtomType + ", nPropID : " + nPropID);
			}
		}
		else
		{
			this.actionL (nPropID, arVarArgs, objRetVal);
		}
	}
	catch (e)
	{
		if (null != e.message)
		{
			alert("LightJDoc.action:" + e.message);
		}
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	return StdCore.S_OK;
}

LightJDoc.prototype.findAtomByScriptIndex = function (nScriptIndex)
{
	var objAtom = Model._atomsByIndex[nScriptIndex];
	
	return objAtom;
}

LightJDoc.prototype.getPropertyS = function (strObjName, nPropID, objRetVal)
{
	if (0 == strObjName.length || StdCore._INIT_WVALUE == nPropID || null == objRetVal) 
		return StdCore.E_NOT_DEF_PROPERTY;

	var nResult = StdCore.S_OK;
	try
	{
		if (StdCore._INIT_WVALUE == nPropID)
		{
			var nPropID1 = CScriptApp.getIDFromName (strObjName);
			
			var pAtom = this.findAtomByScriptIndex(nPropID1);
			//인자가 없는 경우 자식폼에서는 함수인지 속성인지 판단이 어려우므로 action을 호출하여 Getproperty까지 훓도록 한다.
			nResult = pAtom.action (nPropID, null , objRetVal); 
		}
		else   //아톰의 함수..
		{
			// 1. CScriptEntry를 받아온다..
			if (Utils.isEmpty(strObjName) || -1 == nPropID) 
				throw "LightJDoc.getPropertyS";

			/*
			 * 속성에 배열이 있을경우에 대한 처리 추가하였음
			 */
			var nIndex = -1;
			var nPos1 = strObjName.indexOf ("[") ;
			var nPos2 = strObjName.indexOf ("]") ;
			if (0 < nPos1 && nPos1 < nPos2)
			{
				var strTemp = strObjName.substring (nPos1 + 1, nPos2);
				nIndex = Utils.parseInt(strTemp);
				nIndex = this.getRealIndex (nIndex); //EBL 1Base지원

				strObjName = strObjName.substring(0, nPos1) + strObjName.substring(nPos2 + 1);
			}

			var nPropIDEx = -1;
			nPos1 = strObjName.indexOf ("[") ;
			nPos2 = strObjName.indexOf ("]") ;
			if (0 < nPos1 && nPos1 < nPos2)
			{
				var strTemp = strObjName.substring (nPos1 +1, nPos2 - nPos1 -1);
				nPropIDEx = Utils.parseInt(strTemp);
				nPropIDEx = this.getRealIndex (nPropIDEx); //EBL 1Base지원

				strObjName = strObjName.substring(0, nPos1);
			}

			var pAtom = Model.getAtom(strObjName);
			if (null != pAtom)
			{
				if (-1 < nIndex) //스크롤 아톰에 묶여 잇는 경우다
				{
					var objScroll = pAtom.getScrollAtom ();
					if (null == objScroll)
					{
						throw "LightJDoc.getPropertyS";
					}
					
					if (false == objScroll.isBindAtomAction (nPropID))
					{
						objScroll.getCellProperty (strObjName, nIndex, nPropID, objRetVal, nPropIDEx); // 속성[배열] 관련추가
					}
				}
				else
				{
					//인자가 없는 경우 자식폼에서는 함수인지 속성인지 판단이 어려우므로 action을 호출하여 Getproperty까지 훓도록 한다.
					nResult =  pAtom.action (nPropID, null, objRetVal);
				}
			}
			else
			{
				var strMessage = "[" + strObjName + "] 해당 아톰이 존재하지 않습니다.";
				alert (strMessage);
				
				throw "LightJDoc.getPropertyS";
			}
		}
	}
	catch (e)
	{
		nResult = StdCore.E_NOT_DEF_PROPERTY;
	}

	return nResult;
}

LightJDoc.prototype.setPropertyS = function (strObjName, nPropID, arArgs, pValue)
{
	if (0 == strObjName.length || StdCore._INIT_WVALUE == nPropID || null == pValue)
		return StdCore.E_NOT_DEF_PROPERTY;

	var nResult = StdCore.S_OK;
	try
	{
		if (StdCore._INIT_WVALUE == nPropID)
		{
			var nPropID1 = CScriptApp.getIDFromName (strObjName);

			var pAtom = this.findAtomByScriptIndex(nPropID1);
			nResult = pAtom.setProperty (nPropID, arArgs , pValue);					
		}
		else
		{
			// 1. CScriptEntry를 받아온다..
			if (Utils.isEmpty(strObjName) || -1 == nPropID)
				throw "LightJDoc.setPropertyS"; 
			
			// 속성에 배열이 있을경우에 대한 처리 추가하였음
			var nIndex = -2;
			var nPropIDEx = -2;
			var pValueEx = null;

			var nPos1 = strObjName.indexOf ("[") ;
			var nPos2 = strObjName.indexOf ("]") ;
			if (0 < nPos1 && nPos1 < nPos2)
			{
				var strTemp = strObjName.substring (nPos1 + 1, nPos2);
				nIndex = Utils.parseInt(strTemp);
				nIndex = this.getRealIndex (nIndex); //EBL 1Base지원

				strObjName = strObjName.substring(0, nPos1) + strObjName.substring(nPos2 + 1);

				nPos1 = strObjName.indexOf ("[") ;
				nPos2 = strObjName.indexOf ("]") ;

				if (0 < nPos1 && nPos1 < nPos2)
				{
					strTemp = strObjName.substring (nPos1 + 1, nPos2);
					nPropIDEx = Utils.parseInt (strTemp);
					nPropIDEx = this.getRealIndex (nPropIDEx);	//EBL 1Base지원 2007.07.05 이현숙
					pValueEx = new CVariantX(CVariantX._vtInt, nPropIDEx);
					strObjName = strObjName.substring(0, nPos1);
				}
			}
			else if (arArgs != null && nPropID == 0 && arArgs[0].toInt() == 1)
			{
				nIndex = arArgs[1].toInt ();
				nIndex = this.getRealIndex (nIndex); //EBL 1Base지원 2007.07.05 이현숙
			}

			var pAtom = Model.getAtom(strObjName);
			if (null != pAtom)
			{
				if (-2 < nIndex) //스크롤 아톰에 묶여 잇는 경우다
				{
					var objScroll = pAtom.getScrollAtom ();
					if (null == objScroll)
					{
						throw "LightJDoc.setPropertyS"; 
					}

					objScroll.cellPropertyChange (strObjName, nIndex, nPropID, pValue, pValueEx); // 속성[배열] 관련 추가 
				}
				else
					nResult = pAtom.setProperty (nPropID, arArgs, pValue);						
			}
			else
			{
				var strMessage = "[" + strObjName + "] 해당 아톰이 존재하지 않습니다.";
				alert (strMessage); 
				
				throw "LightJDoc.setPropertyS"; 
			}
		}
	}
	catch (e)
	{
		nResult = StdCore.E_NOT_DEF_PROPERTY;
	}

	return nResult;
}

LightJDoc.prototype.actionS = function (strObjName, nPropID, arArgs, objRetVal)
{
	if (Utils.isEmpty(strObjName) || null == objRetVal)
	{
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	var nResult = StdCore.S_OK;
	try
	{
		var pAtom = Model.getAtom(strObjName);
		if (StdCore._INIT_WVALUE == nPropID && null != pAtom)
		{
			nPropID = 0;
		}

		// 1. 사용자 함수일 경우
		if (StdCore._INIT_WVALUE == nPropID)
		{
			var nPropID1 = CScriptApp.getIDFromName (strObjName);
			if (StdCore._INIT_WVALUE != nPropID1)
			{
				// 자식폼.질의얻기(".....") 실행의 경우
				nResult = this.actionL (nPropID1, arArgs, objRetVal);
			}
			else
			{
				strObjName = "@" + strObjName;
				if (false == this.callMsgHandler(strObjName, arArgs, objRetVal))
				{
					nResult = StdCore.E_NOT_DEF_PROPERTY;
				}
			}
		}
		// 2. 아톰의 함수
		else
		{
			if (null != pAtom)
			{
				if (arArgs != null && nPropID == 0 && arArgs[0].toInt() == 1)
				{
					var nIndex = arArgs[1].toInt();
					nIndex = this.getRealIndex(nIndex);

					var objScroll = pAtom.getScrollAtom();
					if (null == objScroll)
					{
						throw "LightJDoc.actionS";
					}
					if (false == objScroll.isBindAtomAction(nPropID))
					{
						objScroll.getCellProperty (strObjName, nIndex, nPropID, objRetVal, -1);
					}
					else
					{
						//objScroll.bindAtomAction (strObjName, nIndex, nPropID, objRetVal);
					}
				}
				else
				{
					nResult = pAtom.action(nPropID, arArgs, objRetVal);
				}
			}
			else
			{
				throw "LightJDoc.actionS";
			}	
		}
	}
	catch (e)
	{
		nResult = StdCore.E_NOT_DEF_PROPERTY;
	}

	return nResult;
}	

LightJDoc.prototype.actionL = function (nPropID, arVarArgs, objRetVal)
{
	switch (nPropID)
	{
	case 11: case 225: return this.raw_UserDefineSQL(225, arVarArgs, objRetVal); // 질의실행 (DBServer와 통일하기 위해 이동함)
	case 16: case 233: return this.raw_Action(233, arVarArgs, objRetVal) ;// 닫기
	case 25: case 274: return this.raw_UserDefineSQL(274, arVarArgs, objRetVal); // 질의수정
	case 54: case 763: return this.raw_UserDefineSQL(763, arVarArgs, objRetVal); // 안전모드준비
	case 58: case 346: return this.raw_Action(346, arVarArgs, objRetVal); // DB동작: case 기본검색키동작
	default: return this.getProperty(nPropID, arVarArgs, objRetVal);
	}
}

/**
 * raw_UserDefineSQL
 * @param nNameId
 * @param arArgs
 * @param objRetVal
 * @return 스크립트 수행결과 코드
 */
LightJDoc.prototype.raw_UserDefineSQL = function (nNameId, arArgs, objRetVal)
{
	if (null == arArgs || 1 > arArgs.length)
	{
		return StdCore.E_NOT_MATCH_PARAM_CNT;
	}

	objRetVal.setValueType(CVariantX._vtInt, -1); // 반환값 초기화

	var strSQLName = Utils.trim(arArgs[1].toStringX());
	var objOuterQuery = g_objPQQuery.getOuterQueryByName(strSQLName);

	if (Utils.isEmpty(strSQLName) || null == objOuterQuery)
	{
		return StdCore.S_OK;
	}

	switch (nNameId)
	{
	case 763 : //질의실행완료
	case 225: // 질의실행
		this.m_objExeScript.runOuterQuery(objOuterQuery, arArgs, objRetVal);
		break;
	case 274: // 질의수정
	{
		if (4 > arArgs.length)
		{
			return StdCore.E_NOT_MATCH_PARAM_CNT;
		}
		this.m_objExeScript.modifyOuterQuery(objOuterQuery, arArgs, objRetVal);
		break;
	}
	case 275: // 질의얻기
		//getOuterQuery(objOuterQuery, objRetVal);
		break;
	case 508: // 질의초기화
		//initOuterQuery(objOuterQuery, objRetVal);
		break;
	default:
		return StdCore.E_NOT_DEF_PROPERTY;
	}

	return StdCore.S_OK;
}

LightJDoc.prototype.raw_Action = function (nNameId, arArgs, objRetVal)
{
	switch (nNameId)
	{
		case 346: // 기본검색키동작, DB동작
			objRetVal.setValueType(CVariantX._vtInt, 0);
			
			// 기본 검색키 동작전에 웹게시판과 웹스크롤은 전체페이지와 현페이지 카운트를 초기화한다.
			//initWebBoradScroll(objServiceParameter.getAtomParameter());s
			
			this.loadData(true, SQL_RECORD_TYPE.EQUAL_RECORD); // 데이터 로드
			
			break;
		default: return StdCore.E_NOT_DEF_PROPERTY;
	}
	return StdCore.S_OK;
}

LightJDoc.setFunctionObject = function (objFormExe)
{
	g_objDoc.setFormExe(objFormExe);
}


function ExeScript ()
{
	
}

ExeScript.prototype.runOuterQuery = function (objOuterQuery, arArgs, objRetVal)
{
	var strQuery = objOuterQuery.getQueryStatement();
	//strQuery = insertSubQuery(strQuery);
	
	strQuery = g_objPQQuery.convertQuery(strQuery);
	
	strQuery = g_objQueryAtom.replaceSearchQuery(strQuery);
	
	var nDBIndex = objOuterQuery.getDBIndex();
	
	// DB처리객체에서 만들어진 인자가 있는 저장프로시저의 경우
	var nSQLMode = objOuterQuery.getSQLKind();
	if (SqlMode._Procedure == nSQLMode)
	{
		if (0 > nDBIndex)
		{
			nDBIndex = 1;
		}
		
		this.completeProcedureParamInfo(objOuterQuery.getProcedureParamInfoList());
	}
	
	var nResult = this.executeOuterQuery(strQuery, nSQLMode, nDBIndex, objOuterQuery, arArgs);

	objOuterQuery.initModify();

	if (SqlMode._Select == nSQLMode)
	{
		//objOuterQueryParam.setLinkedVariables(objOuterQuery.getLinkedVariables());
	}
	
	objRetVal.setValueType(CVariantX._vtInt, nResult);
}

/**
 * 외부질의를 실행
 */
ExeScript.prototype.executeOuterQuery = function (strQuery, nSQLKind, nDBIndex, objOuterQuery, arArgs)
{
	var nUncertain = 0; // 알 수 없는 경우. 예를 들어 저장프로시저인데 리턴값이 있는지 없는지 알 수 없는 경우.
	var nExecute = 1; // insert, update, delete
	var nOpen = 2; // select
	var nProcedure = 3; // DB처리객체의 저장프로시저의 경우

	var nFail = -1; // 실행실패
	var nNoResult = 0; // 검색결과 없음
	var nYesResult = 1; // 검색결과 있음

	var nExeType = nUncertain; // 실행 타입
	var nResult = nFail;  // 질의실행결과

	switch (nSQLKind)
	{
	case SqlMode._Insert:
	case SqlMode._Update:
	case SqlMode._Delete:
		nExeType = nExecute;
		break;
	case SqlMode._Select:
		nExeType = nOpen;
		break;
	case SqlMode._Text:
		nExeType = (objOuterQueryParam.isLoadData()) ? nOpen : nUncertain;
		break;
	case SqlMode._Procedure:
		nExeType = nProcedure;
	}

	var strModuleKey = PQQuery.getModuleKey(nDBIndex);
	
	try
	{
		if (nExecute == nExeType)
		{
			if (SqlMode._Insert == nSQLKind)
			{
				g_objDataService.executeKeySQL(strQuery, 16, nDBIndex, strModuleKey, "_CheckDuplicate_", false);
			}
			else
			{
				g_objDataService.executeSQL(strQuery, 15, nDBIndex, strModuleKey);
			}
			// PQ 논리에 따라서 select 외에는 쿼리 실행이 성공하면 '검색결과있음'으로 설정한다.
			nResult = nYesResult;
		}
		else if (nUncertain == nExeType)
		{
			//쿼리의 사용법이 정해지지않은 경우에는 쿼리 실행 결과값이 무시된다.
			//매개변수가 없는 저장프로시저를 사용하면 select 또는 modify에 상관없이 쿼리를 실행할 수 있다.
//			g_objDataService.executeProcedure(strQuery, null, nDBIndex, strModuleKey, 
//					objServiceParameter.getUniqueID(), objServiceParameter.isPortalService());

			nResult = nYesResult;
		}
		else if (nOpen == nExeType)
		{
			var dtResult = g_objDataService.executeOpenX(strQuery, 13, nDBIndex, strModuleKey);
			
			if (null != dtResult)
			{
				this.handleOuterQuery(dtResult, nSQLKind, objOuterQuery, arArgs);
			}
			
			nResult = (null == dtResult || 0 >= dtResult.m_arRows.length) ? nNoResult : nYesResult;
		}
		else if (nProcedure == nExeType)
		{
			var arParams = this.makeProcedureParam(objOuterQuery.getProcedureParamInfoList());
			var dtResult = g_objDataService.executeProcedure(strQuery, 17, nDBIndex, strModuleKey, arParams);
			
			if (null != dtResult)
			{
				this._handleProcedureParam(dtResult);
			}

			nResult = (null == dtResult || null == dtResult.rowData || 0 >= dtResult.rowData.length)? nNoResult : nYesResult;
		}
	}
	catch (e)
	{
		alert ("ExeScript.prototype.executeOuterQuery:" + e.message);
		nResult = nFail;
	}
	
	return nResult;
}

ExeScript.prototype.handleOuterQuery = function (dtTable, nSQLMode, objOuterQuery, arArgs)
{
	if (SqlMode._Select == nSQLMode || SqlMode._Text == nSQLMode || SqlMode._Procedure == nSQLMode)
	{
		// SELECT 문일 경우 - 변수연결아톰에 값 설정 후 연산식 수행
		this.fillQueryDataAtAtom(dtTable, objOuterQuery.getLinkedVariables());
		
		/*
		var arParam = objDataTable.param;
		if (null != arParam && 0 < arParam.length)
		{
			// PROCEDURE 일 경우 - 변수연결아톰에 값 설정 후 연산식 수행
			this.fillQueryParamAtAtom();
		}
		*/
		
		// 데이터 받아오기
		this.handleReturnValue(arArgs, dtTable, objOuterQuery.getSQLIndex());
	}
}

/**
 * Select 쿼리의 결과를 변수 연결이 설정 되어있는 아톰의 값으로 넣는다.
 * @param arData - 변수연결 되어 있는 아톰에 넣을 데이터
 * @param strLinkedVarNames - 변수연결되어 있는 아톰변수명들
 */
ExeScript.prototype.fillQueryDataAtAtom = function (dtTable, strLinkedVarNames)
{
	var arData = dtTable.getRows();
	if (null == arData || arData.length < 1)
	{
		return;
	}
	
	var arVarNames = this.getConnectedVarNames(strLinkedVarNames);
	var arFirstRowData = arData[0];

	if (arVarNames.length < 1 || null == arFirstRowData || 0 == arFirstRowData.length)
	{
		return;
	}
	
	var nDataLength = arData.length;

	for (var nVarNameIndex = 0; nVarNameIndex < arVarNames.length; nVarNameIndex++)
	{
		var strVarName = arVarNames[nVarNameIndex];

		var objAtom = Model.getAtom(strVarName);
		
		if (null != objAtom)
		{
			if (objAtom.isScroll && objAtom.isScroll())
			{
				var objScroll = Model.getAtom(objAtom.getScrollName());
				
				var nScrollRow = objScroll.m_arRowList.length;
				if (nScrollRow < nDataLength)
				{
					objScroll._expandRow(nDataLength - nScrollRow);
				}
				
				// 결과값 설정
				for (var nRowIndex = 0; nRowIndex < nDataLength; nRowIndex++)
				{
					var arRowData = arData[nRowIndex];
					var strValue = arRowData[nVarNameIndex];
					
					objScroll.setRowBindedValue(nRowIndex, strVarName, strValue);
	
					//m_objServiceParameter.getOperation().executeScrollOperation(strVarName, nRowIndex);
				}
				
				objScroll._changeAttributeRelationAtom();
			}
			else
			{
				// 스크롤이 아닐 때는, 첫번째 줄의 데이터만 유효하다.
				var strValue = arFirstRowData[nVarNameIndex];

				this.setFieldValue (objAtom, strValue);

				// 연산식 수행
				//m_objServiceParameter.getOperation().executeAtomOperation(objAtomParam, objAtomParameter);
			}
		}
	}
}

/**
 * 변수연결 문장을 파싱하여, 변수명의 리스트를 리턴한다.
 * 변수 형태는 '#변수명' 또는 '?변수명?'이다. 변수 사이는 ','로 구분된다.
 * @param strValueStmt
 * @return 변수명들.
 */
ExeScript.prototype.getConnectedVarNames = function (strValueStmt)
{
	var arVarNames = strValueStmt.split(",");

	for (var i = 0; i < arVarNames.length; i++)
	{
		var strVarName = Utils.trim(arVarNames[i]);

		if (Utils.isEmpty(strVarName))
		{
			continue;
		}

		if (0 == strVarName.indexOf("#"))
		{
			strVarName = strVarName.substring(1);
		}
		else if (0 == strVarName.indexOf("?") && strVarName.length - 1 == strVarName.lastIndexOf("?"))
		{
			strVarName = strVarName.substring(1, strVarName.length - 1);
		}

		arVarNames[i] = strVarName;
	}

	return arVarNames;
}

ExeScript.prototype.setFieldValue = function (objAtom, strValue)
{
	strValue = Utils.trim(strValue);
	
	var strFieldType = objAtom.getFieldType();

	// 정수일 경우 소수점 이하를 제거해줌...
	if ("int" == strFieldType)
	{
		var nPosP = strValue.indexOf ('.');
		if (-1 < nPosP)
			strValue = strValue.substring (0 , nPosP);
	}
	else if (objAtom.getFieldLen)
	{
		var nFieldLen  = objAtom.getFieldLen();
		
		if (nFieldLen < strValue.length)
		{
			if (ContainsInputTimeAtom() && objAtom instanceof InputTimeAtom)
			{
				strValue = strValue.replace ("-", "");   //datetime 으로 올라올경우
				strValue = strValue.replace ("/", "");
			}
			else
			{
				strValue = strValue.substring (0, nFieldLen);
			}
		}
	}
	
	objAtom.setValue(strValue);
}

/**
 * 저장프로시저의 결과를 변수연결 되어있는
 * 스크립트 변수 또는 아톰에 값을 설정한다.
 */
ExeScript.prototype.fillQueryParamAtAtom = function ()
{
	
}

/**
 * 폼_질의실행()한 결과를 스크립트변수로 저장한다.
 * @param arArgs
 * @param objDataTable
 * @param bLoadData
 */
ExeScript.prototype.handleReturnValue = function (arArgs, dtTable, nSQLIndex)
{
	var nArgcount = arArgs[0].toInt();

	/**
	 * 1.  0, 1 : 0번행의 데이터를 받아온다.
	 * 2.  n : n개의 행의 데이터를 받아온다.
	 * 3. -1 : 전체 데이터를 받아온다.
	 */
	var nGetRows = (2 < nArgcount) ? arArgs[3].toInt() : -1; // 받아올 행의 갯수.
	if (0 == nGetRows || 1 == nGetRows) // 첫행의 첫번째 데이터만 넘긴다. 
	{
		var objDRServer = new CDataRowServer(this.isEBLSource());

		if (0 == nGetRows) // 첫행 첫번째 데이터 받아가는 경우 
		{
			var pvaReArgs = new Array (2);
			pvaReArgs [0] = new CVariantX (CVariantX._vtInt, 1);	//인자 갯수
			pvaReArgs [1] = new CVariantX (CVariantX._vtInt, 0);	//받아올 데이터의 ID
			
			objDRServer.get_Value (pvaReArgs, arArgs [2]);
		}
		else
		{
			arArgs [2].setValue (objDRServer);
			g_objDoc.addQueryResult (nSQLIndex, objDRServer);
		}
	}
	else // 객체배열로 맹근다.
	{
		var objDTServer = new CDataTableServer(true);

		if (1 < nGetRows)
		{
			var nRowCount = dtTable.getRowCount();
			while (nGetRows < nRowCount)
			{
				//objDataTable = JBinDataTableHelper.removeRow(objDataTable, nGetRows);
				//nRowCount = dtTable.getRowCount();
			}
		}

		objDTServer.attach(dtTable);
		arArgs[2].setValueType(CVariantX._vtExeServer, objDTServer);
		
		g_objDoc.addQueryResult (nSQLIndex, objDTServer);
	}

	arArgs[2].setOutputParam(true); // Output 인자임을 표시한다..
}

ExeScript.prototype.modifyOuterQuery = function (objOuterQuery, arArgs, objRetVal)
{
	var nArgCount = arArgs[0].toInt();

	// #실행테이블(1103), #실행조건(1104), #그룹기준(1105), #정렬기준(1106), #결합문장(1107), #실행필드(1108), #입력변수(1109)
	var nModifyPart = (1 < nArgCount) ? arArgs[2].toInt() : 0;
	var bApp = (arArgs[3].toInt() == 1) ? true : false;
	var bAppend = (2 < nArgCount) ? bApp : false;
	var strModifyStatement = (3 < nArgCount) ? (arArgs[4].toStringX()) : "";
	
	if (Utils.isEmpty(strModifyStatement))
	{
		return;
	}
	
	objOuterQuery.setModifyQuery(nModifyPart, strModifyStatement, bAppend);
}

/**
 * 저장 프로시저 매개변수에 연결되어있는 아톰변수의 값을 대체해준다.
 */
ExeScript.prototype.completeProcedureParamInfo = function (arParamInfo)
{
	if (null != arParamInfo)
	{
		for (var i = 0 ; i < arParamInfo.length; i+=1)
		{
			var objParamInfo = arParamInfo[i];
			
			// 상수가 아닌 변수, 즉 아톰에 연결된 변수 일때
			if (false == objParamInfo.getIsConstant())
			{
				var strProperVarName = objParamInfo.getProperVarName();
				var objAtom = Model.getAtom(strProperVarName);
				
				var strAtomType = "";
				if (null != objAtom)
				{
					strAtomType = objAtom.getAtomType();
				}

				// 입력란일 경우 값을 대체해주고
				if ("InputData" == strAtomType)
				{
					var strValue = objAtom.getValue();
					
					// 값이 있고 길이가 0이 아니면 대체해주고
					if (null != strValue && 0 != strValue.length)
					{
						objParamInfo.setValue(strValue);
					}
					// 값이 없거나 길이가 0이면 값은 NULL
					else
					{
						objParamInfo.setValue("NULL");
					}
				}
				// 입력란이 아닐 경우 값은 스크립트 변수에서 찾는다.
				else
				{
					if (null != g_htScriptVarMap)
					{
						var strAtomValue = "NULL";
						
						var nSymbolId = g_htScriptVarMap[strProperVarName];
						if (null != nSymbolId)
						{
							strAtomValue = g_objDoc.getSymbolValue(nSymbolId);
							
							if (Utils.isEmpty(strAtomValue))
							{
								// @없이, 스크롤에 묶인 변수명만 설정된 경우
								// 스크롤 아톰 하나씩 검사해서 찾음,  검색창의 항목변수도 필요하면 추가해야함
								//strValue = objAtomParameter.getScrollBindedVarNameValue(strProperVarName);
							}
						}
						
						objParamInfo.setValue(strAtomValue);								
					}
				}
			}
		}
	}
}

/**
 * 저장 프로시저 매개변수를 알맞은 형태로 만든다.
 * 
 * @param procedureParamInfo
 * @return String[][] {{매개변수명, 변수자료형, 변수길이, 값,입출력방향}+}.
 */
ExeScript.prototype.makeProcedureParam = function (alProcedureParamInfo)
{
	var arParams = null;
	if (null != alProcedureParamInfo)
	{
		arParams = new Array (alProcedureParamInfo.length);
		var nIndex = 0;
		
		for (var i = 0; i < alProcedureParamInfo.length; i+=1)
		{
			var objParamInfo = alProcedureParamInfo[i];
			
			arParams[nIndex] = new Array (5);
			
			// 매개변수명
			arParams[nIndex][0] = objParamInfo.getParamName();
			// 매개변수 자료형
			arParams[nIndex][1] = objParamInfo.getDataType();
			// 매개변수 길이
			arParams[nIndex][2] = objParamInfo.getDataLength();
			// 매개변수 값
			arParams[nIndex][3] = objParamInfo.getValue();
			// 입출력 방향
			arParams[nIndex][4] = objParamInfo.getParamDirection();

			nIndex += 1;
		}
	}
	return arParams;
}

ExeScript.prototype._handleProcedureParam = function (dtResult)
{
	if (null != dtResult.m_arParam && 0 < dtResult.m_arParam.length)
	{
		var arParam = dtResult.m_arParam;
		for (var i = 0; i < arParam.length; i++)
		{
			var strVarName = arParam[i][0];
			var strValue = arParam[i][3];
			var strDirection = arParam[i][4];
			
			var objAtom = Model.getAtom(strVarName);
			if (null != objAtom)
			{
				objAtom.setValue(strValue);
			}
		}
	}
}

/**
 * sp쿼리를 실행한다.
 */
ExeScript.prototype.executeProcedure = function (objDBIOParam)
{
	var nDBIndex = objDBIOParam.getDBIndex();
	var strModuleKey = PQQuery.getModuleKey(nDBIndex);
	var arParam = objDBIOParam.getParam();
	
	var dtResult = g_objDataService.executeProcedure(objDBIOParam.getQuery(), 17, nDBIndex, strModuleKey, arParam);
	
	if (null != dtResult)
	{
		objDBIOParam.setResult(dtResult.m_arRows);
	}
}


////////////////////////////////////////////////
// DataService
//
g_objDataService = new DataService ();

function DataService ()
{
}

DataService.prototype._makeRequest = function (strEventName, strQuery, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = MakeRequest.createRequestNode();
	var xnQueryRequest = XmlLib.createChild(xnRequest, "WebQuery");
	
	strQuery = Utils.encodeBase64(strQuery);
	XmlLib.setAttribute(xnQueryRequest, "Statement", strQuery);
	XmlLib.setAttribute(xnQueryRequest, "EventName", strEventName);
	XmlLib.setAttribute(xnQueryRequest, "UniqueID", nUniqueID);
	XmlLib.setAttribute(xnQueryRequest, "DBIndex", nDBIndex);
	XmlLib.setAttribute(xnQueryRequest, "ModuleKey", strModuleKey);
	
	return xnRequest;
}

DataService.prototype._executeService = function (xnRequest)
{
	var strURL = "/ups/WebQueryService.do?pn=" + GetProjectName() + "&clk=" + GetCommonLoginKey() + "&ServiceName=executeWebQueryService";
	
	// 요청이 최상위 document이여야 한다.
	if ("#document" != xnRequest.nodeName)
	{
		xnRequest = xnRequest.ownerDocument;
	}
	
	var strResult = PQAjax.post(strURL, xnRequest);
	
	return XmlLib.loadXMLFromString(strResult);
}

DataService.prototype.executeOpenScalarX = function (strQuery, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = this._makeRequest("Scalar", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnResult = this._executeService(xnRequest);
	
	var xnValue = null;
	
	if (is_android || is_firefox)
	{
		var xnWebQuery = XmlLib.selectSingleNode(xnResult, "//WebQuery");
		xnValue = XmlLib.selectSingleNode(xnWebQuery, "/Result");
	}
	else
	{
		xnValue = XmlLib.selectSingleNode(xnResult, "//WebQuery/Result");
	}
	
	if (null != xnValue)
	{
		return XmlLib.getTextValue(xnValue);
	}
	return "";
}

DataService.prototype.executeOpenRowX = function (strQuery, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = this._makeRequest("DataRow", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnResultTop = this._executeService(xnRequest);
	
	var xnResult = null;
	
	if (is_android || is_firefox)
	{
		var xnWebQuery = XmlLib.selectSingleNode(xnResultTop, "//WebQuery");
		xnResult = XmlLib.selectSingleNode(xnWebQuery, "/Result");
	}
	else
	{
		 xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
	}
	
	if (null != xnResult)
	{
		var arResult = new Array();
		
		for (var i = 0; i < xnResult.childNodes.length; i+=1)
		{
			var strColValue = XmlLib.getTextValue(xnResult.childNodes[i]);
			
			arResult.push(strColValue);
		}
		
		return arResult;
	}
	return null;
}

DataService.prototype.executeOpenX = function (strQuery, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = this._makeRequest("DataTable", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnResultTop = this._executeService(xnRequest);
	
	var xnResult = null;
	
	if (is_android || is_firefox)
	{
		var xnWebQuery = XmlLib.selectSingleNode(xnResultTop, "//WebQuery");
		xnResult = XmlLib.selectSingleNode(xnWebQuery, "/Result");
	}
	 else
	{
		 xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
	}
	
	if (null != xnResult)
	{
		return this._handleDataTableResult(xnResult);
	}
	return null;
}

DataService.prototype._handleDataTableResult = function (xnResult)
{
	var strTableName = XmlLib.getAttribute(xnResult, "tableName");
	var nRowCount = Utils.parseInt(XmlLib.getAttribute(xnResult, "rowCount"));
	var nColCount = Utils.parseInt(XmlLib.getAttribute(xnResult, "colCount"));
	
	var arResult = new Array();
	var alRows = XmlLib.selectNodeList(xnResult, "./Row")
	
	for (var i = 0; i < alRows.length; i+=1)
	{
		var arCols = new Array();
		var xnRow = alRows[i];
		
		for (var c = 0; c < xnRow.childNodes.length; c+=1)
		{
			var strColValue = XmlLib.getTextValue(xnRow.childNodes[c]);
			
			arCols.push(strColValue);
		}
		
		arResult.push(arCols);
	}
	
	var xnColName = XmlLib.selectSingleNode(xnResult, "./colName");
	var strColName = XmlLib.getTextValue(xnColName); 
	var arColName = strColName.split(";");
	
	var xnColType = XmlLib.selectSingleNode(xnResult, "./colType");
	var strColType = XmlLib.getTextValue(xnColType); 
	var arColType = strColType.split(";");
	
	var objDataTable = new DataTable (strTableName, arResult, arColName, arColType);
	
	return objDataTable;
}

DataService.prototype.executeTranSQL = function (strQueries, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = this._makeRequest("TransactionEx", strQueries, nUniqueID, nDBIndex, strModuleKey);
	
	var xnResultTop = this._executeService(xnRequest);
	
	//var xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
}

DataService.prototype.executeSQL = function (strQuery, nUniqueID, nDBIndex, strModuleKey)
{
	var xnRequest = this._makeRequest("Transaction", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnResultTop = this._executeService(xnRequest);
	
	//var xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
}

/**
 * 자동증가인 기본검색키를 증가시키며 쿼리 실행
 */
DataService.prototype.executeKeySQL = function (strQuery, nUniqueID, nDBIndex, strModuleKey, strRealValue, bContinueTransaction) 
{
	var xnRequest = this._makeRequest("TransactionKeyPortal", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnQueryRequest = XmlLib.selectSingleNode(xnRequest, "./WebQuery");
	XmlLib.setAttribute(xnQueryRequest, "RealValue", strRealValue);
	XmlLib.setAttribute(xnQueryRequest, "ContinueTransaction", bContinueTransaction ? "true" : "false");
	
	var xnResultTop = this._executeService(xnRequest);
	
	var xnResult = null;
	
	if (is_android || is_firefox)
	{
		var xnWebQuery = XmlLib.selectSingleNode(xnResultTop, "//WebQuery");
		xnResult = XmlLib.selectSingleNode(xnWebQuery, "/Result");
	}
	 else
	{
		 xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
	}
	
	if (null != xnResult)
	{
		return XmlLib.getTextValue(xnResult);
	}
}

/**
 * 저장 프로시져 쿼리를 실행시킨다.
 */
DataService.prototype.executeProcedure = function (strQuery, nUniqueID, nDBIndex, strModuleKey, arParams) 
{
	var xnRequest = this._makeRequest("Procedure", strQuery, nUniqueID, nDBIndex, strModuleKey);
	
	var xnQueryRequest = XmlLib.selectSingleNode(xnRequest, "./WebQuery");
	var xnParamTop = XmlLib.createChild(xnQueryRequest, "ParamInfo");
	
	for (var i = 0; i < arParams.length; i+=1)
	{
		var arParam = arParams[i];
		var xnParam = XmlLib.createChildWithValue(xnParamTop, "Param", arParam[0])
		
		XmlLib.setAttribute(xnParam, "DataType", arParam[1]);
		XmlLib.setAttribute(xnParam, "DataLength", arParam[2]);
		XmlLib.setAttribute(xnParam, "Value", arParam[3]);
		XmlLib.setAttribute(xnParam, "Direction", arParam[4]);
	} 
	
	var xnResultTop = this._executeService(xnRequest);
	
	var xnResult = null;
	
	if (is_android || is_firefox)
	{
		var xnWebQuery = XmlLib.selectSingleNode(xnResultTop, "//WebQuery");
		xnResult = XmlLib.selectSingleNode(xnWebQuery, "/Result");
	}
	 else
	{
		 xnResult = XmlLib.selectSingleNode(xnResultTop, "//WebQuery/Result");
	}
	if (null != xnResult)
	{
		var objDataTable = this._handleDataTableResult(xnResult);
		
		// Parameter 처리
		var xnParam = XmlLib.selectSingleNode(xnResult, "./param");
		
		if (null != xnParam)
		{
			objDataTable.m_arParam = new Array();
			
			for (var j = 0; j < xnParam.childNodes.length; j++)
			{
				var strRow = XmlLib.getTextValue(xnParam.childNodes[j]);
				
				var arRow = strRow.split(";");
				
				objDataTable.m_arParam.push(arRow);
			}
		}
		
		return objDataTable;
	}
	return null;
}

g_objQueryLib = new SqlQueryLib();
g_objQueryAtom = new QueryAtom();

function QueryAtom ()
{
}

QueryAtom.prototype.getSelectQueryString = function (objSelectQuery, eEvent)
{
	var strQuery = "";
	if (SQL_RECORD_TYPE.PREV_RECORD == eEvent)
	{
		strQuery = objSelectQuery.getPrevQuery();
	}
	else if (SQL_RECORD_TYPE.NEXT_RECORD == eEvent)
	{
		strQuery = objSelectQuery.getNextQuery();
	}
	else if (SQL_RECORD_TYPE.EQUAL_RECORD == eEvent || SQL_RECORD_TYPE.LOCK_RECORD == eEvent)
	{
		strQuery = objSelectQuery.getNormalQuery();
	}

	strQuery = g_objPQQuery.convertQuery(strQuery);

	// 공통문법, 고유변수 치환
	strQuery = this.replaceInputQuery(strQuery);

	return strQuery;
}

QueryAtom.prototype.replaceInputQuery = function (strQueryStatement)
{
	var strQuery = g_objQueryLib.getDBMSQuery(strQueryStatement);

	strQuery = g_objQueryLib.replaceAtomVarName(strQuery, false);

	return strQuery;
}

QueryAtom.prototype.replaceSearchQuery = function (strQueryStatement)
{
	var strQuery = strQueryStatement;
	
	if (g_objQueryLib.isCommonSQL(strQuery))
	{
		strQuery = g_objQueryLib.getDBMSQuery(strQuery);
	}
	
	return g_objQueryLib.replaceAtomVarName(strQuery, false);
}

QueryAtom.prototype.getBrowseQuery = function (nSQLIndex)
{
	var objOuterQuery = g_objPQQuery.getOuterQueryByIndex(nSQLIndex);
	
	if (null == objOuterQuery)
	{
		return null;
	}
	else
	{
		this._processWhereStatement(objOuterQuery)
		return objOuterQuery;	
	}
}

/**
 * 게시판은, 검색식, 수행조건 사용하지 않고, 기본조건 설정 기능 포함되어 있음
 */
QueryAtom.prototype._processWhereStatement = function (objOuterQuery)
{
	var strWhere = objOuterQuery.getAppendWhere();

	if (false == Utils.isEmpty(strWhere))
	{
		objOuterQuery.setAppendWhere(objOuterQuery.executeTableAliasing(strWhere));
	}
}


/**
 * SqlQueryLib
 */
function SqlQueryLib ()
{
	this.m_saOwnerList = new Array();
	
	this.m_objMSSQL = new CToMSSQL();
	
	this.m_objOracle = new CToOracle();
}

SqlQueryLib.prototype.getOwnerList = function ()
{
	return this.m_saOwnerList;
}

SqlQueryLib.prototype.isCommonSQL = function (strQuery)
{
	if (-1 < strQuery.indexOf ("[") || -1 < strQuery.indexOf ("_OWNER_"))
		return true;
	return false;
}

/**
 * SQL 모델 정보가 있으면 모델에 있는 모듈키 정보를 사용해서 쿼리를 생성한다.
 * 모델 정보가 없으면 StateManager에 있는 모듈키 정보를 사용한다.
 */
SqlQueryLib.prototype.getDBMSQuery = function (strOrgSql)
{
	if (null != g_objPQQuery)
	{
		var arModuleKeys = g_objPQQuery.getModuleKeys();
		
		if (null != arModuleKeys)
		{
			return this.getDBMSQueryString (strOrgSql, arModuleKeys, false);
		}
	}
	return this.getDBMSQueryString (strOrgSql, objStateMan.getDBIndexToKeyArray(), false);
}

SqlQueryLib.prototype.getDBMSQueryString = function (strOrgSql, arDBIndexToKey, bCond)
{
	var bIsOracle9i = false;	//objStateMan.isOracle9i(nDBKind);

	for (var i = 0; i < arDBIndexToKey.length; i++)
	{
		this.getOwnerList().push(g_arDBNameOwner[arDBIndexToKey[i]]);
	}
	
	return this.doMakeQuery(strOrgSql, bCond, g_nDBKind, false, g_arDBNameOwner[1]);
}

SqlQueryLib.prototype.getOwnerWithDBName = function (strDBName)
{
	for (var i = 0; i < g_arDBName.length; i++)
	{
		if (g_arDBName[i] == strDBName)
		{
			return g_arDBNameOwner[i];
		}
	}
	return strDBName;
}

SqlQueryLib.prototype.doMakeQuery = function (strOldSource, bCond, nDBKind, bIs9i, strOwner)
{
	if (null == strOldSource || 0 == strOldSource.length)
		return strOldSource;
	
	var strCopySQL = strOldSource;

	var strResult = "";
	if (bCond)
	{
		var nIndex = strOldSource.indexOf("$");
		if (-1 < nIndex && nIndex <= strOldSource.length)
		{
			var strJoin = strOldSource.substring(nIndex);
			strOldSource   = strOldSource.substring(0, nIndex);
			strJoin		   = strJoin.replace("$", " ");
			strJoin        = strJoin.replace("##", "#TABLE#");

			strOldSource = "SELECT * FROM " + strJoin + " WHERE " + strOldSource;
		}
		else if (-1 == nIndex)
		{
			strOldSource = "SELECT * FROM #TABLE# WHERE " + strOldSource;
		}
	}

	if (0 == nDBKind)
	{
		strResult = this.m_objMSSQL.doAnalize(strOldSource);
	}
	else if (1 == nDBKind)
	{
		var bHasWhere = this._isHasWhere (strCopySQL, bCond); // Where 절이 있는지 여부..
		strResult = this.doToOracle (strOldSource, bHasWhere);
	}
	else
	{
		strResult = strOldSource;
	}

	if (bCond)
	{
		var nWhere 	= strResult.indexOf("WHERE");
		var nFrom 	= strResult.indexOf("FROM");

		if (-1 < nFrom && nFrom < nWhere && nWhere <= strResult.length) //2005.07.05
		{
			var strFrom = strResult.substring(nFrom + 4, nWhere - nFrom - 4);
			strFrom = Utils.replaceAll(strFrom, "#TABLE#", "");
			strFrom = Utils.trim(strFrom);

			if (null != strFrom && 0 < strFrom.length && 1 <= strFrom.length && "," == strFrom.substring(0, 1))
			{
				strFrom = strFrom.substring (1);
				strFrom = strFrom.trim ();
			}

			if (strFrom == "_OWNER_")
				strFrom = "";

			if ("" != strFrom && nWhere + 5 <= strResult.length)
				strResult = strResult.substring(nWhere + 5) + "$" + strFrom;
			else if (nWhere + 5 <= strResult.length)
				strResult = strResult.substring(nWhere + 5);
		}
		else if (nWhere + 5 <= strResult.length)
			strResult = strResult.substring(nWhere + 5);
	}

	strResult = Utils.trim(strResult);
	return strResult;
}

SqlQueryLib.prototype._isHasWhere = function (strOldSource, bCondition)
{
	var strWhere = "";
	if (false == bCondition)
	{
		strOldSource = Utils.replaceAll(strOldSource, "\n", " ");
		var nPosW = strOldSource.toUpperCase().indexOf (" WHERE ");
		if (-1 < nPosW)
			strWhere = strOldSource.substring (nPosW + 7);
	}
	else
	{
		strWhere = strOldSource;
	}
	strWhere = Utils.trim(strWhere);
	
	if ("" == strWhere)
		return false;

	var nPos = strWhere.indexOf ("$");
	if (-1 < nPos)
	{
		strWhere = Utils.trim(strWhere.substring (0, nPos));
		if (0 < strWhere.length)
			return true;
		return false;
	}
	return true;
}

/**
 * 쿼리에 포함된 아톰변수명 키워드를 해당 아톰의 값으로 치환한다.
 * 예) 아톰변수명 = "value" 일 때
 * '?아톰변수명?' -> 'value'
 * '[아톰변수명]' -> 'value'
 * '#아톰변수명' -> 'value'
 */
SqlQueryLib.prototype.replaceAtomVarName = function (strQuery, bInsert)
{
	if (Utils.isEmpty(strQuery))
	{
		return strQuery;
	}

	// #스크롤관계설정_AtomVarName -> AtomVarName으로 변경한다.
	strQuery = strQuery.replace("#스크롤관계설정_", "#");

	// where 절 위치 : 아톰의 값이 없을 때, is null 로 변환할지 여부를 결정할 때 사용한다.
	var nWherePosition = strQuery.indexOf(" WHERE ");

	bNullDelete = false;
	var nMovingMode = 0;
	var nQuestionMode = 1; //?아톰변수명?
	var nBracketMode = 2; //[아톰변수명]
	var nSharpMode = 3; //#아톰변수명
	var nPreDollarMode = 4; //$키워드를 발견하고 다음 문자가 %임을 확인함. %로 이동 후 nDollarMode로 전환.
	var nDollarMode = 5; //$%아톰변수명 까지 진행
	var nPostDollarMode = 6; //nDollarMode 진행 중 %발견하고 다음 문자가 $임을 확인함.
	var nCurrentMode = nMovingMode;

	var strQueryBuilder = "";
	var strAtomVarNameBuilder = "";

	for (var i = 0; i < strQuery.length; i+=1)
	{
		bNullDelete = false;
		var bWhere = (0 < nWherePosition && nWherePosition < i);
		
		var chChar = strQuery.charAt(i); 
		if ('?' == chChar)
		{
			if (nMovingMode == nCurrentMode)
			{
				nCurrentMode = nQuestionMode;
			}
			else if (nQuestionMode == nCurrentMode)
			{
				var strAtomVarName = strAtomVarNameBuilder.substring(1);

				strQueryBuilder = this.replaceRealValueToBuffer(strQueryBuilder, strAtomVarName, bWhere, bInsert);

				strAtomVarNameBuilder = "";
				nCurrentMode = nMovingMode;
				continue;
			}
		}
		else if ('[' == chChar)
		{
			if (nMovingMode == nCurrentMode)
			{
				nCurrentMode = nBracketMode;
			}
		}
		else if (']' == chChar)
		{
			if (nBracketMode == nCurrentMode)
			{
				var strAtomVarName = strAtomVarNameBuilder.substring(1);

				strQueryBuilder = this.replaceRealValueToBuffer(strQueryBuilder, strAtomVarName, bWhere, bInsert);

				strAtomVarNameBuilder = "";
				nCurrentMode = nMovingMode;
				continue;
			}
		}
		else if ('#' == chChar)
		{
			if (nMovingMode == nCurrentMode)
			{
				nCurrentMode = nSharpMode;
			}
		}
		else if ('$' == chChar)
		{
			if (nMovingMode == nCurrentMode)
			{
				var nNextCharIndex = i + 1;
				if (nNextCharIndex < strQuery.length)
				{
					var chNextChar = strQuery.charAt(nNextCharIndex);
					if ('%' == chNextChar)
					{
						nCurrentMode = nPreDollarMode;
					}
				}
			}
			else if (nPostDollarMode == nCurrentMode)
			{
				var strAtomVarName = strAtomVarNameBuilder;
				strAtomVarName = strAtomVarName.substring(2, strAtomVarName.lastIndexOf("%"));

				if (strAtomVarName.charAt(0) == '?' && strAtomVarName.charAt(strAtomVarName.length - 1) == '?')
				{
					strAtomVarName = strAtomVarName.substring(1, strAtomVarName.length - 1);
				}

				strQueryBuilder = this.replaceRealValueToBuffer(strQueryBuilder, strAtomVarName, bWhere, bInsert);

				strAtomVarNameBuilder = "";
				nCurrentMode = nMovingMode;
				continue;
			}
		}
		else if ('%' == chChar)
		{
			if (nPreDollarMode == nCurrentMode)
			{
				nCurrentMode = nDollarMode;
			}
			else if (nDollarMode == nCurrentMode)
			{
				var nNextCharIndex = i + 1;
				if (nNextCharIndex < strQuery.length)
				{
					var chNextChar = strQuery.charAt(nNextCharIndex);
					if ('$' == chNextChar)
					{
						nCurrentMode = nPostDollarMode;
					}
				}
			}
		}
		else if (' ' == chChar || '\'' == chChar || '"' == chChar || 
				',' == chChar || '\t' == chChar || '\n' == chChar || ')' == chChar)
		{
			if (nSharpMode == nCurrentMode)
			{
				var strAtomVarNameToken = strAtomVarNameBuilder.substring(1);
				strQueryBuilder = this.replaceRealValueToBuffer(strQueryBuilder, strAtomVarNameToken, bWhere, bInsert);
				
				strAtomVarNameBuilder = "";
				nCurrentMode = nMovingMode;
				
				if (bNullDelete)
				{
					continue;
				}
			}
		}

		switch (nCurrentMode)
		{
			case nMovingMode:
			{
				strQueryBuilder += chChar;
				break;
			}
			default:
			{
				strAtomVarNameBuilder += chChar;
				break;
			}
		}
	}

	if (nQuestionMode == nCurrentMode || nBracketMode == nCurrentMode || nDollarMode == nCurrentMode)
	{
		strQueryBuilder += strAtomVarNameBuilder;
	}
	else if (nSharpMode == nCurrentMode)
	{
		var strAtomVarName = strAtomVarNameBuilder.substring(1);

		strQueryBuilder = this.replaceRealValueToBuffer(strQueryBuilder, strAtomVarName, 0 < nWherePosition, bInsert);
	}
	
	return this.treatEmptyString(strQueryBuilder);
}

/**
 * 변수명에 해당하는 아톰값을 가져와서 쿼리를 변경한다.
 * 값이 없을 경우에, 자료형에 따라서 쿼리를 처리해 준다.
 */
SqlQueryLib.prototype.replaceRealValueToBuffer = function (strQueryBuilder, strVarName, bWhere, bInsert)
{
	var strTempVarName = "";

	bNullDelete = false;
	var bAutoIncrease = false;
	var nAutoIncreaseMarkStart = strVarName.indexOf('<');
	var nAutoIncreaseMarkClose = strVarName.indexOf('>');
	// 자동증가 마크가 있을 때
	if (0 == nAutoIncreaseMarkStart && -1 != nAutoIncreaseMarkClose)
	{
		bAutoIncrease = true;
		strVarName = strVarName.substring(1, nAutoIncreaseMarkClose);
		strVarName = Utils.replaceAll(strVarName, "#", "");
		
		// TODO: 정규식 써야 하는데 몰라서 그냥 replace 사용함 --;
		strTempVarName = Utils.replaceAll(strVarName, "'", "");
		strTempVarName = Utils.replaceAll(strTempVarName, "$", "");
		strTempVarName = Utils.replaceAll(strTempVarName, "?", "");
		strTempVarName = Utils.replaceAll(strTempVarName, "|", "");
		strTempVarName = Utils.replaceAll(strTempVarName, "%", "");
	}
	else
	{
		strTempVarName = strVarName;
	}

	var strNewValue = this.getAtomValue(strTempVarName, bAutoIncrease, bInsert);
	
	var objAtom = Model.getAtom(strTempVarName);
	
	// 아톰값이 없는 경우. 아톰만 해당. 스크립트 변수는 제외.
	if (Utils.isEmpty(strNewValue) && null != objAtom)
	{
		var nLength = strQueryBuilder.length;
		
		if (bWhere)
		{
			strQueryBuilder = strQueryBuilder.substring(0, nLength - 3);
			strNewValue = "IS NULL";
		}
		else
		{
			strQueryBuilder = strQueryBuilder.substring(0, nLength - 1);
			strNewValue = "NULL";
		}
		bNullDelete = true;
	}

	if (bAutoIncrease)
	{
		strNewValue = strVarName.replace(strTempVarName, strNewValue);
	}
	strQueryBuilder += strNewValue;
	
	return strQueryBuilder;
}

/**
 * Where절에 아톰의 값이 없으면 IS NULL로 변경한다.
 */
SqlQueryLib.prototype.treatEmptyString = function (strQuery)
{
	var nIsNullStart = strQuery.indexOf("__ISNULL_START");
	var nIsNullEnd = strQuery.indexOf("__ISNULL_END");
	
	while (-1 < nIsNullStart)
	{
		var nEmptyValue = strQuery.indexOf("= ''");
		
		if (nIsNullStart < nEmptyValue && nEmptyValue < nIsNullEnd)
		{
			strQuery = Utils.replaceFirst(strQuery, "= ''", "IS NULL");
		}
		
		strQuery = Utils.replaceFirst(strQuery, "__ISNULL_START", "");
		strQuery = Utils.replaceFirst(strQuery, "__ISNULL_END", "");
		
		nIsNullStart = strQuery.indexOf("__ISNULL_START");
		nIsNullEnd = strQuery.indexOf("__ISNULL_END");
	}
	
	return strQuery;
}

/**
 * 해당 아톰의 값을 가져온다. 
 * @param strAtomVarNameToken 아톰변수명
 * @param objServiceParameter 
 */
SqlQueryLib.prototype.getAtomValue = function (strAtomVarNameToken, bAutoIncrease, bInsert)
{
	var strAtomValue = "";
	var strAtomVarName = strAtomVarNameToken.replace('.', '@');
	var nIndex = strAtomVarName.indexOf("@");

	if (0 < nIndex)
	{
		strAtomValue = getSelectedAtomValue(strAtomVarName, objAtomParameter, nIndex);
	}
	else
	{
		strAtomVarName = strAtomVarName.replace("%", "");
		
		var objAtom = Model.getAtom(strAtomVarName);
		
		if (null != objAtom && objAtom.getValue)
		{
			if ("Radio" == objAtom.getAtomType())
			{
				objValue = objAtom.getSelectValue();
			}
			else
			{
				objValue = objAtom.getValue();
			}
			
			strAtomValue = "";
			try
			{
				strAtomValue += objValue
			}
			catch (e)
			{
			}
			
			if ("InputData" == objAtom.getAtomType())
			{
				//입력란 아톰에서 값을 가져올 때 값에 포함된 따옴표는 디비에 저장할 수 있는 형태인 따옴표 2개로 변경한다.
				//입력란아톰.값 = "'VALUE'"
				// "'?입력란아톰?'" -> "'''VALUE'''"
				strAtomValue = Utils.replaceAll(strAtomValue, "'", "''");

				// 값이 있으면 접두어를 붙여준다.
				if (false == Utils.isEmpty(strAtomValue))
				{
					if (bAutoIncrease)
					{
						strAtomValue = Utils.getPrefix(objAtom.getPrefix()) + "[<" + strAtomValue + ">]";
					}
					else if (objAtom.isAutoInc() && 0 == objAtom.getAutoIncCount() && bInsert)
					{
						strAtomValue = Utils.getPrefix(objAtom.getPrefix()) + "[<" + strAtomValue + ">]";
						objAtom.addAutoIncCount();
					}
					else
					{
						strAtomValue = Utils.getPrefix(objAtom.getPrefix()) + strAtomValue;
					}
				}
			}
		}
		else
		{
			/**
			 * 서버에서는 map에 값까지 설정해서 미리 만들어 놓지만, 클라이언트에서는 값을 미리 구해놓지 않고, 
			 * 필요할때 구해오도록 변경하였음
			 */
			var nSymbolId = g_htScriptVarMap[strAtomVarName];
			
			if (null != nSymbolId)
			{
				strAtomValue = g_objDoc.getSymbolValue(nSymbolId);
			}
			
			if (null == strAtomValue || null == g_htScriptVarMap)
			{
				// @없이, 스크롤에 묶인 변수명만 설정된 경우
				// 스크롤 아톰 하나씩 검사해서 찾음,  검색창의 항목변수도 필요하면 추가해야함
				strAtomValue = objAtomParameter.getScrollBindedVarNameValue(strAtomVarName);
			}
		}

		if (null == strAtomValue)
		{
			strAtomValue = "";
		}

		strAtomValue = Utils.replace(strAtomVarNameToken, strAtomVarName, strAtomValue);
	}

	// 고유변수의 값으로 들어갈 strNew가  null이면, ""로 만든다.
	// 그렇지 않으면 String.replace()에서 예외 발생합니다.
	if (null == strAtomValue)
	{
		strAtomValue = "";
	}

	return strAtomValue;
}

/**
 * @param aliasingQuery - 앨리어싱 대상 쿼리
 * @param hmTableAlias 테이블 앨리어싱 목록 {tableName, alias}
 * @return #A[테이블명] 형태에 대해서 테이블 앨리어싱을 실행한 결과 쿼리를 반환한다.
 */
SqlQueryLib.prototype.tableAliasingByKeyword = function (aliasingQuery, hmTableAlias, nMapSize)
{
	var strSQL = aliasingQuery;
	var nStart = strSQL.indexOf("#A[");
	var bCanAlias = 1 < nMapSize ? true : false;
	
	while (-1 < nStart)
	{
		var nEnd = strSQL.indexOf("]", nStart);
		if (-1 == nEnd)
			break;

		// #A[테이블명] 을 찾아내어 잘라낸다.
		var strKeyword = strSQL.substring(nStart, nEnd + 1);

		// 순수 테이블명만 잘라낸다.
		var strTable = strKeyword.substring(3, strKeyword.length -1);

		var strAlias = hmTableAlias[strTable];
		if (null == strAlias || 0 == strAlias.length) // 현재 mapTableAlias에 key는 대소문자 구별없이 들어가 있기 때문에 2005.10.08 김경진
		{
			strTable = strTable.toUpperCase();
			strAlias = hmTableAlias[strTable];
		}
		if (bCanAlias)
		{
			while (-1 < strSQL.indexOf(strKeyword))
			{
				strSQL = Utils.replaceAll(strSQL, strKeyword, strAlias);
			}
		}
		else
		{
			while (-1 < strSQL.indexOf(strKeyword))
			{
				strSQL = Utils.replaceAll(strSQL, strKeyword + ".", "");
				strSQL = Utils.replaceAll(strSQL, strKeyword, "");
			}
		}
		nStart = strSQL.indexOf("#A[", nEnd);

	}

	return strSQL;
}

/**
 * @param strQuery 앨리어싱 대상 쿼리.
 * @param hmTableAlias 테이블 앨리어싱 목록 {tableName, alias}
 * @return 테이블명.필드명 형태에 대해서 테이블 앨리어싱을 실행한 결과 쿼리를 반환한다.
 */
SqlQueryLib.prototype.tableAliasingByMap = function (strQuery, hmTableAlias, nMapCount)
{
	if (null == hmTableAlias || 0 == nMapCount)
	{
		return strQuery;
	}

	if (Utils.isEmpty(strQuery))
	{
		return "";
	}

	var strResult = strQuery;
	var strUpperCaseQuery = strQuery.toUpperCase();
	var bCanAlias = nMapCount > 1 ? true : false;

	for (var strTable in hmTableAlias)
	{
		var strAlias = hmTableAlias[strTable];
		strTable = strTable + ".";

		if (bCanAlias)
		{
			strAlias = strAlias.concat(".");
		}
		else
		{
			strAlias = "";
		}

		var nTableIndex = strUpperCaseQuery.indexOf(strTable.toUpperCase());
		while (-1 != nTableIndex)
		{	
			if (0 < nTableIndex)
			{
				var ch = strUpperCaseQuery.charAt(nTableIndex - 1);
				if (Utils.isAlphabet(ch)) // || StringLib.isKorean(ch))
				{
					nTableIndex = strUpperCaseQuery.indexOf(strTable, nTableIndex + 1);
					continue;
				}
			}

			var strLeft  = strResult.substring(0, nTableIndex);
			var strLeftTemp = strUpperCaseQuery.substring(0, nTableIndex);

			var strRight = strResult.substring(nTableIndex + strTable.length);
			var strRightTemp = strUpperCaseQuery.substring (nTableIndex + strTable.length);

			strResult = strLeft + strAlias + strRight;
			strUpperCaseQuery = strLeftTemp + strAlias + strRightTemp;

			nTableIndex = strUpperCaseQuery.indexOf(strTable, nTableIndex + 1);
		}
	}

	return strResult;
}

/**
 * @param strWord 조사대상 식별자
 * @return 큰 따옴표로 묶여있는 식별자인가?
 */
SqlQueryLib.prototype.isValidQuotedIdentifier = function (strWord)
{
	if (Utils.isEmpty(strWord))
	{
		return false;
	}
//	var strRegex = "^\"(.*)\"$";
//	Pattern objPattern = Pattern.compile(strRegex);
//	Matcher objMatcher = objPattern.matcher(strWord);
//	return objMatcher.matches();
}

/**
 * @param strWord 식별자
 * @return 식별자 형식이 맞는가?
 * 정규표현식 : [한글A-Za-z0-9_#$]+
 */
SqlQueryLib.prototype.isValidIdentifier = function (strWord)
{
	if (Utils.isEmpty(strWord))
	{
		return false;
	}

	//한글은 식별자에 쓰일 수 있으므로 먼저 다 제거시킨다. 
//	strWord = StringLib.removeKorean(strWord);
	//모두 한글인 경우에는 식별자로 들어온 단어가 다 제거되었기 때문에 더이상의 검사가 불필요하다.
	if (0 == strWord.length)
	{
		return true;
	}

//	final String strRegex = "[A-Za-z0-9_#$]+";
//	Pattern objPattern = Pattern.compile(strRegex);
//	Matcher objMatcher = objPattern.matcher(strWord);
//	return objMatcher.matches();
}

SqlQueryLib.prototype.doToOracle = function (strOldSource, bHasWhere)
{
	//this.m_objOracle.setStart (this);
	this.m_objOracle.set9i (false);
	this.m_objOracle.setHasWhere(bHasWhere);
	
	return this.m_objOracle.doAnalize (strOldSource, false);
}

function CToOracle ()
{
	this.m_nPos = 0;
	this.m_strOne = "";
	this.m_bIs9i = false;
	this.m_bHasWhere = true;
	
	this.m_mapIsChange = new Hashtable();
	this.m_mapJoinType = new Hashtable();
	this.m_arList = new Array();
	
	this.m_arKeywordFrom = new Array ("[CASE]", "[WHEN]", "[ELSE]", "[THEN]", "[END]", "[UNION]", "[SYSDATE]", "[SYSDATE_2]", "[ISNULL]", "[SUBSTR]", "[||]", "[=*]",
				"[BIT]", "[INT]", "[FLOAT]", "[DECIMAL]", "[DATE]", "[CHAR]", "[VARCHAR2]", "[TEXT]", "[BINARY]", "[VARBINARY]", "[IMAGE]",
				"?0?", "?100?", "?101?", "?102?", "?103?", "?104?", "?105?", "?106?", "?107?", "?108?", "?9?", "?109?", "?110?", "?111?", "?112?", "?13?", "?113?", "?114?", "?120?", "?121?", 
				"[SYSOBJECTS]", "[SYSCOLUMNS]", "[NAME]", "[ID]", "[CRDATE]", "[XTYPE]", "[TYPE]", "[REFDATE]",
				"['P']", "['S']", "['TR']", "['U']", "['V']", "[HOSTNAME]", "[LEN]", null	
			);
	
	this.m_arKeywordTo = new Array ("CASE", "WHEN", "ELSE", "THEN", "END", "UNION", "SYSDATE", "TO_CHAR(SYSDATE, 'yyyy-mm-dd hh24:mi:ss')", "NVL", "SUBSTR", "||", "(+)=",
				"NUMBER(1)", "NUMBER", "NUMBER", "NUMBER", "DATE", "CHAR", "VARCHAR2", "LONG", "RAW", "LONG RAW", "LONG RAW", 
				"mon dd yyyy hh:mi", "mon dd yyyy hh:mi", "mm/dd/yy", "yy.mm.dd", "dd/mm/yy", "dd.mm. yy", "dd-mm-yy", "dd mon yy", "mon dd yy", "hh:mi:ss", "mon dd, yyyy hh:mi:ss ", "mon dd, yyyy hh:mi:ss ", "mm-dd-yy", "yy/mm/dd", "yyyymmdd", "dd mon yyyy hh24:mi:ss", "dd mon yyyy hh24:mi:ss", "hh24:mi:ss", "yyyy-mm-dd hh24:mi:ss", "yyyy-mm-dd hh24:mi:ss", 
				"SYS.ALL_OBJECTS", "USER_TAB_COLUMNS", "OBJECT_NAME", "OBJECT_ID", "CREATED", "OBJECT_TYPE", "OBJECT_TYPE", "LAST_DDL_TIME", 
				"'PROCEDURE'", "'TABLE'", "'TRIGGER'", "'TABLE'", "'VIEW'", "SYS_CONTEXT('USERENV','TERMINAL')", "LENGTH", null
			);
}

CToOracle.prototype.set9i = function (bIs9i)
{
	this.m_bIs9i = bIs9i;
}

CToOracle.prototype.setHasWhere = function (bHasWhere)
{
	this.m_bHasWhere = bHasWhere;
}

CToOracle.prototype._initKeywordMap = function ()
{
	if (0 == this.m_mapIsChange.length)
	{
		for (var i = 0; null != this.m_arKeywordFrom[i]; i+=1)
		{
			var strFrom = this.m_arKeywordFrom[i];
			var strTo   = this.m_arKeywordTo[i];

			this.m_mapIsChange[strFrom] = strTo;
		}
	}

	if (0 == this.m_mapJoinType.length)
	{
		this.m_mapJoinType["[J_FULLOUTER]"] = "3";
		this.m_mapJoinType["[J_LEFTOUTER]"] = "1";
		this.m_mapJoinType["[J_RIGHTOUTER]"] = "2";
		this.m_mapJoinType["[J_LEFT]"] = "1";
		this.m_mapJoinType["[J_RIGHT]"] = "2";
		this.m_mapJoinType["[J_INNER]"] = "0";
		this.m_mapJoinType[null] = null;
	}
}

CToOracle.prototype.doAnalize = function (lpszSource, bFile)
{
	this.m_nPos = 0;
//	m_saJoinOnList.clear ();
	
	this._initKeywordMap ();

	var strSource = lpszSource;

	if(-1 < strSource.indexOf("[SYSOBJECTS]"))
	{
		strSource = this._convertQuerySysObjectOwner(strSource);
	}
	
	var nLen = this.m_arKeywordFrom.length;
	for (var i = 0; i < nLen; i+=1)
	{
		var strFrom = this.m_arKeywordFrom[i];
		var strTo   = this.m_arKeywordTo[i];

		strSource = Utils.replaceAll(strSource, strFrom, strTo);
	}
	
	//strSource = m_Start.convOwnerInfo (strSource);

	var strUpperTemp = Utils.trim(strSource.toUpperCase());
	
	if (6 <= strUpperTemp.length && "[EXEC]" == strUpperTemp.substring(0, 6))
	{
		strSource = this._doExecAnalize (strSource);
		return strSource;
	}

	//strSource = this._doJoinAnalize (strSource, false);

	if (false == this.m_bIs9i)
	{
		var nIndex = strSource.indexOf ("*=");
		if (-1 < nIndex)
		{
			strSource = Utils.replace(strSource, "*=", "(+) =");
			strSource = Utils.replace(strSource, "[AND]", "AND");
		}
		else
		{
			nIndex = strSource.indexOf ("=*");
			if (-1 < nIndex)
			{
				strSource = Utils.replace(strSource, "=*", "=");
				strSource = Utils.replace(strSource, "[AND]", "(+) AND");
			}
		}
	}
	else
	{
		strSource = Utils.replace(strSource, "[AND]", "AND");
	}

	return strSource;
}

CToOracle.prototype._convertQuerySysObjectOwner = function (strConvert)
{
	strConvert = strConvert.toUpperCase();
	if(-1 < strConvert.indexOf ("WHERE"))
	{
		strConvert = Utils.replaceAll(strConvert, "WHERE", " where owner='_OWNER_' and ");
	}
	else
	{
		strConvert = strConvert + " where owner='_OWNER_' ";
	}

	var strOwnerName = (null != this.m_Start) ? this.m_Start.getOwnerList()[0].toString() : "";
	strConvert = Utils.replaceAll(strConvert, "_OWNER_", strOwnerName);
	return strConvert;
}

CToOracle.prototype._doExecAnalize = function (lpszSource)
{
	var strSource = lpszSource;
	var strResult = "";

	strSource = this._getOneWord (strSource, true);
	var strWord = this.m_strOne;

	var saOutput = new Array();
	var bNext = true;

	while (null != strWord && 0 < strWord.length)
	{
		bNext = true;

		var strUpper = strWord.toUpperCase ();
		strUpper = Utils.trim(strUpper);

		if (true == this._isFunctionWord (strUpper))
		{
			strResult += this._doFunctionAnalize (strSource);
		}
		else if (3 <= strWord.length && "[P_" == strWord.substring(0, 3))
		{
			strWord = Utils.replaceAll(strWord, "[P_", "[");

			var strType = this.m_mapIsChange[strWord];
			var nParen1 = 0;

			var strTemp = "";
			do
			{
				strSource = this._getOneWord (strSource, true);
				strWord = this.m_strOne;

				strTemp = Utils.trim(strWord);
				
				if ("(" == strTemp)
				{
					nParen1 += 1 ;
				}
				
				if (")" == strTemp)
				{
					strSource = this._getOneWord (strSource, true);
					nParen1 -= 1;
				}

				if ("" == strTemp || 0 < nParen1 || ")" == strTemp)
				{
					strType += strWord;
				}

			}
			while (("" == strTemp || 0 < nParen1) && "" != strWord);

			bNext = false;
			saOutput.push(strType);

			var strAdd = "v_Temp" + saOutput.length;
			strResult += ", " + strAdd;
		}
		else
		{
			strResult += strWord;
		}

		strSource = this._getOneWord (strSource, bNext);
		strWord = this.m_strOne;
	}

	strResult = Utils.trim(strResult);
	
	if (8 <= strResult.length)
	{
		strResult = strResult.substring(8);
	}
	else
	{
		strResult = "";
	}
	strResult = Utils.trim(strResult);

	strResult = Utils.replaceAll(strResult, "\t", "    ");
	var nSpace = strResult.indexOf (" ");
	if (-1 < nSpace && nSpace <= strResult.length)
	{
		var strLEft = strResult.substring(0, nSpace);
		var strRight = strResult.substring(nSpace);

		nSpace = strRight.indexOf(" ");
		if (-1 < nSpace && nSpace <= strResult.length)
		{
			var strProc = strRight.substring(0, nSpace);
			var strParam = strRight.substring(nSpace);

			strParam = Utils.trim(strParam);
			if ("," == strParam)
			{
				strParam = strParam.substring(1);
			}

			strRight = strProc + "( " + strParam + "); END;";
		}

		strResult = "BEGIN " + strLEft + strRight;
	}

	if (0 < saOutput.size)
	{
		var nCount = saOutput.length;
		for (var i = nCount - 1; i >=0 ; i--)
		{
			var strVar = "";
			strVar = "v_Temp" + (i + 1) + " " + saOutput[i] + "; ";
			strResult = strVar + strResult;
		}

		strResult = "DECLARE " + strResult;
	}

	return strResult;
}

CToOracle.prototype._getOneWord = function (strString, bNext)
{
	if (false != bNext)
	{
		this.m_strOne = "";
		var ch;
		var nLength = strString.length;
		for ( ; this.m_nPos < nLength; this.m_nPos++)
		{
			ch = strString.charAt(this.m_nPos);

			if (' ' == ch || '\t' == ch || '\n' == ch || '(' == ch || ')' == ch || ',' == ch || '{' == ch || '}' == ch || '-' == ch || '+' == ch || '*' == ch || '/' == ch )
			{
				if ("" == this.m_strOne)
				{
					this.m_strOne = ch;
					this.m_nPos++;
				}
				break;
			}

			this.m_strOne += ch;
		}
	}

	return strString;
}

CToOracle.prototype._isFunctionWord = function (strWord)
{
	var bFunc = false;

	if ("[CONVERT]"	== strWord || "[STR]" == strWord || "[RIGHT]" == strWord
			|| "[LEFT]" == strWord || "[DATEDIFF]" == strWord || "[DATEADD]" == strWord)	
	{
		bFunc = true;
	}

	return bFunc;
}

CToOracle.prototype._doFunctionAnalize = function (lpszSource)
{
	var strResult = "";
	var strSource = lpszSource;

	strSource = this._getOneWord (strSource, false);
	var strFtName = this.m_strOne;

	var nParen = 0;
	var nIndex = 0;

	strSource = this._getOneWord (strSource, true);
	while ("(" != this.m_strOne)
	{
		strSource = this._getOneWord (strSource, true);
	}

	strSource = this._getOneWord (strSource, true);
	var strWord = this.m_strOne;

	var strPara  = "";
	var strUpper = "";

	this.m_arList = new Array();
	while (null != strWord && 0 < strWord.length)
	{
		strUpper = strWord;
		strUpper = strUpper.toUpperCase ();
		strUpper = Utils.trim(strUpper);

		if ("(" == strWord)
		{
			nParen++;
		}
		if (")" == strWord)
		{
			nParen--;
		}

		if (-1 == nParen && ")" == strWord)
		{
			this._setAtGrow (nIndex, strPara);
			break;
		}
		else if (0 == nParen && "(" == strWord)
		{
		}
		else if (3 <= strWord.length && "[J_" == strWord.substring(0, 3))
		{
			//strPara += changeJoin (strSource, false);
		}
		else if (true == this._isFunctionWord (strUpper))
		{
			strPara += this._doFunctionAnalize (strSource);
		}
		else if (0 == nParen && "," == strWord)
		{
			this._setAtGrow (nIndex, strPara);
			nIndex++;
			strPara = "";
		}
		else
		{
			strPara += strWord;
		}

		strSource = this._getOneWord (strSource, true);
		strWord = this.m_strOne;
	}
	
	var strFTUpper = strFtName;
	strFTUpper = Utils.trim(strFTUpper);

	if ("[CONVERT]"	== strFTUpper)
	{
		strResult = this._doConvertAnalize ();
	}
	else if ("[STR]"	== strFTUpper)
	{
		strResult = this._doStrAnalize ();
	}
	else if ("[RIGHT]"	== strFTUpper)
	{
		//strResult = doRightAnalize();
	}
	else if ("[LEFT]"	== strFTUpper)
	{
		//strResult = doLeftAnalize ();
	}
	else if ("[DATEDIFF]"	== strFTUpper )
	{	
		//strResult = doDateDiffAnalize ();
	}
	else if ("[DATEADD]" == strFTUpper )
	{
		//strResult = doDateAddAnalize();
	}

	return strResult;
}

CToOracle.prototype._setAtGrow = function (nIndex, strData)
{
	if (this.m_arList.length <= nIndex)
	{
		var nSize = this.m_arList.length;
		for (var i = nSize - 1; i < nIndex; i++)
		{
			this.m_arList.push("");
		}
	}

	this.m_arList.splice(nIndex, strData);
}

CToOracle.prototype._doConvertAnalize = function ()
{
	if (2 > this.m_arList.length)
		return "";

	var strResult = "";
	var strPara0 = this.m_arList[0];
	var strPara1 = this.m_arList[1];
	var strPara2 = (2 < this.m_arList.length) ? this.m_arList[2] : "";

	var strUpper1 = strPara1.toUpperCase ();

	var nStart = strPara0.indexOf("(");
	var nEnd   = strPara0.indexOf(")");

	var nSize = 0;
	if ( -1 != nStart && -1 != nEnd && nEnd <= strPara0.length)
	{
		nSize = Utils.parseInt(strPara0.substring(nStart+1, nEnd));
		strPara0 = strPara0.substring(0, nStart);
	}

	var bSys = false;
	if ( -1 < strUpper1.indexOf("SYSDATE") || -1 < strUpper1.indexOf("ADD_MONTHS") || -1 < strUpper1.indexOf ("TO_DATE"))
	{   
		if (2 < this.m_arList.length && -1 < strPara2.indexOf ("'"))     
		{
			bSys = true;
			strResult = "SUBSTR( TO_CHAR( " + strPara1 + ", " +strPara2+"),1," + nSize + " )";
		}
		else if (2 < this.m_arList.length)
		{
			strPara2 = Utils.trim(strPara2);
			bSys = true;
			strResult = "SUBSTR( TO_CHAR( " + strPara1 + ", \'" +strPara2+"\'),1," + nSize + " )";
		}
	}

	if (false == bSys)
	{
		if(false != this._isStringType(strPara0))
		{
			if ( nSize != 0 )
				strResult = "SUBSTR( " + strPara1 + ", 1, " + nSize + " )";
			else 
				strResult = "TO_CHAR(" + strPara1 +")"; 
		}
		else if ("DATE" == strPara0)
		{
			strResult = "TO_DATE(" + strPara1 + ")"; 
		}
		else 
		{
			strResult = "TO_NUMBER(" + strPara1 + ")";
		}
	}

	return strResult;
}

CToOracle.prototype._isStringType = function (strType)
{
	if ("CHAR" == strType || "NCHAR" == strType || "VARCHAR2" == strType || "LONG" == strType
			|| "CHARACTER" == strType || "VARCHAR" == strType || "NVARCHAR"	== strType || "TEXT" == strType)
	{
		return true;
	}

	return false;
}

CToOracle.prototype._doStrAnalize = function ()
{
	var strResult = "";

	var nCount = this.m_arList.length;
	if (1 == nCount)
	{
		strResult = "SUBSTR (ROUND(" + this.m_arList[0] + ", 0), 1, LENGTH(" + this.m_arList[0] + "))";
	}
	else if (2 == nCount)
	{
		strResult = "SUBSTR (ROUND(" + this.m_arList[0] + ", 0), 1, " + this.m_arList[1] + ")";
	}
	else if (3 == nCount)
	{
		strResult = "SUBSTR (ROUND(" + this.m_arList[0] + ", " + this.m_arList[2] + "), 1, " + this.m_arList[1] + ")";
	}

	return strResult;
}


function CToMSSQL ()
{
	this.m_arKeywordFrom = new Array("[CASE]", "[WHEN]", "[ELSE]", "[THEN]", "[END]", "[UNION]", "[CONVERT]",
							"[SYSDATE]", "[SYSDATE_2]", "[ISNULL]", "[STR]", "[SUBSTR]", "[LEFT]", "[RIGHT]",
							"[EXEC]", "[||]", "[=*]", 
							"[BIT]", "[INT]", "[FLOAT]", "[DECIMAL]", "[DATE]", "[CHAR]", "[VARCHAR2]", "[TEXT]", "[BINARY]", "[VARBINARY]", "[IMAGE]"   
							);
	
	this.m_arKeywordTo = new Array("CASE", "WHEN", "WHEN", "THEN", "END", "UNION", "CONVERT",
							"GETDATE ()", "GETDATE ()", "isnull", "STR", "SUBSTRING", "LEFT", "RIGHT", 
							"EXEC", "+", "=*",
							"BIT", "INT", "FLOAT", "DECIMAL", "DATETIME", "CHAR", "VARCHAR2", "TEXT", "BINARY", "VARBINARY", "IMAGE"
							);
}

CToMSSQL.prototype.doAnalize = function (lpszSource)
{
	var strSource = lpszSource;

	if(-1 < strSource.indexOf ("[SYSOBJECTS]"))
	{
		strSource = strSource.replace ("[SYSOBJECTS]", "_OWNER_[SYSOBJECTS]");
	}
	
	var nLen = this.m_arKeywordFrom.length;
	for (var i = 0; i < nLen; i+=1)
	{
		var strFrom = this.m_arKeywordFrom[i];
		var strTo   = this.m_arKeywordTo[i];

		strSource = Utils.replaceAll(strSource, strFrom, strTo);
	}
	
	// 2. _OWNER_를 분석한다...
	//strSource = m_Start.convOwnerInfo (strSource);	
	
	// 3. Join분석을 한다... Join이 여러번 나올경우
	//strSource = doJoinAnalize (strSource);
	strSource = Utils.replaceAll(strSource, "[AND]", "AND");

	var nParam = strSource.indexOf("[P_");
	if (-1 < nParam && nParam <= strSource.length)
		strSource = strSource.substring(0, nParam);

	return strSource;
}

