package com.eactive.eai.transformer.dao.excel;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eactive.eai.transformer.dao.TransformerDaoException;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.ItemFactory;
import com.eactive.eai.transformer.layout.Layout;
import com.eactive.eai.transformer.layout.LayoutType;
import com.eactive.eai.transformer.layout.LayoutTypeManager;
import com.eactive.eai.transformer.layout.LayoutValidator;
import com.eactive.eai.transformer.layout.Types;
import com.eactive.eai.transformer.message.Message;
import com.eactive.eai.transformer.message.MessageFactory;
import com.eactive.eai.transformer.util.ConstantUtil;

@Service
public class Layout2ExcelDao extends BaseExcelDao<String, Layout> {
	private static String COL_REGEXP_LAYOUT_DESC;
	private int COL_LAYOUT_DESC;

	private static String COL_REGEXP_NO;
	private int COL_NO;

	private static String COL_REGEXP_DESC;
	private int COL_DESC;

	private static String COL_REGEXP_DPTH;
	private int COL_DPTH;

	private static String COL_REGEXP_NODE;
	private int COL_NODE;
	private static String COL_REGEXP_OCC_TYPE;
	private int COL_OCC_TYPE;

	private static String COL_REGEXP_OCC_REF;
	private int COL_OCC_REF;

	private static String COL_REGEXP_TYPE;
	private int COL_TYPE;

	private static String COL_REGEXP_LEN;
	private int COL_LEN;
	private static String COL_REGEXP_DEC_POINT_LEN;
	private int COL_DEC_POINT_LEN; // 소숫점길이

	private static String COL_REGEXP_CODE;
	private int COL_CODE;

	private static String COL_REGEXP_NAME;
	private int COL_NAME;
	private static int COL_BASE; // EAI(...) 라고 표시된 컬럼
	private static String COL_REGEXP_START_FLAG;
	private static String COL_REGEXP_MATCH_FLAG;

	private static String COL_REGEXP_NOTE;
	private int COL_NOTE;

	private int COL_DEFAULT; // EAI초기값

	private int COL_CHANGE_BASE;
   
   private String SHEET_NAME;
	@Autowired
	protected LayoutTypeManager layoutTypeManager;

	public Layout2ExcelDao() {
		super("layout2");
		LayoutExcelLoadFormatManager manager = LayoutExcelLoadFormatManager.getInstance();
		COL_REGEXP_LAYOUT_DESC = manager.getData("COL_REGEXP_LAYOUT_DESC");// 인터페이스명
		COL_REGEXP_NO = manager.getData("COL_REGEXP_NO");// 일련번호
		COL_REGEXP_DESC = manager.getData("COL_REGEXP_DESC");// 한글명
		COL_REGEXP_DPTH = manager.getData("COL_REGEXP_DPTH");// 깊이
		COL_REGEXP_NODE = manager.getData("COL_REGEXP_NODE");// 항목편진구분코드(GROUP/FIELD/ARRAY)
		COL_REGEXP_OCC_TYPE = manager.getData("COL_REGEXP_OCC_TYPE");// 배열최대갯수
		COL_REGEXP_OCC_REF = manager.getData("COL_REGEXP_OCC_REF");// 반복횟수참조정보
		COL_REGEXP_TYPE = manager.getData("COL_REGEXP_TYPE");// 테이터타입(String/Long/BigDecimal)
		COL_REGEXP_LEN = manager.getData("COL_REGEXP_LEN");// 데이터길이
		COL_REGEXP_DEC_POINT_LEN = manager.getData("COL_REGEXP_DEC_POINT_LEN");// 소숫점길이
		COL_REGEXP_CODE = manager.getData("COL_REGEXP_CODE");// 코드변환
		COL_REGEXP_NAME = manager.getData("COL_REGEXP_NAME");// 영문명
		COL_REGEXP_NOTE = manager.getData("COL_REGEXP_NOTE");// 비고

		COL_REGEXP_START_FLAG = manager.getData("COL_REGEXP_START_FLAG");
		COL_REGEXP_MATCH_FLAG = manager.getData("COL_REGEXP_MATCH_FLAG");
		COL_LAYOUT_DESC = manager.getInt("COL_LAYOUT_DESC");// 인터페이스명
		COL_NO = manager.getInt("COL_NO");// 일련번호
		COL_DESC = manager.getInt("COL_DESC");// 한글명
		COL_DPTH = manager.getInt("COL_DPTH");// 깊이
		COL_NODE = manager.getInt("COL_NODE");// 항목편진구분코드(GROUP/FIELD/ARRAY)
		COL_OCC_TYPE = manager.getInt("COL_OCC_TYPE");// 배열최대갯수
		COL_OCC_REF = manager.getInt("COL_OCC_REF");// 반복횟수참조정보
		COL_TYPE = manager.getInt("COL_TYPE");// 테이터타입(String/Long/BigDecimal)
		COL_LEN = manager.getInt("COL_LEN");// 데이터길이
		COL_DEC_POINT_LEN = manager.getInt("COL_DEC_POINT_LEN");// 소숫점길이
		COL_CODE = manager.getInt("COL_CODE");// 코드변환
		COL_NAME = manager.getInt("COL_NAME");// 영문명
		COL_NOTE = manager.getInt("COL_NOTE");// 비고

		COL_NOTE = manager.getInt("COL_DEFAULT");// 비고
		COL_BASE = manager.getInt("COL_BASE");// 베이스
      SHEET_NAME = manager.getData("SHEET_NAME");// sheet명
	}
	
    protected Map<String, Layout> loadExcelFile(String filename) {
    	File file = new File(filename);
    	
    	if (file.getName().startsWith("-")) {
    		return new TreeMap<>();
    	}

        InputStream in = null;

        try {
            /**
             * find sheets
             */
            in = new BufferedInputStream(new FileInputStream(filename));
            ExcelSheet[] sheets = null;
         
            try {
                sheets = ExcelSheet.getExcelSheets(in);
            } catch (Exception e) {
                throw new Exception("sheets 를 얻어낼 수 없읍니다. - '" + filename + "'", e);
            }

            if (logger.isDebugEnabled()) {
            	String msg = String.format("    - %-25s | %s", "loading excel ", filename);
            	logger.debug(msg);
            }

            return loadSheets(sheets);
        } catch (Exception e) {
            throw new TransformerDaoException("error when load excel file '" + filename + "'", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                }
            }
        }
    }    


	@Override
	protected Map<String, Layout> loadSheets(Sheet[] sheets) throws Exception {
		return parse(sheets);	
	}

	@Override
	protected Map<String, Layout> parse(Sheet[] sheets) throws Exception {
        Map<String, Layout> map = new TreeMap<>();
        map.putAll(parse(sheets[2]));
        if(sheets.length > 3) {
            map.putAll(parse(sheets[3]));
        }
        return map;
	}
        
	protected Map<String, Layout> parse(Sheet sheet) throws Exception {
        parseColumnMapping(sheet);
		
		Map<String, Layout> treeMap = new TreeMap<>();

        try {
        	int columnBase = COL_BASE;
        	if(!sheet.getCellString(0, COL_CODE).equals(COL_REGEXP_CODE)){        		
        		columnBase = COL_CHANGE_BASE;
        	}
			while (columnBase < 100 && sheet.existsCell(0, columnBase)) {
				/**
				 * EAI(...) 값이 아니면 무시한다.
				 */
				String eaiFlag = sheet.getCellString(0, columnBase);
				String layoutTypeName = sheet.getCellString(2, columnBase).trim();
		    	if ("ASCII".equals(layoutTypeName)) {
		    		layoutTypeName = "BYTES";
		    	}				
		    	
		    	if ("VASCII".equals(layoutTypeName)) {
		    		layoutTypeName = "VBYTES";
		    	}
		    	
				if (eaiFlag == null) { 		
					break;
				} else if (!eaiFlag.matches(COL_REGEXP_START_FLAG) || "".equals(layoutTypeName.trim())) {			
					columnBase++;
					continue;
				}
				
				if (!eaiFlag.matches(COL_REGEXP_MATCH_FLAG)) {
					throw new Exception("cell[0, " + columnBase + "] must be like "+ COL_REGEXP_MATCH_FLAG);
				}
				
		        /**
		         * layout type
		         */
		        LayoutType layoutType = layoutTypeManager.getLayoutType(layoutTypeName);
		        if (layoutType == null) {
		            throw new TransformerDaoException("LayoutTypeManager에서 LoutPtrnName을 찾을 수 없습니다. - " + layoutTypeName);
		        }
	
		        /**
		         * message
		         */
		        StringBuffer sb = new StringBuffer();
		        sb.append(sheet.getCellString(1, columnBase).trim() + "_");
				sb.append(sheet.getCellString(3, columnBase).trim() + "_");
				sb.append(eaiFlag.substring(eaiFlag.indexOf('(')+1, eaiFlag.indexOf(')')));
				String layoutName = sb.toString();
				Message root = makeMessage(sheet, layoutTypeName, layoutName);
				//Item rootItem = (Item) message;
				root.setDepth(1);
				
				// Default Setting
				root.setDataTypeId(Types.TYPE_UNKNOWN);
				root.setLength(-1);
				
				try {
					root.setDescription(sheet.getCellString(4, COL_LAYOUT_DESC).trim());
				} catch(Exception e) {
					root.setDescription("");
				}
	
				/**
				 * build item tree
				 */
				int rownum = 4;
				root.setLayoutName(layoutName);
				//rootItem.setDescription(sheet.getCellString(rownum, 3).trim());
				
				// 2009.05.29
				// 중복확인
				validateLayout(layoutName, sheet, columnBase, rownum);
				
				root = (Message) buildTree(layoutName, root, sheet, layoutTypeName, columnBase, rownum);
				root.initItemParentId(0, 0);
	
				/**
				 * layout
				 */
		        Layout layout = new Layout();
		        layout.setName(root.getName());
		        layout.setDescription(root.getDescription());
		        layout.setBzwkDstcd(sheet.getCellString(1, columnBase).trim());
		        layout.setLastUpdateDate(LocalDateTime.now());
		        layout.setSystemInterface(sheet.getCellString(3, columnBase).trim());
		        
		        layout.setRootItem(root);
		        root.setLayout(layout);      
		        layout.setLayoutType(layoutType); 
		        
		        /**
		         * set overwrite -> 무조건 한다..
		         */
		        boolean overwrite = true; //sheet.isEquals(6, 4, "O");        
		        layout.setOverwrite(overwrite);
		        
		        /**
		         * LayoutValidate
		         */
		        LayoutValidator.validate(layout);
		        
		        
		        /**
		         * tree map 추가..
		         */
		        treeMap.put(layout.getName(), layout);
		        columnBase++;
			}
			
			return treeMap;
		} catch(Exception e) {
			throw new TransformerDaoException(e.getMessage(), e);
		}		
	}
	
	private void parseColumnMapping(Sheet sheet) throws Exception {
		HashMap<String, String> columnMap = new HashMap<String, String>();
		columnMap.put(COL_REGEXP_LAYOUT_DESC, COL_REGEXP_LAYOUT_DESC);
		columnMap.put(COL_REGEXP_NO, COL_REGEXP_NO);
		columnMap.put(COL_REGEXP_DESC, COL_REGEXP_DESC);
		columnMap.put(COL_REGEXP_DPTH, COL_REGEXP_DPTH);
		columnMap.put(COL_REGEXP_NODE, COL_REGEXP_NODE);
		columnMap.put(COL_REGEXP_OCC_TYPE, COL_REGEXP_OCC_TYPE);
		columnMap.put(COL_REGEXP_OCC_REF, COL_REGEXP_OCC_REF);
//		columnMap.put(COL_REGEXP_OCC_MIN, COL_REGEXP_OCC_MIN);
		columnMap.put(COL_REGEXP_TYPE, COL_REGEXP_TYPE);
		columnMap.put(COL_REGEXP_LEN, COL_REGEXP_LEN);
		columnMap.put(COL_REGEXP_DEC_POINT_LEN, COL_REGEXP_DEC_POINT_LEN);
		columnMap.put(COL_REGEXP_NAME, COL_REGEXP_NAME);
		columnMap.put(COL_REGEXP_NOTE, COL_REGEXP_NOTE);

		for (int i=0; i<COL_BASE+30; i++) {
			if (!sheet.existsCell(0, i))
				break;
			
			String name = sheet.getCellString(0, i);		
			if (name == null)
				continue;
			
			if (name.replaceAll("\\s+", "").matches(COL_REGEXP_LAYOUT_DESC)) { 				
				COL_LAYOUT_DESC = i;
				columnMap.remove(COL_REGEXP_LAYOUT_DESC);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_NO)) { 				
				COL_NO = i;
				columnMap.remove(COL_REGEXP_NO);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_DESC)) {			
				COL_DESC = i;
				columnMap.remove(COL_REGEXP_DESC);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_DPTH)) {				
				COL_DPTH = i;
				columnMap.remove(COL_REGEXP_DPTH);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_NODE)) {		
				COL_NODE = i;
				columnMap.remove(COL_REGEXP_NODE);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_OCC_TYPE))	{		
				COL_OCC_TYPE = i;
				columnMap.remove(COL_REGEXP_OCC_TYPE);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_OCC_REF)) {	
				COL_OCC_REF = i;
				columnMap.remove(COL_REGEXP_OCC_REF);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_TYPE)) {
				COL_TYPE = i;
				columnMap.remove(COL_REGEXP_TYPE);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_LEN)) {	
				COL_LEN = i;
				columnMap.remove(COL_REGEXP_LEN);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_DEC_POINT_LEN)) {			
				COL_DEC_POINT_LEN = i;
				columnMap.remove(COL_REGEXP_DEC_POINT_LEN);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_NAME))	{
				COL_NAME = i;
				columnMap.remove(COL_REGEXP_NAME);
			} else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_NOTE))	{
				COL_NOTE = i;
				columnMap.remove(COL_REGEXP_NOTE);
			} 
//			else if (name.replaceAll("\\s+", "").matches(COL_REGEXP_MASK))	{
//				COL_MASK = i;
//			}
		}
		
		if (columnMap.size() > 0) {
			StringBuilder sb = new StringBuilder();
			sb.append("excel file does not have columns [");
			for (Iterator iter = columnMap.keySet().iterator(); iter.hasNext(); ) {
				sb.append(iter.next() + ",");
			}
			sb.append("] - check excel file format");
			throw new Exception(sb.toString());
		}
	}

	
	private Message makeMessage(Sheet sheet, String layoutTypeName, String layoutName) throws Exception {
//		String nodeType = "MESSAGE";	
		Message message = MessageFactory.getFactory().createMessage(layoutTypeName);

		((Item) message).setName(layoutName);
	    ((Item) message).setLayoutName(layoutName);
	    
	    return message;
	}	
	
	private void validateLayout(String layoutName, Sheet sheet, int columnBase, int rownum) throws Exception {
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
		
		for (int currentRow = rownum; sheet.existsRow(currentRow); currentRow++) {
			String use = sheet.getCellString(currentRow, columnBase);
			if (use == null || !use.trim().matches("(o|O|0|○|y|Y)")) {	
		    	continue;
	    	}
			
			// 일련번호 중복 처리
			int seq = (new Double(sheet.getCellValue(currentRow, COL_NO))).intValue();
			if(map.get(seq) != null) {
				throw new Exception(layoutName + "의 일련번호가 중복되었습니다 - [row=" + currentRow + ", col=" + COL_NO + "]");
			}
			else {
				map.put(seq, currentRow);
			}
			
			// 아이템명 중복처리
//			String itemName = sheet.getCellValue(currentRow, COL_NAME);
//System.out.println("itemName===========================>"+itemName);
//			if(nameMap.get(itemName) != null) {
//				throw new Exception(layoutName + "의 거래(입|출)력항목명(영문)이 중복되었습니다 - [row=" + currentRow + ", col=" + COL_NAME + "]");
//			}
//			else {
//				nameMap.put(itemName, currentRow);
//			}
			
			// 한글명 필수입력 확인
			String desc = sheet.getCellValue(currentRow, COL_DESC);
			
			if(desc == null || desc.trim().length() == 0) {
				throw new Exception(layoutName + "의 거래(입|출)력항목명(한글)이 입력되지 않았습니다. - [row=" + currentRow + ", col=" + COL_DESC + "]");
			}
		}
		map.clear();		
	}
	
	private Item buildTree(String layoutName, Item parent, Sheet sheet, String layoutTypeName, int columnBase, int rownum) throws Exception {
		Item item = null;
		while (rownum < 1000) {
			item = makeItem(sheet, layoutTypeName, columnBase, rownum);
			if (item != null) {
				break;
			} else {
				rownum++;
			}
		}
		
		if (item == null) {
			return parent;
		}
			
		Item next = null;
		if (sheet.existsRow(rownum+1)) {
	        next = makeItem(sheet, layoutTypeName, columnBase, rownum+1);
		}
	
        item.setLayoutName(layoutName);
      
        if (!sheet.existsRow(rownum)) { // 마지막일 경우 
			return parent;
		} else if (item.getDepth() > parent.getDepth()) { // 그룹의 항목일 경우
            parent.addChild(item);
            item.setParent(parent);
            
            //----------------------------------------------------
            // Layout 로딩시 이중 ARRAY 등록시 에러처리 : 2009.04.08
            //----------------------------------------------------
            if( (item.getNodeTypeId() == Item.NODE_GROUP) && (item.getOccMax() > 1) 
             && (parent.getNodeTypeId() == Item.NODE_GROUP) && (parent.getOccMax() > 1) ) {
        		throw new Exception("이중 ARRAY는 지원하지 않습니다. - 다음 layout item 처리시 에러 발생 - " + item.getName());
            }
            //----------------------------------------------------
            
            if (next == null) {
        		if (sheet.existsRow(rownum+1)) {
	      			++rownum;
	      			
	      			// NODE_MESSAGE 또는 NODE_GROUP 일  경우에 대한 Parent ID 오류 수정 : 2009.03.11
	      			// NODE_GROUP 다음의 필드가  'O' 가 아닐 경우 
	      			if(item.getNodeTypeId() == Item.NODE_MESSAGE || item.getNodeTypeId() == Item.NODE_GROUP) {
	      				item = buildTree(layoutName, item, sheet, layoutTypeName, columnBase, ++rownum);
	      			}
	      			else {
	      				// 2009.06.30
	      				// Group의 하위항목의 마지막이 'O' 가 아닐 경우
	      				// parent 계산의 문제가 있음
	      				
	      				// 2009.10.13 그룹 다음에 'O'가 아닌 항목이 여러 개 올 경우
	      				//---------------------------------------------------------
	      				int p = 1;
	      				while(true) {
	      					next = makeItem(sheet, layoutTypeName, columnBase, rownum+p);
	      					if(next != null || (rownum+p) >= 1000) break;
	      					p++;
	      				}
//	      				next = makeItem(sheet, layoutTypeName, columnBase, rownum+1);
	      				//---------------------------------------------------------
	      				if(next != null) {
		      				if(item.getDepth() > next.getDepth()) { 
		      					for (int i=0; i<item.getDepth() - next.getDepth(); i++)
		      						parent = parent.getParent();					
		      				}
	      				}
		      			item = buildTree(layoutName, parent, sheet, layoutTypeName, columnBase, ++rownum);
	      			}
        		}
    		} else if (next.getDepth() > item.getDepth()) {
            	item = buildTree(layoutName, item, sheet, layoutTypeName, columnBase, ++rownum);
            } else if (next.getDepth() == item.getDepth()) {
            	parent = buildTree(layoutName, parent, sheet, layoutTypeName, columnBase, ++rownum); 
            } else {
            	for (int i=0; i<item.getDepth() - next.getDepth(); i++)
            		parent = parent.getParent();
            	parent = buildTree(layoutName, parent, sheet, layoutTypeName, columnBase, ++rownum);
            }
            return parent;
        } else {
        	throw new Exception("(depth를 포함한) layout 구조를 확인하십시요 - 다음 layout item 처리시 에러 발생 - " + item.getName());
        }
    }
	

	private Item makeItem(Sheet sheet, String layoutTypeName, int columnBase, int rownum) throws Exception {
		if (!sheet.existsRow(rownum)
			|| sheet.getCellValue(rownum, 0) == null 
			|| sheet.getCellValue(rownum, 1) == null) {
    		return null;
    	}

		/**
		 * 'o|O|0|○|y|Y' 값이 아니면 null을 return 한다.
		 */
		String use = sheet.getCellString(rownum, columnBase);
		if (use == null || !use.trim().matches("(o|O|0|○|y|Y|M|m|D)")) {	
    		return null;
    	}
		
		Item item = null;

    	try {
			String nodeType = sheet.getCellString(rownum, COL_NODE).trim();	
			String name = sheet.getCellString(rownum, COL_NAME).trim();
			if (name.trim().length() <= 0) {	
				//return null;
				throw new Exception("거래입/출력항목명이 입력되지 않았습니다. [row=" + rownum + ", col=" + COL_NAME + "]");
			}
			else {
				if(name.indexOf(".") > -1) {
					throw new Exception("거래입/출력항목명에 '.'을 사용할 수 없습니다. [row=" + rownum + ", col=" + COL_NAME + "] - "+name);
				}
			}
			
			int nodeTypeId = ConstantUtil.getNodeTypeId(nodeType);
	        item = ItemFactory.createItem(nodeTypeId);
			//item.setNodeTypeId(nodeTypeId);
	        item.setName(name);
	        
	        // 사용여부가  M/m 인 경우 Masking 필드로 설정한다.
	        if( "M".equalsIgnoreCase(use)) {
	        	item.setMask("Y");
	        }
	        else {
	        	item.setMask(" ");
	        }
	        
	        //----------------------------------------------------------------
	        // 2009.05.29 
	        // 일련번호는 0보다 큰 값이어야 한다.
	        try {
				item.setSeqNo((new Double(sheet.getCellValue(rownum, COL_NO))).intValue());
			} catch (NumberFormatException e) {
				throw new Exception("sequence number is invalid value [row=" + rownum + ", col=" + COL_NO + "]='" + sheet.getCellValue(rownum, COL_NO) +
						"' - " + e.getMessage());
//				logger.warn("sequence number is invalid value [row=" + rownum + ", col=" + COL_NO + "]='" + sheet.getCellValue(rownum, COL_NO) +
//						"' - " + e.getMessage());
//				item.setSeqNo(-1);
			}
			
			if(item.getSeqNo() < 1) {
				throw new Exception(item.getName() + " - 일련번호는 0보다 커야 합니다.");
			}
			//----------------------------------------------------------------
			
			
			if (sheet.getCellInt(rownum, COL_DPTH) <= 0) {
				throw new Exception(item.getName() + "'s DEPTH = '" + sheet.getCellInt(rownum, COL_DPTH) + 
						"', 'DEPTH' value must be greate than 0");
			}
			item.setDepth(sheet.getCellInt(rownum, COL_DPTH) + 1);
			
			item.setDescription(sheet.getCellString(rownum, COL_DESC).trim());
			item.setDataTypeRef(sheet.getCellString(rownum, COL_TYPE).trim());
			
			// 2010.01.18 권세환대리
			// 필드설명에 '비밀'이라는 문자가 있으면 강제 Masking
			if(item.getDescription() != null && item.getDescription().indexOf("비밀") != -1) {
				item.setMask("Y");
			}
			
			
			// 2009.03.20
			// nodeTypeId 이 NODE_MESSAGE, NODE_GROUP 면  DataTypeId 를 강제로 TYPE_UNKNOWN 설정
			// XLS 등록시 오류방지
			if(nodeTypeId == Item.NODE_MESSAGE || nodeTypeId == Item.NODE_GROUP) {
				item.setDataTypeId(Types.TYPE_UNKNOWN);
			}
			else {
				item.setDataTypeId(ConstantUtil.getDataTypeId(sheet.getCellString(rownum, COL_TYPE).trim(), layoutTypeName));
			}
			try {
				/*
				// PIC S9(n)V9(d) 인 경우 길이에 (+1) 하도록 한다. 
				if( "PIC S9(n)V9(d)".equals(item.getDataTypeRef()) ) {
					item.setLength(sheet.getCellInt(rownum, COL_LEN)+1);
				}
				else {
					item.setLength(sheet.getCellInt(rownum, COL_LEN));
				}
				*/
				
				item.setLength(sheet.getCellInt(rownum, COL_LEN));
				
			} catch (Exception e) {
				item.setLength(0);
			}
			try {
				item.setDecimalPointLength(sheet.getCellInt(rownum, COL_DEC_POINT_LEN));
			} catch (Exception e) {
				item.setDecimalPointLength(0);
			}
						
			/**
			 * occRef
			 */
			item.setOccRef(sheet.getCellString(rownum, COL_OCC_REF).trim());
			if (!"".equals(item.getOccRef())) {
				item.setOccType("+");
			}
	
			/**
			 * occType
			 */
			String occType = sheet.getCellString(rownum, COL_OCC_TYPE).trim();
			item.setOccType(occType);
	     	Matcher m = Pattern.compile("([0-9]+)\\.\\.([0-9]*)").matcher(occType);
	        if (m.find()) {
	            item.setOccMin(Integer.parseInt(m.group(1)));
	            if ("".equals(m.group(2))) {
	            	item.setOccMax(Integer.MAX_VALUE);
	            } else {
	            	item.setOccMax(Integer.parseInt(m.group(2)));
	            }
			} else if (("?".equals(occType.trim()))) {
				item.setOccMin(0);
				item.setOccMax(1);
			} else if (("*".equals(occType.trim()))) {
				item.setOccMin(0);
				item.setOccMax(-1);
			} else if (("+".equals(occType.trim()))) {
				item.setOccMin(1);
				item.setOccMax(-1);
			} else if (("".equals(occType.trim()))) {
				item.setOccMin(1);
				item.setOccMax(1);
			} else if (occType.trim().matches("[0-9]+")) {
				item.setOccMax(Integer.parseInt(occType.trim()));
				
				//--------------------------------------------------------
				// 2009.09.14 강길수 차장 요청
				// 반복참조회수가 있는 경우 최소값을 0인 가변배열로 정의하도록 수정
				if (item.getOccRef() != null && !"".equals(item.getOccRef().trim())) {
					item.setOccMin(0);
				}
				else {
					item.setOccMin(Integer.parseInt(occType.trim()));
				}	
				//--------------------------------------------------------
			} else {
				throw new Exception("OccType 값이 잘못 설정되었습니다. - " + occType);
			}				
			
			/**
			 * path
			 */
			if (layoutTypeName.startsWith("FML"))
				item.setPath(sheet.getCellString(rownum, COL_NOTE).trim());
			
			if (use.trim().equals("D")){
				item.setDefaultValue(sheet.getCellString(rownum, COL_DEFAULT).trim());
			}

	        return item;
    	} catch(Exception e) {
    		String itemName = "";
    		if(item != null) {
    			itemName = item.getName();
    		}

    		throw new Exception("error when read item : " + itemName, e);
    	}
	}

	@Override
	protected Map<String, Layout> removeSheets(Sheet[] sheets) throws Exception {
		return Collections.emptyMap();
	}

	public Layout findLayoutByName(String layoutName) {
		return null;
	}

	public Item findItemByName(String layoutName) {
		return null;
	}
	public Map<String, Layout> findPermanent(){
		return Collections.emptyMap();
	}

   public String getSheetName() {
      return SHEET_NAME;
   }
}
