//package com.eactive.eai.transformer.message;
//
//import java.math.BigDecimal;
//import java.util.Base64;
//import java.util.HashMap;
//import java.util.Iterator;
//import java.util.Map;
//
//import org.apache.commons.lang3.StringUtils;
//import org.json.simple.JSONArray;
//import org.json.simple.JSONObject;
//
//import com.eactive.eai.transformer.layout.Item;
//import com.eactive.eai.transformer.layout.Types;
//import com.eactive.eai.transformer.util.Logger;
//import com.fasterxml.jackson.databind.node.ObjectNode;
//
///**
// * 
// * 
// * UJSON과 차이
// *  HJSON 은 JSON 으로 출력시 항목이 없어도 GROUP이 출력됨(표준전문에만 사용됨)
// *  UJOSN 은 JSON 으로 출력시 항목이 없으면 GROUP도 출력안됨
// * 
// * 
// * @author LENOVO
// *
// */
//public class HJSONMessage extends UJSONMessage {
//    /**
//	 * 
//	 */
//	private static final long serialVersionUID = -4490794379709362079L;
//
//	private static Logger logger = Logger.getLogger("transformer");
//
//    public static final String NAME = "HJSON";
//    //private JSONObject data;
//    protected boolean bStaled = false;
//    
//    public static String  encode = "UTF-8";
//    
//    public String  MULTILANG  = "|BASE64|UTF-8|";
//    
//    public HJSONMessage() {
//        super();
//    }
//    
//    public Object getDataFromParent(Map<Integer,Object> parentDataList, Item item){
//    	Item parentItem = item.getParent();
//    	int parentIndex = parentItem == this ? 0 : parentItem.getDepth();
//    	Object parentDataObject = parentDataList.get(parentIndex);
//    	if (parentDataObject == null) return null;//HJSON 추가
//    	//원본 if(parentItem != this && "*".equals(parentItem.getOccType()) ){
//    	//참조항목이 있고 maxcount 가 있을경우 때문에수정  조건 추가 juns 20211019
//    	//JSON 고정그리드 때문에 추가 juns 20211020
//    	if(parentItem != this 
//    			&& ( "*".equals(parentItem.getOccType()) 
//    					|| "+".equals(parentItem.getOccType()) 
//    					|| parentItem.getOccMax() > parentItem.getOccMin() // OccType 이 숫자이고  max 값과 min 값이 다른경우
//    					|| (parentItem.getOccMax() == parentItem.getOccMin() && parentItem.getOccMin() > 1) // JSON 고정그리드 때문에 추가
//    			)){
//    		JSONArray parentArray = (JSONArray) parentDataObject;
//    		Object dataObj = parentArray.get(item.getParent().getIndex());
//    		if (dataObj instanceof JSONObject) {
//				JSONObject json = (JSONObject) dataObj;
//				return json.get(item.getName());
//			}else{
//				return dataObj;
//			}
//    	}else{
//    		JSONObject parentObject = (JSONObject) parentDataObject;
//    		return parentObject.get(item.getName());
//    	}
//    }
//    
//    public void setValue(JSONObject obj, String itempPath) throws InvalidAccessException {
////    	int originalLength = data.length;
//    	Item item = null;
//    	Map<Integer,Object> parentDataList = new HashMap<>();
//    	parentDataList.put(0, this.data.get(this.getLayoutName()));
//		for (Iterator iter = iterator(); iter.hasNext();) {
//			item = (Item) iter.next();
//			
//			if(item == null) {
//				continue;
//			}
//			/**
//			 * occType = * | + | (occMax>occMin) 일 경우
//			 * occRef를 참조하여 그 갯수만큼 item을 생성한다.
//			 */
//	        if (item.getIndex()==-1 && ("*".equals(item.getOccType()) || "+".equals(item.getOccType()) || item.getOccMax()>item.getOccMin() )) {
//	            int occCount = 0;
//	            String path ="";
//	            try {
//	            	//occCount = item.getRoot().getInt(item.getParent().getItemPath() + Types.FIELD_SEPARATOR + item.getOccRef());
//	            	if(item.getOccMin() > 0 && item.getOccMin() == item.getOccMax()){
//	            		occCount = item.getOccMin() ;
//	            	}else if(StringUtils.isBlank(item.getOccRef())){
////	            		JSONArray array = (JSONArray) getDataFromParent(parentDataList, item);
////	            		occCount = array.size();
//	            		Object ret = getDataFromParent(parentDataList, item);
//	            		if (ret == null){
//	            			occCount = 0;
//	            		}else if (ret instanceof JSONArray){
//	            			occCount = ((JSONArray)ret).size();
//	            		}else if (ret instanceof JSONObject){
//	            			occCount = 1;
//	            		}
//	            	}else{
//		            	path = getOccRefItem(item);
//		            	occCount = item.getRoot().getInt(path);
//	            	}
//	            	
//	            }
//	            catch(Exception oe) {
//	            	throw new InvalidAccessException(item.getName() +"의 반복참조정보 값이 숫자가 아닙니다 - " + path + " : " + oe.getMessage() , path);
//	            }
//	            
//	            if (occCount < item.getOccMin() 
//	            	|| (!"*".equals(item.getOccType()) && !"+".equals(item.getOccType()) && occCount > item.getOccMax())) { 
//	                throw new InvalidAccessException("반복횟수가 OccMin~OccMax 의 범위를 벗어납니다. , " + item.getName(), item.getItemPath());
//	            }
//	            
//	            item.createItem(item, 
//	            		item.getRoot().normalizeFullName(item.getParent().getItemPath() + Types.FIELD_SEPARATOR + item.getName() + "[" + (occCount-1) + "]"), 
//	            		false);
//
//	            /**
//	             * item 이 속해있는 childList 크기가 증가로 인해, iterator를 다시 생성한다.
//	             */
//	            iter = item.getRoot().iterator();
//	            for (;iter.hasNext();) {	
//	            	if (item.equals(iter.next())) {
//	            		break;
//	            	}
//	            }
//	        }
//	        
//			/**
//			 * index == -1 인 경우는 무시한다
//			 */
//			if (item.getIndex() == -1) {		
//				continue;
//			}
//			
//	        switch (item.getNodeTypeId()) {
//			case NODE_FIELD:
//				try {
//					/*
//					 * Field 인데 반복하는경우 
//					 * FIELD ARRAY FORMAT "name":["value1", "value2"]
//					 * data : FIELD(2203) , Type필요(2101 등등), length 필요, occType ="*", occMin=0, occMax=-1  
//					 */
//					 if ("*".equals(item.getOccType()) || "+".equals(item.getOccType()) || item.getOccMax()>item.getOccMin()) {
//						 JSONArray arrayValue = (JSONArray)getDataFromParent(parentDataList, item);
//						item.setValue(arrayValue.get(item.getIndex()));
//					 }else{
//						Object value = getDataFromParent(parentDataList, item);
//						//multi lang 고려
//						if (value instanceof String
//								&& item.getDataTypeId() == Types.TYPE_STRING
//								&& item.getMultiLang() != null){
//							String multiLang = item.getMultiLang();
//							String s = (String)value;
//							if (s != null){
//								if (multiLang != null &&(MULTILANG.contains("|"+multiLang.toUpperCase().trim()+"|")) ){
//									String b = Base64.getEncoder().encodeToString(s.getBytes(encode));
//									item.setValue(b);
//								}else{
//									item.setValue(s);
//								}
//							}
//						}else{
//							item.setValue(value);
//						}
//					 }
//				} catch(Exception e) {
//					e.printStackTrace();
//					StringBuffer sb = new StringBuffer();
//		        	sb.append("전문레이아웃 매핑 중 데이터 사이즈 오류 ("+e.getMessage()+")");
//		        	sb.append("\n");
//		        	sb.append("전문레이아웃="+item.getItemPath());
//		           throw new MessageException(sb.toString());
//				}
//				
//	            break;
//			case NODE_GROUP:
//				Object parentData = getDataFromParent(parentDataList, item);
//				parentDataList.put(item.getDepth(), parentData);
//			}
//		}
//    } 
//    
//    protected Object toJsonObjectType(int itemType, String multiLang, String value) {    	
//    	Object jsonValueObject = null;
//    	
////    	if(value == null) {
////    		return null;
////    	}
//    	switch(itemType) {
//    	case Types.TYPE_INT :
//    	case Types.TYPE_LONG :
//    	case Types.TYPE_SHORT :
//    	case Types.TYPE_DOUBLE :
//        case Types.TYPE_FLOAT :
//        case Types.TYPE_BIGDECIMAL :
//        	if (value == null) value ="0";
//        	jsonValueObject = new BigDecimal(value);
//        	break;
//        case Types.TYPE_BOOLEAN :
//        	jsonValueObject = new Boolean(value);
//        	break;
//        case Types.TYPE_STRING :
//        	if (value == null) value ="";
//			if (multiLang != null &&(MULTILANG.contains("|"+multiLang.toUpperCase().trim()+"|")) ){
//				try{
//					jsonValueObject =  new String(Base64.getDecoder().decode(value),"UTF-8");
//				}catch(Exception e){
//					jsonValueObject =  value;
//				}
//			}else{
//				jsonValueObject = value;
//			}
//        	break;	
//        default :
//        	jsonValueObject = value;
//    	}
//    	return jsonValueObject;
//    }    
//
//	protected ObjectNode getJSONData(boolean isMask) throws Exception {
//		ObjectNode root = mapper.createObjectNode();
////		JSONObject root = new JSONObject();
////		JSONObject messageName = new JSONObject();
////		root.put(getName(), messageName);
////        
////		Stack stack = new Stack();
////		Object parent = messageName;
////		Object current = null;
////		
////		JSONObject obj = null;
////		JSONArray arr = null;
////		
////		
////		stack.push(messageName);
////		int prevDepth = 1;
////		
////		Item item = null;
////		try {
////			for (Iterator iter = iterator(); iter.hasNext();) {
////				item = (Item) iter.next();
////	
////				/**
////				 * index == -1 인 경우는 무시한다
////				 */
////				if (item == null || item.getIndex() == -1) {
////					if (item.getNodeTypeId() != NODE_GROUP) continue;  //배열에서 group 명만 존재하도록 수정-그룹은 통과 (index != -1)
////				}
////				
////				/**
////				 * depth 가 낮아질 때(tree를 빠져 나올 때), parent를 재설정한다. 
////				 */
////				if (item.getDepth() < prevDepth) {
////					for(int j=0; j<(prevDepth - item.getDepth()); j++) stack.pop();
////				}	        
////		        /**
////		         * 이전 depth를 저장해 둔다.
////		         */
////				prevDepth = item.getDepth();	      
////				
////				parent = stack.peek();
////				
////				/** 
////				 * "?" 속성인 경우 값이 스페이스로 채워져 있을 때 변경  
////				 * Number Type 속성의 값이 0 인 경우 Empty 처리 ( 2013.08.02 )
////				*/  
////	            if( item.getOccMin() == 0 && item.getOccMax() == 1 ) {
////	            	if( item.getValue() == null ) continue;  
////	            	if( item.getValue() instanceof String && "".equals(((String)item.getValue()).trim()) ) continue;    
////	            	if( item.getValue() instanceof byte[] && "".equals(new String((byte[])item.getValue()).trim()) ) continue;
////	            	if( item.getValue() instanceof Number && ((Number)item.getValue()).floatValue() == 0.0f ) continue;          	
////	            }
////	            
////		        switch (item.getNodeTypeId()) {
////		        	case NODE_ATTR:
////					case NODE_FIELD:
////						
////						// 2020.02.25 : KB에서는 attr type을 사용하지 않는다.
////	//					String prefix = item.getNodeTypeId() == NODE_ATTR ? "-":"";
////						if( parent instanceof JSONObject ) {
////							obj = (JSONObject)parent;
////							
////							// validation error check
////							String val = null;
////							try {
////								val = getStringValue(item.getValue(),item);
////							}
////							catch(Exception ex) {
////								throw new Exception("item="+item.toString() +", "+ ex.getMessage());
////							}
////							// String인 경우에만 Masking 이 가능 - 숫자는 불가능
////							if (isMask && "Y".equals(item.getMask()) 
////									&& (Types.TYPE_STRING == item.getDataTypeId()) ) {
////								val = maskString2(val, item.getMaskLength(), item.getMaskOffset());							
////							}
////							//JSON default값 추가??? 20210310 jun's
////							if ("".equals(val) && item.getDefaultValue() != null) {
////								Object o = item.getDefaultValue();
////								if (o instanceof String) {
////									val = (String)o;
////								}else if (o instanceof Integer) {
////									val = Integer.toString((Integer)o);
////								}else if (o instanceof Long) {
////									val = Long.toString((Long)o);
////								}else if (o instanceof BigDecimal) {
////									val = ((BigDecimal)o).toPlainString();
////								}
////								
////							}	
////							//우체국 요건 field 값이 null 일경우에 field를 삭제한다.
////							//header 일경우는 ""
////							//최종수정 null 무시하고 toJsonObjectType에서  defaul값 셋팅 juns 20211025
//////							if (val == null ) {
////////								continue;
//////								val ="";
//////							}
////							Object value = toJsonObjectType(item.getDataTypeId(),item.getMultiLang(), val);
////							
////							if( item.getOccMax() > 1 || item.getOccMax() == -1  ) {  // FIELD ARRAY FORMAT "name":["value1", "value2"]
////								arr = (JSONArray)obj.get(item.getName());
////								if (arr == null){
////									arr = new JSONArray();
////									arr.add(value);
////	//								obj.put(prefix+item.getName(), arr);
////									obj.put(item.getName(), arr);
////								}else{
////									arr.add(value);
////								}
////								
////							}else { //FIELD
////								obj = (JSONObject)parent;
////	//							obj.put(prefix+item.getName(), value);
////								obj.put(item.getName(), value);
////							}
////						} else {
////							logger.error("JSONArray 타입의 부모를 지원하지 않음");
////							throw new Exception("JSONArray 타입의 부모를 지원하지 않음");
////						}
////	
////						break;
////					case NODE_GROUP:
////						if( parent instanceof JSONObject ) {
////							obj = (JSONObject)parent;
////							if( item.getOccMax() > 1 || item.getOccMax() == -1  ) {  // GRID
////								if (item.getIndex()== -1) {//배열에서 group 명만 존재하도록 수정 (index != -1)
////									obj.put(item.getName(),  new JSONArray());
////								}else {
////									arr = (JSONArray)obj.get(item.getName());
////									if (arr == null){
////										arr = new JSONArray();
////									}
////									current = new JSONObject();
////									arr.add(current);
////									obj.put(item.getName(), arr);
////									
////								}
////							}else{  //GROUP
////	
////								current = new JSONObject();
////								obj.put(item.getName(), current);
////							}
////							
////						} else {
////							logger.error("JSONArray 타입의 부모를 지원하지 않음");
////							throw new Exception("JSONArray 타입의 부모를 지원하지 않음");
////						}
////						
////						// 그룹의 Child가 있는 경우에만
////						if(item.getChildCount() > 0 && item.getIndex() != -1){ //배열에서 group 명만 존재하도록 수정 (index != -1)
////							stack.push(current);
////						}
////						break;
////					case NODE_MESSAGE:
////						//로직이 호출 안됨
////						if( parent instanceof JSONObject ) {
////							obj = (JSONObject)parent;
////							current = new JSONObject();
////							obj.put(item.getName(), current);
////							stack.push(current);
////							
////						}else {
////							logger.error("JSONArray 타입의 부모를 지원하지 않음");
////							throw new Exception("JSONArray 타입의 부모를 지원하지 않음");
////						}
////						break;
////		        
////		        }  // end switch
////			} // end for
////		}catch(Exception e) {
////			logger.error(item.getItemPath()+" "+e.getMessage(),e);
////			throw new Exception(e);
////		}
//		return root; 
//	}
//
//}
