package com.eactive.eai.rms.onl.manage.rule.layoutsync;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.View;
import org.xml.sax.InputSource;

import com.eactive.apim.portal.monitoringcode.entity.MonitoringCode;
import com.eactive.apim.portal.monitoringcode.entity.MonitoringCodeId;
import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.common.util.UUIDGenerator;
import com.eactive.eai.rms.data.entity.man.monitoringCode.service.MonitoringCodeService;
import com.eactive.eai.rms.common.base.OnlBaseAnnotationController;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.common.logging.UserAccessLogger;
import com.eactive.eai.rms.common.login.SessionManager;
import com.eactive.eai.rms.common.util.AgentParserUtils;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.common.util.StringUtils;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.common.util.DateUtil;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.Types;


@Controller
@RequestMapping("/layoutSync.do")
public class LayoutSyncController extends OnlBaseAnnotationController implements InterceptorSkipController {

    private static final Logger logger = LoggerFactory.getLogger(LayoutSyncController.class);

    @Autowired
    @Qualifier("layoutSyncService")
    private LayoutSyncService service;

    @Autowired
    @Qualifier("monitoringContext")
    private MonitoringContext monitoringContext;

    @Autowired
    private KJBTransformService transformService;

    @Autowired
    private KJBInterfaceService interfaceService;

    @Autowired
    private MonitoringCodeService monitoringCodeService;
    
    
	/**
	 * xml 형식으로 전달 된 레이아웃을 LayoutVo로 전환
	 * 
	 * @param e
	 * @param msgType
	 * @param loutName
	 * @return
	 * @throws Exception
	 */
	private List<HashMap<String,Object>> setLayoutItems(Element e, String msgType, String loutName ) throws Exception {
		List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();

        List<Element> items = e.getChildren();
        for(Element el : items) {
    		// Layout Item Format (TR08)
            HashMap<String,Object> item = new HashMap<String,Object>();

            item.put("loutName",loutName);
            item.put("loutItemName",el.getAttributeValue("id"));
            item.put("loutItemSerno", Integer.parseInt(el.getAttributeValue("no")) );
            item.put("loutItemIDName",Integer.parseInt(el.getAttributeValue("no")) + 1000);
            String no = el.getParentElement().getAttributeValue("no");
            item.put("parntLoutItemIDName",Integer.parseInt( no == null ? "0":no ) + 1000 );
            item.put("loutItemDesc",el.getAttributeValue("desc"));
            
            int node = 0;
            if( "GROUP".equals(el.getName().toUpperCase()) ) {
            	node = Item.NODE_GROUP;
            } else if("GRID".equals(el.getName().toUpperCase())) {
            	node = Item.NODE_GROUP;
            } else {
            	node = Item.NODE_FIELD;
            }
            
            item.put("loutItemNodePtrnIDName",node);

            int loutType = Types.TYPE_UNKNOWN;
            if( el.getAttributeValue("type") == null ||  "".equals(el.getAttributeValue("type"))) {
            } else if( "GRID".equals(el.getName().toUpperCase()) || "GROUP".equals(el.getName().toUpperCase()) ) {
            } else if( msgType.equals("XML") || msgType.equals("JSON") ) {     
            	loutType = "VARCHAR".startsWith(el.getAttributeValue("type").toUpperCase()) ? Types.TYPE_STRING : Types.TYPE_INT;  // TYPE_LONG, TYPE_SHORT, TYPE_DOUBLE, TYPE_FLOAT
            	//loutType = Types.TYPE_STRING;
            } else {
            	loutType = Types.TYPE_BYTEARRAY;
            }
            
			item.put("loutItemPtrnIDName", loutType);
			item.put("loutItemLenCnt",
					"".equals(el.getAttributeValue("len")) ? 0 : Integer.parseInt(el.getAttributeValue("len")));
			item.put("loutItemRefInfo2", el.getAttributeValue("count"));
            
            // MIN, MAX 설정
            // 통합인터페이스는 * , 숫자만 보냄 ( 가변은 * 고정은 숫자 ) 
            String occurNoitm = el.getAttributeValue("maxCnt");
            int max = 0;
            int min = 0;
            if( String.valueOf(Item.OCC_MULTI_OR_NONE).equals(occurNoitm) ) {  // *
            	max = -1;
            } else if ( String.valueOf(Item.OCC_ONCE_OR_NONE).equals(occurNoitm) ) {  // ?
            	max = 1;
            } else if ( String.valueOf(Item.OCC_MULTI_OR_ONCE).equals(occurNoitm) ) {  // +
            	min = 1;
            	max = -1;
            } else if ( "".equals(occurNoitm) ) {  // ""
            	min = 1;
            	max = 1;
            } else if ( occurNoitm.matches("[0-9]+") ) {  // ""
            	min = StringUtils.isNotEmpty(el.getAttributeValue("count")) ? 0 : Integer.parseInt(occurNoitm);
            	max =  Integer.parseInt(occurNoitm);
            }
            
            // 반복횟수 참조정보가 없는데 MIN, MAX 값이 설정되지 않은 경우 오류
            if( max == 0 && min == 0 ) {
            	if("GRID".equals(el.getName().toUpperCase()) ) {
            		if ( !StringUtils.isEmpty(el.getAttributeValue("count")) ) {            		
                	} else {
                		throw new Exception("반복횟수 참조정보 오류");
                	}
            	} else {
            		min = 1;
        		    max = 1;
            	}            	
            }
            
            if( "0".equals(occurNoitm) ) {
            	occurNoitm = "";         		
        	}
            
            item.put("loutItemOccurPtrnDstcd",occurNoitm); // 레이아웃항목발생유형구분코드
            item.put("loutItemMaxOccurNoitm",max); // 레이아웃항목최대발생건수
            item.put("loutItemMinOccurNoitm",min); // 레이아웃항목최소발생건수
            
            item.put("loutItemBascVal",el.getAttributeValue("default"));  // 레이아웃항목기본값
            item.put("louItemMskYn",el.getAttributeValue("mask")); // [Y/N/ ]
            item.put("louItemMskCode",el.getAttributeValue("mask2"));
            //item.put("loutItemMskTarget",el.getAttributeValue("maskTarget")); // [LOG/DATA ]
            
            if( "Y".equals(item.get("loutItemMskYn")) ) item.put("loutItemMaskLength",Integer.parseInt(el.getAttributeValue("maskLength")));
            item.put("lyoutDptCnt",Integer.parseInt(el.getAttributeValue("depth")) + 1 );  // 통합인터페이스 전달되는 Depth + 1을 해야 함
            item.put("decptLenCnt","".equals(el.getAttributeValue("scale")) ? 0 : Integer.parseInt(el.getAttributeValue("scale"))); // 소수점길이 META에서 "" 이면 "" 으로 표현함
            
            
            
            String dataType = "";
            if( el.getAttributeValue("type") == null ||  "".equals(el.getAttributeValue("type"))) {  
            } else if( "VARCHAR".startsWith(el.getAttributeValue("type").toUpperCase()) ) { // Varchar, Number
            	dataType = "String";
            } else if( "NUMBER".startsWith(el.getAttributeValue("type").toUpperCase()) ) { // Varchar, Number
            	dataType = "Integer";
            }            
            item.put("lyoutItemRefPtrnIDName",dataType); // 데이터타입

            list.add(item);
            if( el.getChildren() != null && el.getChildren().size() > 0 ) {
            	list.addAll(setLayoutItems(el, msgType, loutName));
            }
        }  // end FOR
		
		return list;
	}
	
	// JJB 수정사항 shkim 2020-05-13 JSON 타입 추가
	/**
	 * json 형식으로 전달 된 레이아웃을 LayoutVo로 전환
	 * 
	 * @param e
	 * @param msgType
	 * @param loutName
	 * @return
	 * @throws Exception
	 */
	private List<HashMap<String,Object>> setLayoutItemsJSN(JSONArray items, String msgType, String loutName, String parentNo) throws Exception {
		List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
		
		for(Object i : items) {
			// Layout Item Format (TR08)
			HashMap<String,Object> item = new HashMap<String,Object>();
			
			String type = (String) ((JSONObject) i).keySet().iterator().next();
			
			JSONObject _i = (JSONObject) ((JSONObject) i).get(type);
			
			item.put("loutName",loutName);
			item.put("loutItemName",_i.get("id"));
			item.put("loutItemSerno", Integer.parseInt((String) _i.get("no")) );
			item.put("loutItemIDName",Integer.parseInt((String) _i.get("no")) + 1000);
			String no = parentNo;
			item.put("parntLoutItemIDName",Integer.parseInt( no == null ? "0":no ) + 1000 );
			item.put("loutItemDesc",_i.get("desc"));
			type = type.toUpperCase();
			int node = 0;
			if( "GROUP".equals(type) ) {
				node = Item.NODE_GROUP;
			} else if("GRID".equals(type)) {
				node = Item.NODE_GROUP;
			} else {
				node = Item.NODE_FIELD;
			}
			
			item.put("loutItemNodePtrnIDName",node);
			
			int loutType = Types.TYPE_UNKNOWN;
			if( _i.get("type") == null ||  "".equals(_i.get("type"))) 
			{            	
			} else if( "GRID".equals(type) || "GROUP".equals(type) ) 
			{       	
			} else if( msgType.equals("XML") ) 
			{     
				loutType = "VARCHAR".startsWith(((String) _i.get("type")).toUpperCase()) ? Types.TYPE_STRING : Types.TYPE_INT;  // TYPE_LONG, TYPE_SHORT, TYPE_DOUBLE, TYPE_FLOAT
				
				//loutType = Types.TYPE_STRING;
			}
			else if ( msgType.equals("JSON") )
			{
				String type2 = ((String) _i.get("type")).toUpperCase();
				
				switch(type2)
				{
				case "VARCHAR":
					loutType = Types.TYPE_STRING;
					break;
				// JJB 수정사항 shkim 2020-08-19 숫자형 실수부 처리 문제로 BigDecimal로 처리
				case "NUMBER":
//					loutType = Types.TYPE_INT;
//					break;
				case "BIGDECIMAL":
					loutType = Types.TYPE_BIGDECIMAL;
					break;
				}
				//loutType = type2.equals("VARCHAR") ? Types.TYPE_STRING : Types.TYPE_INT;  // TYPE_LONG, TYPE_SHORT, TYPE_DOUBLE, TYPE_FLOAT
				
			}else if ( msgType.equals("FML32") )
			{
				String fmlType = ((String) _i.get("id")).toUpperCase().replaceAll("[\\d]", "");
				
				switch(fmlType)
				{
				case "LONG":
					loutType = Types.TYPE_LONG;
					break;
				case "SHORT":
					loutType = Types.TYPE_SHORT;
					break;
				case "DOUBLE":
					loutType = Types.TYPE_DOUBLE;
					break;
				default:
					loutType = Types.TYPE_STRING;
					break;
					
				}
				item.put("loutItemPathName", _i.get("id"));
			}
			else {
				loutType = Types.TYPE_BYTEARRAY;
			}
			
		
			
			item.put("loutItemPtrnIDName",loutType);
			item.put("loutItemLenCnt","".equals(_i.get("len")) ? 0 : Integer.parseInt((String) _i.get("len")));

			
			
			// MIN, MAX 설정
			// 통합인터페이스는 * , 숫자만 보냄 ( 가변은 * 고정은 숫자 ) 
			String occurNoitm = (String) _i.get("maxCnt");
			
			
			int max = 0;
			int min = 0;
			if( String.valueOf(Item.OCC_MULTI_OR_NONE).equals(occurNoitm) ) {  // *
				max = -1;
				item.put("loutItemRefInfo2",_i.get("count"));
			} else if ( String.valueOf(Item.OCC_ONCE_OR_NONE).equals(occurNoitm) ) {  // ?
				max = 1;
			} else if ( String.valueOf(Item.OCC_MULTI_OR_ONCE).equals(occurNoitm) ) {  // +
				min = 1;
				max = -1;
			} else if ( "".equals(occurNoitm) ) {  // ""
				min = 1;
				max = 1;
			} else if ( occurNoitm.matches("[0-9]+") ) {  // ""
				min =  Integer.parseInt(occurNoitm);
				max =  Integer.parseInt(occurNoitm);
			}
			
			// 반복횟수 참조정보가 없는데 MIN, MAX 값이 설정되지 않은 경우 오류
			if( max == 0 && min == 0 ) {
				if("GRID".equals(type) ) {
					if ( !StringUtils.isEmpty((String) _i.get("count")) ) {            		
					} else {
						throw new Exception("반복횟수 참조정보 오류");
					}
				} else {
					min = 1;
					max = 1;
				}            	
			}
			
			if( "0".equals(occurNoitm) ) {
				occurNoitm = "";         		
			}
			
			item.put("loutItemOccurPtrnDstcd",occurNoitm); // 레이아웃항목발생유형구분코드
			item.put("loutItemMaxOccurNoitm",max); // 레이아웃항목최대발생건수
			item.put("loutItemMinOccurNoitm",min); // 레이아웃항목최소발생건수
			
			item.put("loutItemBascVal",_i.get("default"));  // 레이아웃항목기본값
			if( _i.get("mask") != null && _i.get("mask").equals("Y"))
			{
				item.put("loutItemMskYn", "Y");
				
				// DJB : mask2에 마스킹 코드가 있으면 offset에 mask2 입력 length=0으로, 기존 마스킹은 length만 입력
				// 엔진에서는 length가 0이면 masking code로, 0보다 크면 기존 마스킹으로 적용
				String mask2 = (String) _i.get("mask2");
				if (mask2 == null || mask2.equals("")) {
					item.put("loutItemMaskOffset", 0);
					item.put("loutItemMaskLength",Integer.parseInt((String) _i.get("maskLength")));
				} else {
					String maskingCode = monitoringCodeService.findById(new MonitoringCodeId("MASKING_CODE", mask2))
							.map(MonitoringCode::getCodeName)
							.orElse("99");
					item.put("loutItemMskCode", maskingCode);
					item.put("loutItemMaskOffset", Integer.parseInt(maskingCode));
					item.put("loutItemMaskLength",0);
				}
			}
			else
			{
				item.put("loutItemMskYn",_i.get("mask")); // [Y/N/ ]
			}
			
			
			item.put("lyoutDptCnt",Integer.parseInt((String) _i.get("depth")) + 1 );  // 통합인터페이스 전달되는 Depth + 1을 해야 함
			item.put("decptLenCnt","".equals(_i.get("scale")) ? 0 : Integer.parseInt((String) _i.get("scale"))); // 소수점길이 META에서 "" 이면 "" 으로 표현함
			item.put("loutItemMskTarget", _i.get("maskTarget"));
			
			
			String dataType = "";
			if( _i.get("type") == null ||  "".equals(_i.get("type"))) {            	
			} else if( "VARCHAR".startsWith(((String) _i.get("type")).toUpperCase()) ) { // Varchar, Number
				dataType = "String";
			} else if( "NUMBER".startsWith(((String) _i.get("type")).toUpperCase()) ) { // Varchar, Number
				// JJB 수정사항 shkim 2020-08-19 숫자형 실수부 처리 문제로 BigDecimal로 처리
				dataType = "BigDecimal";
//				dataType = "Integer";
			} else if( "BIGDECIMAL".startsWith(((String) _i.get("type")).toUpperCase()) ) { // Varchar, Number
				dataType = "BigDecimal";
			}
			
			item.put("lyoutItemRefPtrnIDName",dataType); // 데이터타입
			
			list.add(item);
			
			if( _i.containsKey("item") && _i.entrySet().size() > 0 ) {
				list.addAll(setLayoutItemsJSN((JSONArray) _i.get("item"), msgType, loutName, (String) _i.get("no")));
			}
		}  // end FOR
		
		return list;
	}
	
    /**
     * 통합인터페이스 시스템(iim)에서 전문 레이아웃에 대한 INSERT, DELETE 요청
     * *
     * @param request
     * @param response
     * @param schema
     * @return
     * @throws Exception
     */
    @RequestMapping(params = "cmd=Message")
    public View parseMessage(HttpServletRequest request, HttpServletResponse response, String schema) throws Exception {
        UserAccessLogger.log(request, "레이아웃", "L", "cmd=Message");
        Document rDoc = null;
        Element results = null;
        String  resultS = null;
        ServletInputStream sis = null;

        HashMap<String, String> param = new HashMap<>();
        String recvTime = DateUtil.getDateTime("yyyyMMddHHmmssSS").substring(0, 16);

    	// 초기화
    	DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(schema));
    	try {

	    	SAXBuilder builder = new SAXBuilder();

	        // 응답 전문
	        InputStream resStream = request.getSession().getServletContext().getResourceAsStream("/WEB-INF/layout-messagesync-res.xml");
	        if (resStream == null) {
	            throw new Exception("layout-messagesync-res.xml 파일을 찾을 수 없습니다.");
	        }
	        try {
	            rDoc = builder.build(resStream);
	            results = rDoc.getRootElement();
	        } finally {
	            resStream.close();
	        }


	    	// 요청 전문 - InputStream을 먼저 byte[]로 읽음
	    	sis = request.getInputStream();
	        byte[] arg = new byte[request.getContentLength()];
	        int resultSet = 0;
	        int total = 0;
	        
	        String xmlContent = null;
			try {
				resultSet = sis.readLine(arg, 0, arg.length);
				while (resultSet != -1) {
					total += resultSet;
					resultSet = sis.readLine(arg, total, 1024);
				}

				xmlContent = new String(arg, "EUC-KR");
				// ===== 인코딩 확인 로그 시작 =====
				logger.info("========== 인코딩 디버깅 정보 ==========");
				// 다양한 인코딩으로 읽어보기
				logger.info("request.getCharacterEncoding(): {}", request.getCharacterEncoding());
				logger.info("request.getContentType(): {}", request.getContentType());
				logger.info("Content Length: {} bytes", arg.length);
				logger.info("EUC-KR 전체 내용:\n{}", xmlContent);
				logger.info("========================================");
				// ===== 인코딩 확인 로그 끝 =====
				param.put("recvData", xmlContent);
			} catch (Exception e) {
				logger.error("MessageSync.err - don't read the XML File", e);
				param.put("recvData", "");
			}

	        // byte[]로부터 XML 파싱 - EUC-KR로 읽기
	        Document doc = builder.build(new StringReader(xmlContent));
	        
	        param.put("logPrcssSeqno", UUIDGenerator.getUUID());
	        // xml 1.1
	        Element message = doc.getRootElement();
	        
	        // Command 확인
	        String command = message.getChild("Header").getChild("Command").getText();
	        
	        Element body = message.getChild("Body").getChild("Layout");
	        String layoutName = body.getChild("id").getText();

	        param.put("serviceName", message.getChild("Header").getChild("ServiceName").getText());
	        param.put("command", command);
	        param.put("loutName", layoutName);
			param.put("recvAmndHMS", recvTime);
	        
	        logger.info(layoutName + " command - [" + command +"]");	       
	        HashMap<String, Object> returnMap = new HashMap<>();
	        if( command.equals("delete") ) {
	            HashMap<String,Object> vo = new HashMap<>();
	            vo.put("loutName",layoutName);
	        	
	            service.deleteLayout(vo);
	            
	            CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.RemoveLayoutCommand",vo.get("loutName"));
	            HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
	            param.putAll(result);
	            
	            service.addLayoutSyncLog(param);
	        	
	        	
	        	
	        } else {
	        	// LoutName 검증
	        	// 인터페이스 이름 20자리 이하  
	        	// EAI _CORS _CORR _CORE _UAIR
	        	// FEP _COR _ORG
	        	String fattern = "[A-Za-z0-9]*";
	        	
	        	//레이아웃 필터링으로 미동작 주석처
//	        	if(!layoutName.matches(fattern)) {
//	        		throw new BizException("잘못된 전문레이아웃명 입니다.\n명명규칙을 확인하세요.\n"+fattern);
//	        	}
	        	
		        String layout = body.getChild("data").getText();
				logger.info("{} recv Data - [{}]]", layoutName, layout);
				param.put("recvData", layout);
				
		        Document doc2 = builder.build(new StringReader(layout));
	
		        HashMap<String,Object> vo = new HashMap<String,Object>();
		        
				Element format = doc2.getRootElement();
		
		        String msgType = format.getAttributeValue("msgType");
		        String useSystem = format.getAttributeValue("usesystem");
		        
		        // useSystem "EAI", "FEP" 만 배포 받는다.
		        if (!"EAI".equalsIgnoreCase(useSystem) && !"FEP".equalsIgnoreCase(useSystem)) {
		        	String errorMessage = "사용 시스템(" + useSystem + ")인 전문레이아웃은 EAI, FEP로 배포 안됨."; 
		        	logger.error(errorMessage);
		        	throw new UseSystemException(errorMessage);
		        }
			  	
			  	if( "ASCII".equals(format.getAttributeValue("msgType")) ) {
		        	msgType = "BYTES";
		        } else if( "VASCII".equals(format.getAttributeValue("msgType")) ) {
		        	msgType = "VBYTES";
		        }
		        
				// Layout Format (TR07)
		        vo.put("loutName",layoutName);
		        vo.put("loutPtrnName",msgType); //  ASCII, EBCDIC, XML
		        vo.put("loutDesc",format.getAttributeValue("desc"));  

		        String date = format.getAttributeValue("date");
		        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		        vo.put("lastAmndHMS",new SimpleDateFormat("yyyyMMddHHmmssSS").format(sdf.parse(date)));
		        
		        vo.put("eaiBzwkDstcd",format.getAttributeValue("group"));
		        
		        if( !"".equals(format.getAttributeValue("createBy"))) {
		        	vo.put("createBy",format.getAttributeValue("createBy"));
		        }

		        if( !"".equals(format.getAttributeValue("updateBy"))) {
		        	vo.put("updateBy",format.getAttributeValue("updateBy"));
		        }
		        
		        
				// Layout Item Format (TR08)
		        List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
		        HashMap<String,Object> tr08 = new HashMap<String,Object>();
		        tr08.put("loutName",layoutName);
		        tr08.put("loutItemName",layoutName);
		        tr08.put("loutItemSerno",0);
		        tr08.put("loutItemIDName",1000);
		        tr08.put("parntLoutItemIDName",0);
		        tr08.put("loutItemDesc",format.getAttributeValue("desc"));
		        tr08.put("loutItemNodePtrnIDName",Item.NODE_MESSAGE);
		        tr08.put("loutItemPtrnIDName",Types.TYPE_UNKNOWN);
		        tr08.put("loutItemPathName",""); // 
		        tr08.put("loutItemLenCnt",0);
		        tr08.put("loutItemRefInfo",""); // GROUP NAME
		        tr08.put("loutItemRefInfo2",""); // 
		        tr08.put("loutItemOccurPtrnDstcd",""); // 레이아웃항목발생유형구분코드
		        tr08.put("loutItemMaxOccurNoitm",0); // 레이아웃항목최대발생건수
		        tr08.put("loutItemMinOccurNoitm",0); // 레이아웃항목최소발생건수
		        tr08.put("loutItemBascVal","");  // 레이아웃항목기본값
		        tr08.put("loutItemMskYn"," "); // 
		        tr08.put("lyoutDptCnt",1);
		        tr08.put("decptLenCnt",0); // 소수점길이
		        tr08.put("lyoutItemRefPtrnIdName",""); // 데이터타입
		        
		        list.add(tr08);
		        list.addAll(setLayoutItems(format, msgType, layoutName));
				
		        service.insertLayout(vo, list);  //FIXME : 스키마 변경 룰 적용해야 함
		        
	            CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.ReloadLayoutCommand",vo.get("loutName"));
	            HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
	            param.putAll(result);
		    	service.addLayoutSyncLog(param);
		        
		        
	        }
	        results.getChild("Result").setText("S".equals(param.get("prcssRslt"))?"True":"False");
	        results.getChild("ResultMessage").setText("S".equals(param.get("prcssRslt"))?"성공":param.get("prcssRsltCmnt"));

	        resultS = StringUtils.toXMLString(rDoc, true);
	        
    	} catch( Exception e ) {
    		logger.error("",e);
    		try {
	    		if( results != null ) {
			        if (e instanceof UseSystemException) {
			        	results.getChild("Result").setText("True");
			        } else {
			        	results.getChild("Result").setText("False");
			        }
			        results.getChild("ResultMessage").setText( e.getMessage() );
			        
			        
			        
			        resultS = StringUtils.toXMLString(rDoc, true);
	    		}
	    		if( param.get("logPrcssSeqno") == null ) {
	    			param.put("logPrcssSeqno", UUIDGenerator.getUUID());
	    			param.put("ServiceName", "MessageSync");
	    			param.put("RecvAmndHMS", recvTime);
	    		}
	    		param.put("PrcssRslt", "F");
				param.put("PrcssRsltCmnt", StringUtils.cuttings(CommonUtil.getArrayString(e.getStackTrace(), "\n"), 4000)[0]);
	    		service.addLayoutSyncLog(param);
    		} catch(Exception ee) {
        		ee.printStackTrace();
    		}
    	}

		ServletOutputStream sos = null;
    	try {
    		response.setContentType("application/xml; charset=EUC-KR");
    		sos = response.getOutputStream();
    		sos.write(resultS.getBytes("EUC-KR"));
    	} catch( Exception e ) {
    		e.printStackTrace();
    	} finally {
    		if( sis != null ) sis.close();
    		if( sos != null ) sos.close();
    	}
    	return null;
    }
    
    // JJB 수정사항 shkim 2020-05-13 JSON 타입 추가
    /**
     * 통합인터페이스 시스템(iim)에서 전문 레이아웃에 대한 INSERT, DELETE 요청
     * *
     * @param request
     * @param response
     * @param schema
     * @return
     * @throws Exception
     */
    @RequestMapping(params = "cmd=MessageJSON")
    public View parseMessageJSN(HttpServletRequest request, HttpServletResponse response, String schema) throws Exception {
        UserAccessLogger.log(request, "레이아웃", "L", "cmd=MessageJSON");

        ServletInputStream sis = null;
        
        JSONObject results = new JSONObject();
        JSONObject resultS = new JSONObject();
        resultS.put("Results", results);
        
        
        HashMap<String, String> param = new HashMap<String, String>();
        String recvTime = DateUtil.getDateTime("yyyyMMddHHmmssSS").substring(0, 16);

    	// 초기화
    	DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(schema));
    	try {
//	    	// 요청 전문
	    	sis = request.getInputStream();

    		JSONObject json = (JSONObject) JSONValue.parse(new InputStreamReader(sis, "EUC-KR"));

    		// JJB 향후제거 shkim 2020-05-13 연계 테스트 체크 
    		logger.error("\n\n MMI SYNC Request : " + json.toString());
    		
	        // log 기록
	        byte[] arg = new byte[request.getContentLength()];
	        int resultSet =0;
	        int total = 0;
	        try {
	        	resultSet = sis.readLine(arg, 0, arg.length);
	        	while(resultSet != -1) {
	        		total += resultSet;
	        		resultSet = sis.readLine(arg, total, 1024);
	        	}

	        	param.put("recvData", new String(arg, "EUC-KR"));
	        } catch(Exception e) {
	        	logger.error("MessageSync.err - don't read the JSON File - " + new String(arg, "EUC-KR"), e);
	        	param.put("recvData", "");
	        }
	        
	        //syncLayout(param, recvTime, json);
	        syncLayoutDjb(param, recvTime, json);
//	        results.getChild("Result").setText("S".equals(param.get("prcssRslt"))?"True":"False");
//	        results.getChild("ResultMessage").setText("S".equals(param.get("prcssRslt"))?"성공":param.get("prcssRsltCmnt"));

//	        resultS = StringUtils.toXMLString(rDoc, true);
	        
	        results.put("Result", "S".equals(param.get("prcssRslt"))?"True":"False");
	        results.put("ResultMessage", "S".equals(param.get("prcssRslt"))?"성공":param.get("prcssRsltCmnt"));

	        
    	} catch( Exception e ) {
    		logger.error("", e);
    		try {
	    		if( results != null ) {
//			        results.getChild("Result").setText("False");
//			        results.getChild("ResultMessage").setText( e.getMessage() );

//			        resultS = StringUtils.toXMLString(rDoc, true);
			        results.put("Result", "False");
			        results.put("ResultMessage", e.getMessage() );
			        
	    		}
	    		if( param.get("logPrcssSeqno") == null ) {
	    			param.put("logPrcssSeqno", UUIDGenerator.getUUID());
	    			param.put("ServiceName", "MessageSync");
	    			param.put("RecvAmndHMS", recvTime);
	    		}
	    		param.put("PrcssRslt", "F");
				param.put("PrcssRsltCmnt", StringUtils.cuttings(CommonUtil.getArrayString(e.getStackTrace(), "\n"), 4000)[0]);
	    		service.addLayoutSyncLog(param);
    		} catch(Exception ee) {
        		ee.printStackTrace();
    		}
    	}

		ServletOutputStream sos = null;
    	try {
    		response.setContentType("application/json; charset=EUC-KR");
    		sos = response.getOutputStream();
    		sos.write(resultS.toString().getBytes("EUC-KR"));
    	} catch( Exception e ) {
    		e.printStackTrace();
    	} finally {
    		if( sis != null ) sis.close();
    		if( sos != null ) sos.close();
    	}
    	return null;
    }

	private void syncLayout(HashMap<String, String> param, String recvTime, JSONObject json)
			throws Exception, BizException, ParseException {
		JSONObject header = (JSONObject) ((JSONObject) json.get("Message")).get("Header");
		JSONObject body = (JSONObject) ((JSONObject) json.get("Message")).get("Body");
		
		String serviceName = (String) header.get("ServiceName");
		String command = (String) header.get("Command");
		
		String interfaceId = (String) body.get("interfaceCode");
		Object layoutObject = body.get("Layout");
		
		param.put("serviceName", serviceName);
		param.put("command", command);
		param.put("recvAmndHMS", recvTime);
		
		
		
		JSONArray layoutArray = null;
		if (layoutObject instanceof JSONArray) {
			insertInterface(interfaceId,body);
			layoutArray = (JSONArray) layoutObject;
			for (int i = 0; i < layoutArray.size(); i++) {
				syncLayout(param, body, command, (JSONObject) layoutArray.get(i));
			}
		} else {
			syncLayout(param, body, command, (JSONObject) layoutObject);
		}
		
		
        // 전문 변환 매핑이 필요한 지 확인 한 후 매핑 한다. 
		if (body.get("interfaceLayout") != null && body.get("serviceLayout") != null && layoutArray != null
				&& layoutArray.size() % 2 == 0) {
			
			String[] serviceLayoutList = ((String)body.get("serviceLayout")).split(",");
			String[] interfaceLayoutList = ((String)body.get("interfaceLayout")).split(",");
			
			if ( "E".equals(interfaceId.substring(0,1)) ) // EAI일때
			{
				for( String serviceLayout : serviceLayoutList)
				{
					for(String interfaceLayout : interfaceLayoutList )
					{
						 if ( interfaceLayout.endsWith(serviceLayout) )
						 {
							String cnvsnName = transformService.transactionLayoutToTransform(json,interfaceLayout, serviceLayout);
							CommonCommand refreshCommand = new CommonCommand("com.eactive.eai.agent.transformer.ReloadTransformCommand",cnvsnName);
							//변환매핑 reload처리후, result 받아서 예외처리 안한 이유. 앞단에서 레이아웃 동기화 command 날리면서 온라인이동 통신 성공해야 여기 까이 오기때문에, 굳이 추가하지않음.
							agentUtilService.broadcast(refreshCommand);
							logger.debug(">>> reload cnvsName = " +cnvsnName);
						 }
					}
				}
			}
			else //FEP일때
			{
				for( String srcLayout : interfaceLayoutList)
				{
					for( String targetLayout : serviceLayoutList )
					{
						String cnvsnName = transformService.transactionLayoutToTransform(json,srcLayout, targetLayout);
						CommonCommand refreshCommand = new CommonCommand("com.eactive.eai.agent.transformer.ReloadTransformCommand",cnvsnName);
						//변환매핑 reload처리후, result 받아서 예외처리 안한 이유. 앞단에서 레이아웃 동기화 command 날리면서 온라인이동 통신 성공해야 여기 까이 오기때문에, 굳이 추가하지않음.
						agentUtilService.broadcast(refreshCommand);
						logger.debug(">>> reload cnvsName = " +cnvsnName);
					}
				}
			}
			
			
		}
		
		
        
	}
	
	private void insertInterface(String interfaceId, JSONObject body) throws Exception
	{
		if ( interfaceId.startsWith("E") )
		{
			insertInterfaceForEAI(interfaceId, body);
		}
		else
		{
			insertInterfaceForFEP(interfaceId, body);
		}
		
	}
	
	private void insertInterfaceForEAI(String interfaceId, JSONObject body) throws Exception
	{
		HashMap<String, Object> param = new HashMap<String, Object>();
		
		
		String bizCode = (String) body.get("bzSystemCode");
		String interfaceDesc = (String) body.get("interfaceDesc");
		String tuxedoxaYn = (String) body.get("tuxedoXaYN");
		String tuxedosvcId = (String) body.get("serviceCode");
		param.put("eaiSvcName", interfaceId+"S1"); 
		param.put("eaiBzwkDstCd", bizCode);
		param.put("interfaceId", interfaceId);
		param.put("interfaceDesc", interfaceDesc);
		param.put("io", "I");
		param.put("splizdmndDstCd","S");
		param.put("inExtnlDstCd","1");
		param.put("tuxedoxaYn", tuxedoxaYn);
		
		if( "INF".equals(interfaceId.substring(5, 8)) )
		{
			param.put("tuxedosvcId", tuxedosvcId);
		}
		
		if( "S".equals(interfaceId.substring(1, 2)) ) //sync일경우
		{
			param.put("layoutMappingName",interfaceId+"_I,"+interfaceId.substring(5, interfaceId.length())+"_O");
			param.put("svcMotivuseDstCd","SYNC");
		}
		else
		{
			param.put("layoutMappingName",interfaceId+"_I");
			param.put("svcMotivuseDstCd","ASYN");
		}
		
		interfaceService.lazyInsertToIF01(param);
		
	}
	
	private void insertInterfaceForFEP(String interfaceId, JSONObject body) throws Exception
	{
		HashMap<String, Object> param = new HashMap<String, Object>();

		String bizCode = (String) body.get("bzSystemCode");
		String interfaceDesc = (String) body.get("interfaceDesc");
		String tuxedoxaYn = (String) body.get("tuxedoXaYN");
		String tuxedosvcId = (String) body.get("serviceCode");
		
		String io = "1".equals(interfaceId.substring(1, 2)) ? "I" : "O";
		String splizdmndDstCd = interfaceId.substring(interfaceId.length()-1);
		String inExtnlDstCd = "";
		
		if ( "IS:OR".contains(io+splizdmndDstCd) )
		{
			inExtnlDstCd = "1";
			param.put("bzwksvckeyName",interfaceId.substring(5, interfaceId.length()-1));
		}
		else
		{
			inExtnlDstCd = "2";
		}
		
		param.put("eaiSvcName", interfaceId+splizdmndDstCd+inExtnlDstCd); 
		param.put("eaiBzwkDstCd", bizCode);
		param.put("interfaceId", interfaceId);
		param.put("interfaceDesc", interfaceDesc);
		param.put("io", io);
		param.put("splizdmndDstCd",splizdmndDstCd);
		param.put("inExtnlDstCd",inExtnlDstCd);
		param.put("svcMotivuseDstCd","ASYN");
		param.put("tuxedoxaYn", tuxedoxaYn);
		
		
		param.put("layoutMappingName",interfaceId+"1");

		interfaceService.lazyInsertToIF01(param);
	}

	private void syncLayout(HashMap<String, String> param, JSONObject body, String command, JSONObject layout)
			throws Exception, BizException, ParseException {
		
		String layoutName = (String) layout.get("id");
		String useSystem = (String) layout.get("usesystem");
		
		param.put("logPrcssSeqno", UUIDGenerator.getUUID());
		param.put("loutName", layoutName);
		
		logger.info(layoutName + " command - [" + command +"]");
		if( command.equals("delete") ) {
		    HashMap<String,Object> vo = new HashMap<String,Object>();
		    vo.put("loutName",layoutName);
			
		    service.deleteLayout(vo);
		    
		    CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.RemoveLayoutCommand",vo.get("loutName"));
		    HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
		    param.putAll(result);
		    
		    service.addLayoutSyncLog(param);
		} else {
			// LoutName 검증
			// 인터페이스 이름 20자리 이하  
			// EAI _CORS _CORR _CORE _UAIR
			// FEP _COR _ORG
//			String fattern = "";
//			switch(useSystem)
//			{
//			case "FEP":
//				fattern = "[A-Za-z0-9]*[12E]{1}";
//				break;
//			case "EAI":
//			case "FWK":
//				fattern = "[A-Za-z0-9]*_[IOE]{1}";
//				break;
//			}
//			
//			if(!layoutName.matches(fattern)) {
//				throw new BizException("잘못된 전문레이아웃명 입니다.\n명명규칙을 확인하세요.\n"+fattern);
//			}
			
			logger.info(layoutName + " recv Data - [" + layout + "]");
			param.put("recvData", layout.toString());
			
		    HashMap<String,Object> vo = new HashMap<String,Object>();
		    
		    String msgType = (String) layout.get("msgType");
		    if( "ASCII".equals(msgType) ) {
		    	msgType = "FEP".equals(useSystem) ? "BYTES" : "PBYTES";
		    } else if( "VASCII".equals(msgType) ) {
		    	msgType = "VBYTES";
		    }
		    
		    
			// Layout Format (TR07)
		    vo.put("loutName",layoutName);
		    vo.put("loutPtrnName",msgType); //  ASCII, EBCDIC, XML
		    vo.put("loutDesc",layout.get("desc"));  
		    vo.put("eaiSevrDstcd", "A");
		    vo.put("useYn", "1");

		    String date = (String) layout.get("date");
		    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		    vo.put("lastAmndHMS",new SimpleDateFormat("yyyyMMddHHmmssSS").format(sdf.parse(date)));
		    
		    vo.put("eaiBzwkDstcd",layout.get("group"));
		    
		    if( !"".equals(layout.get("createBy"))) {
		    	vo.put("createBy",layout.get("createBy"));
		    }

		    if( !"".equals(layout.get("updateBy"))) {
		    	vo.put("updateBy",layout.get("updateBy"));
		    }
		    
		    
			// Layout Item Format (TR08)
		    List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
		    HashMap<String,Object> tr08 = new HashMap<String,Object>();
		    tr08.put("loutName",layoutName);
		    tr08.put("loutItemName",layoutName);
		    tr08.put("loutItemSerno",0);
		    tr08.put("loutItemIDName",1000);
		    tr08.put("parntLoutItemIDName",0);
		    tr08.put("loutItemDesc",layout.get("desc"));
		    tr08.put("loutItemNodePtrnIDName",Item.NODE_MESSAGE);
		    tr08.put("loutItemPtrnIDName",Types.TYPE_UNKNOWN);
		    tr08.put("loutItemPathName",""); // 
		    tr08.put("loutItemLenCnt",0);
		    tr08.put("loutItemRefInfo",""); // GROUP NAME
		    tr08.put("loutItemRefInfo2",""); // 
		    tr08.put("loutItemOccurPtrnDstcd",""); // 레이아웃항목발생유형구분코드
		    tr08.put("loutItemMaxOccurNoitm",0); // 레이아웃항목최대발생건수
		    tr08.put("loutItemMinOccurNoitm",0); // 레이아웃항목최소발생건수
		    tr08.put("loutItemBascVal","");  // 레이아웃항목기본값
		    tr08.put("loutItemMskYn"," "); // 
		    tr08.put("lyoutDptCnt",1);
		    tr08.put("decptLenCnt",0); // 소수점길이
		    tr08.put("lyoutItemRefPtrnIdName",""); // 데이터타입
		    
		    list.add(tr08);
		    list.addAll(setLayoutItemsJSN((JSONArray) layout.get("data"), msgType, layoutName, null));
			
		    service.insertLayout(vo, list);  //FIXME : 스키마 변경 룰 적용해야 함
		    
		    //Djb custom 서버연동 제외 2026.07.22 jwh
//		    CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.ReloadLayoutCommand",vo.get("loutName"));
//		    HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
//		    param.putAll(result);
		    
		    param.put("prcssRslt", "S");
		    param.put("prcssRsltCmnt", "");
		    
			service.addLayoutSyncLog(param);
		}
	}
    
    /**
     * [통합인터페이스]에 레이아웃 정보 송신
     * * schemaId에 따라 별도로 저장 됨 
     * * filePath / schemaId / layoutName .xml 형식으로 저장 됨
     * 
     * @param request   prptyGroupName=migrationLayoutInfo
     * @param response
     * @param schema    EAI/FEP 
     * @return
     * @throws Exception
     */
    @RequestMapping(params = "cmd=M_LAYOUT")
    public String migrationLayout(HttpServletRequest request, HttpServletResponse response, ModelMap model, String schema) throws Exception {

        UserAccessLogger.log(request, "레이아웃", "M", "cmd=SYNC");

        if( !DataSourceTypeManager.EAI.equals(schema) && !DataSourceTypeManager.FEP.equals(schema) ) {
        	schema = DataSourceContextHolder.getDataSourceType().getName();
        } 
        
        // 1. 파라메터 셋팅
		String migration = monitoringContext.getStringProperty("iim.layout.migration" ,"");
		String[] props = null;
        if( migration.indexOf(";") != -1 ) {
        	props = migration.split(";");
        }
        
    	HashMap<String, String> param = new HashMap<String, String>();
    	param.put("userId", SessionManager.getUserId(request));
    	param.put("schemaId", schema);
    	param.put("filePath", StringUtils.defaultString(props[0], request.getSession().getServletContext().getRealPath("/WEB-INF/")));
    	param.put("encoding", StringUtils.defaultString(props[1],"EUC-KR"));
    	param.put("indent",   StringUtils.defaultString(props[2],"yes"));
    	param.put("path", request.getSession().getServletContext().getRealPath("/WEB-INF/"));
    	
    	logger.debug("*** userId *** " + param.get("userId"));
    	logger.debug("*** schemaId *** " + param.get("schemaId"));
    	logger.debug("*** path *** " + param.get("path"));

    	// 2. 지정 스키마 변경 
    	DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(param.get("schemaId")));

    	// 3. 전체 레이아웃 목록 조회
        List<HashMap<String,Object>> list = service.getAllLayouts();
        int succCnt = 0;
        try {

	        // 폴더 초기화 후 생성
	        File mkf = new File(param.get("filePath") + "/" + param.get("schemaId"));			        
	        if( mkf.exists() ) { 
	        	File[] fList = mkf.listFiles();
	        	for( int i=0; i< fList.length; i++) {
	        		fList[i].delete();
	        	}
	        	mkf.delete();
	        }
	        mkf.mkdir();
	        
	        
	        for( HashMap<String,Object> layout : list ) {
	        	// 4. 레이아웃 상세 정보 조회 
	        	param.put("LoutName", (String)layout.get("LOUTNAME"));
		    	HashMap<String, String> result = service.migrationLayoutToXML(param);
		        	
		    	String xmlQuery = result.get("xmlQuery");
		
				//5. XML 파일 생성
		        // Layout별로 생성
		        String newName = param.get("filePath") + "/" + param.get("schemaId") 
		                       + "/" + layout.get("LOUTNAME") + ".xml";
		        
		        // 파일 저장
		    	File newFile = new File(newName);
		    	
		    	TransformerFactory factory = TransformerFactory.newInstance();
		    	Transformer transformer = factory.newTransformer();
		    	transformer.setOutputProperty(OutputKeys.ENCODING, param.get("encoding"));
		    	transformer.setOutputProperty(OutputKeys.INDENT, param.get("indent"))	;
		    	
		    	Reader r = new StringReader(xmlQuery);
		    	org.w3c.dom.Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(r));
		    	
		    	DOMSource src = new DOMSource(d);
		    	StreamResult rst = new StreamResult(new File(newName));
		    	transformer.transform(src,rst);
		    	succCnt++;
	        }
        } catch(Exception e) {
        	e.printStackTrace();
        }

        return null;
    }
    

    @RequestMapping(params = "cmd=M_LAYOUT_MAPPING")
    public String migrationLayoutMapping(HttpServletRequest request, HttpServletResponse response, ModelMap model, String schema) throws Exception {

        UserAccessLogger.log(request, "레이아웃", "M", "cmd=SYNC");

        if( !DataSourceTypeManager.EAI.equals(schema) && !DataSourceTypeManager.FEP.equals(schema) ) {
        	schema = DataSourceContextHolder.getDataSourceType().getName();
        } 
        
        // 1. 파라메터 셋팅
		String migration = monitoringContext.getStringProperty("iim.layout.migration" ,"");
		String[] props = null;
        if( migration.indexOf(";") != -1 ) {
        	props = migration.split(";");
        }
        
    	HashMap<String, String> param = new HashMap<String, String>();
    	param.put("userId", SessionManager.getUserId(request));
    	param.put("schemaId", schema);
    	param.put("filePath", StringUtils.defaultString(props[0], request.getSession().getServletContext().getRealPath("/WEB-INF/")));
    	param.put("encoding", StringUtils.defaultString(props[1],"EUC-KR"));
    	param.put("indent",   StringUtils.defaultString(props[2],"yes"));
    	param.put("path", request.getSession().getServletContext().getRealPath("/WEB-INF/"));
    	
    	logger.debug("*** userId *** " + param.get("userId"));
    	logger.debug("*** schemaId *** " + param.get("schemaId"));
    	logger.debug("*** path *** " + param.get("path"));

    	// 2. 지정 스키마 변경 
    	DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(param.get("schemaId")));

    	// 3. 전체 eaisvcname 목록 조회     
        List<HashMap<String,Object>> list = service.getAllEAIMessages(param);	 
        int succCnt = 0;
        try {

	        // 폴더 초기화 후 생성
	        File mkf = new File(param.get("filePath") + "/mapping_" + param.get("schemaId"));			        
	        if( mkf.exists() ) { 
	        	File[] fList = mkf.listFiles();
	        	for( int i=0; i< fList.length; i++) {
	        		fList[i].delete();
	        	}
	        	mkf.delete();
	        }
	        mkf.mkdir();
	        
	        for( HashMap<String,Object> message : list ) {
	        	param.put("eaiSvcName", (String)message.get("EAISVCCD"));
	        	param.put("cmd", "insert");
	        	String xmlQuery = service.getLayoutMappingXMLList(param);
	        	
		
				//5. XML 파일 생성
		        // Layout별로 생성
		        String newName = param.get("filePath") + "/mapping_" + param.get("schemaId") + "/" + message.get("EAISVCCD") + ".xml";
		        
		        // 파일 저장
		        if( xmlQuery.indexOf("Layout") != -1) {
			    	File newFile = new File(newName);
			    	
			    	TransformerFactory factory = TransformerFactory.newInstance();
			    	Transformer transformer = factory.newTransformer();
			    	transformer.setOutputProperty(OutputKeys.ENCODING, param.get("encoding"));
			    	transformer.setOutputProperty(OutputKeys.INDENT, param.get("indent"))	;
			    	
			    	Reader r = new StringReader(xmlQuery);
			    	org.w3c.dom.Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(r));
			    	
			    	DOMSource src = new DOMSource(d);
			    	StreamResult rst = new StreamResult(new File(newName));
			    	transformer.transform(src,rst);
			    	succCnt++;
		        }
	        }
        } catch(Exception e) {
        	e.printStackTrace();
        }
        return null ;
    }
    
    
    private void syncLayoutDjb(HashMap<String, String> param, String recvTime, JSONObject json)
			throws Exception, BizException, ParseException {
    	JSONObject header = (JSONObject) ((JSONObject) json.get("Message")).get("Header");
		JSONObject body = (JSONObject) ((JSONObject) json.get("Message")).get("Body");
		
		String serviceName = (String) header.get("ServiceName");
		String command = (String) header.get("Command");
		
		Object layoutObject = body.get("Layout");
		
		param.put("serviceName", serviceName);
		param.put("command", command);
		param.put("recvAmndHMS", recvTime);
				
		JSONArray layoutArray = null;
		if (layoutObject instanceof JSONArray) {
			layoutArray = (JSONArray) layoutObject;
			for (int i = 0; i < layoutArray.size(); i++) {
				syncLayout(param, body, command, (JSONObject) layoutArray.get(i));
			}
		} else {
			syncLayout(param, body, command, (JSONObject) layoutObject);
		}
    }

}
