package com.eactive.eai.transformer.message;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Stack;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.transformer.SystemKeys;
import com.eactive.eai.transformer.layout.Converter;
import com.eactive.eai.transformer.layout.InvalidNodeException;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.Types;
import com.eactive.eai.transformer.util.Constants;
import com.eactive.eai.transformer.util.Logger;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JSONMessage extends Message {
	private static final long serialVersionUID = -1436691531430920703L;

	protected static Logger logger = Logger.getLogger("transformer");

	public static final String MESSAGE_NAME = "JSONMessage";
    public static final String NAME = "JSON";
//    public static String encode  = "euc-kr";
    
    protected JsonNode data;
    protected ObjectMapper mapper =  null;
    protected JsonFactory factory = null;
    protected boolean bStaled = false;

    public JSONMessage() {
        super();
        mapper = new ObjectMapper();
        // if necessary, add proper options -> use system property config ?
		mapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
		mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
		mapper.setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));
		
		factory = mapper.getFactory();
    }

	@Override
	public void createObject() {
		data = mapper.createObjectNode();
	}
	
	@Override
	protected void composeData(Item item, Object value) {
        if (item.getIndex() < 0)
            return;

        if (!bStaled) {
            bStaled = true;
        }
	}

    protected JsonNode getJSONObject() {
        return  data;
    }
    
	@Override
	protected void doSetData(Object data) {
		doSetData(data, false);
	}

	protected void doSetData(Object data, boolean refCountLimit) {
		JsonParser parser = null; 
		String jsonString = null;
		try {
			if (data instanceof String) {
				jsonString = (String) data;
				parser = factory.createParser(jsonString);
				this.data = mapper.readTree(parser);				
			} 
//			else if (data instanceof byte[]) {				
//				jsonString = new String((byte[]) data,encode);
//				parser = factory.createParser(jsonString);
//				this.data = mapper.readTree(parser);				
//	        } 
			else if (data instanceof JsonNode) {
	        	this.data = (JsonNode) data;
	        } else {
	            if (data == null) {
	                throw new InvalidDataTypeException("Not able to generate JSON messages with data. Input value is null.", data);
	            
	            } else {
	                throw new InvalidDataTypeException("Not able to generate JSON messages with data. data type = " + data.getClass().getName(), data);
	            }
	        }
				        
	        if (this.data == null) {
	            logger.error("Parsed data is null");
	            return;
	        }
								
			//ObjectNode node = (ObjectNode) this.data.get(getName());
	        /*
	        if(node == null) {
				// if  layoutname not appended
				setValue(this.data, getName());				
			}
			else {
				setValue(node, getName());				
			}
	        */
	        
	        ObjectNode node = null;
	        
	     // 변경된 부분: NullNode 검사 추가
	        if (this.data.has(getName()) && !this.data.get(getName()).isNull()) {
	            JsonNode nameNode = this.data.get(getName());
	            if (nameNode.isObject()) {
	                node = (ObjectNode) nameNode;
	                
	                // 배열 데이터 처리 개선
	                processArrayNodes(this.data);
	                
	                // 값 설정
	                setValue(node, getName());
	            } else {
	                logger.warn("Node with name '" + getName() + "' is not an object, skipping setValue operation");
	            }
	        } else {
	            // layoutname이 추가되지 않은 경우
	            setValue(this.data, getName());
	        }        
	        			
	    } catch (Exception e) {
	        throw new MessageSetDataException(e.getMessage(), this, data, e);
	    }
	}
	
    public void setValue(JsonNode node, String itempPath) throws InvalidAccessException {   	
    	
    	try {
//    		this.value = Converter.convert(value, getDataTypeId());
    		/**
        	 * occRef 설정을 위해
        	 */
    		
            HashMap validationTargets = new HashMap();            
            
            doSetValue(node, validationTargets, itempPath);

            // validation
            if(SystemKeys.isValidationEnabled()) {
	            Iterator iter = validationTargets.keySet().iterator();
	            while(iter.hasNext()) {
	                String itemPath = (String) iter.next();
	                Item item = (Item) validationTargets.get(itemPath);
	                int occCount = getInt(itemPath);
	                if (occCount < item.getOccMin() || 
	                   (!"*".equals(item.getOccType()) && !"+".equals(item.getOccType()) && occCount > item.getOccMax())) 
	                    throw new InvalidAccessException("Number of iterations out of [OccMin ~ OccMax] , " + item.getName(), item.getItemPath());
	                if (occCount != item.arraySize())
	                    throw new InvalidAccessException("The number of repetitions is different from the number of repetitions of the actual data. , " + item.getName(), item.getItemPath());            
	            }
            } // validation
    	} catch(InvalidAccessException e) {
    		throw e;
    	} catch(Exception e) {
    		throw new InvalidAccessException("setValue error", getItemPath(), null, e);
    	}
    }

    protected void doSetValue(JsonNode node, HashMap validationTargets, String parentPath) {    	
        Item item = null;
                
    	if( node.isObject()) {
    		Iterator<String> fieldNames = node.fieldNames();    		
    		if(StringUtils.isNotEmpty(parentPath)) {
				item = getOrCreateItem(denomalizeXPath(parentPath));				
				if(SystemKeys.isValidationEnabled() && StringUtils.isNotEmpty(item.getOccRef())) {
                    validationTargets.put(item.getParent().getItemPath() + Types.FIELD_SEPARATOR + item.getOccRef(), item);
                }
            }
    		while(fieldNames.hasNext()) {
    			String fieldName = fieldNames.next();
    			    			
    			JsonNode fieldValue = node.get(fieldName);
	            try {
	            	String path = null;
	            	if(StringUtils.isEmpty(parentPath)) {
	            		path = fieldName;
	            	}
	            	else {
	            		path = parentPath + Types.FIELD_SEPARATOR + fieldName;
	            	}
	            	doSetValue(fieldValue, validationTargets, path);
    			} catch(InvalidNodeException e) {
//    				throw new InvalidAccessException(e.getMessage(),  itemPath, this,e);
    				continue;
    			}
    		}
    	}		
    	else if( node.isArray() ) {
    		ArrayNode arrayNode = (ArrayNode) node;
    		
    		// 배열이 문자열 값만 포함하는지 확인
            boolean isSimpleArray = true;
            for (int i = 0; i < arrayNode.size(); i++) {
                if (!arrayNode.get(i).isValueNode()) {
                    isSimpleArray = false;
                    break;
                }
            }
                        
            if (isSimpleArray) {
                // 문자열 배열은 직접 값 설정
                try {                	
                    setString(parentPath, arrayNode.toString());
                } catch (Exception e) {
                    logger.error("Error setting simple array: " + parentPath, e);
                    // 개별 요소 설정
                    for (int i = 0; i < arrayNode.size(); i++) {
                        try {
                            String itemPath = parentPath + "[" + i + "]";      
                            setString(itemPath, arrayNode.get(i).asText());
                        } catch (Exception ex) {
                            logger.error("Error setting array item: " + parentPath + "[" + i + "]", ex);
                        }
                    }
                }
            } else {
                // 복잡한 배열 구조 처리
                for (int i = 0; i < arrayNode.size(); i++) {
                    JsonNode arrayItem = arrayNode.get(i);
                    
                    if (StringUtils.isNotEmpty(parentPath)) {
                        try {
                            item = getOrCreateItem(denomalizeXPath(parentPath + "[" + i + "]"));                            
                        } catch (InvalidNodeException ie) {
                            continue;
                        }
                    }
                    doSetValue(arrayItem, validationTargets, parentPath + "[" + i + "]");
                }
            }
    	}
    	else {    		
    		String itemPath = parentPath;
    		item = getOrCreateItem(denomalizeXPath(itemPath));
    		String value = node.asText();

			if(node == null || node.isNull()) {
				setObject(itemPath, null);  // 실제 null 값 설정
			} else if(value == null || value.length() == 0) {
    			setObject( itemPath,  value );
        	} else {
	    		int itemType = item.getDataTypeId();
	    		try {
		        	switch(itemType) {
		        	case Types.TYPE_INT :
		        	case Types.TYPE_SHORT :
		        	    setInt( itemPath, new Integer(value) );
		        		break;
		        	case Types.TYPE_LONG :
		        	    setLong( itemPath, new Long(value) );
		        		break;
		        	case Types.TYPE_BIGDECIMAL :
		        		if (SystemKeys.isValidationEnabled() && !Converter.isValid(value, item.getLength(), item.getDecimalPointLength())) {
		        			throw new InvalidAccessException(
		        				String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d",
		        					value, item.getLength(), item.getDecimalPointLength()),
		        				itemPath);
		        		}
		        		setBigDecimal( itemPath, new BigDecimal(value) );
		            	break;
			        case Types.TYPE_DOUBLE :
			        	setDouble( itemPath, new Double(value) );
		            	break;
		            case Types.TYPE_FLOAT :
		            	setFloat( itemPath, new Float(value) );
		            	break;
		            case Types.TYPE_BOOLEAN :
		            	setObject( itemPath,  new Boolean(value) );
		            	break;
		            case Types.TYPE_STRING :
		            	setString(itemPath,  value);
		            	break;
		            default :
		            	setString(itemPath,  value);
		            	break;
		        	}
	    		} catch (InvalidAccessException e) {
	    			throw e;
	    		} catch (Exception e) {
	    			throw new InvalidAccessException(
	    				String.format("Type mismatch: value='%s', field='%s', dataType=%s",
	    					value, itemPath, Types.getType(itemType)),
	    				itemPath, null, e);
	    		}
    		}
    	}
    }
    
	protected ObjectNode getJSONData() throws Exception {
		return getJSONData(false);
	}

	protected ObjectNode getJSONData(boolean isMask) throws Exception {
		
		boolean withLayoutName = false;
		
		ObjectNode root = mapper.createObjectNode();
		
		ObjectNode messageName = mapper.createObjectNode();
		root.set(getName(), messageName);
        
		Stack <ObjectNode> stack = new Stack<ObjectNode>();
		ObjectNode parent = messageName;
		ObjectNode current = null;
		
		ObjectNode obj = null;
		ArrayNode arr = null;
		
		stack.push(messageName);
		int prevDepth = 1;
		
		try {
		for (Iterator iter = iterator(); iter.hasNext();) {
			Item item = (Item) iter.next();
			/**
			 * index == -1 인 경우는 무시한다
			 */
			if (item == null || item.getIndex() == -1) {
				continue;
			}
			
			/**
			 * depth 가 낮아질 때(tree를 빠져 나올 때), parent를 재설정한다. 
			 */
			if (item.getDepth() < prevDepth) {
				for(int j=0; j<(prevDepth - item.getDepth()); j++) stack.pop();
			}	

			/**
	         * 이전 depth를 저장해 둔다.
	         */
			prevDepth = item.getDepth();	      
			
			parent = (ObjectNode)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:
					String prefix = item.getNodeTypeId() == NODE_ATTR ? "-":""; //무엇에 쓰이는 물건인고.
					if( parent instanceof ObjectNode ) {
						obj = (ObjectNode)parent;
						
						String val = getStringValue(item.getValue(),item);												
						int itemType = item.getDataTypeId();						
						
						if (isMask && "Y".equals(item.getMask()) && (Types.TYPE_STRING == itemType )){
							val = maskString2(val, item.getMaskLength(), item.getMaskOffset());
							item.setValue(val);
						}
//						Object value = toJsonObjectType(item.getDataTypeId(), val);
						String value = val;
						if( item.getOccMax() > 1 || item.getOccMax() == -1  ) {  // FIELD ARRAY FORMAT "name":["value1", "value2"]
							arr = (ArrayNode)obj.get(item.getName());
							if (arr == null){
								arr = mapper.createArrayNode();
								setJsonArrayValue(arr, item);
								obj.set(prefix+item.getName(), arr);
							}else{								
								arr.add(value);
							}
							
						} else { //FIELD
							obj = (ObjectNode)parent;
							setJsonNodeValue(obj, prefix+item.getName(), item);
						}
					} else {
						logger.error("not support parent type JSONArray");
						throw new Exception("not support parent type JSONArray");
					}
					break;
				case NODE_GROUP:
					if( parent instanceof ObjectNode ) {
						obj = (ObjectNode)parent;
						if( item.getOccMax() > 1 || item.getOccMax() == -1  ) {  // GRID
							arr = (ArrayNode)obj.get(item.getName());
							if (arr == null){
								arr = mapper.createArrayNode();
							}
							current = mapper.createObjectNode();
							arr.add(current);
							obj.set(item.getName(), arr);
						}else{  //GROUP
							current = mapper.createObjectNode();
							obj.set(item.getName(), current);
						}
						
					} else {
						logger.error("not support parent type JSONArray");
						throw new Exception("not support parent type JSONArray");
					}
					if (item.getChildCount() > 0){						
						stack.push(current);
					}
					break;
	        }  // end switch
		} // end for
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
			throw new Exception(e);
		}
		
		if(withLayoutName) {
			return root;
		}
		else {
			JsonNode node = root.get(this.layoutName);
		 	if(node == null) return root;
		 	else return (ObjectNode)node;
		}
		
	}
	
	private void setJsonNodeValue(ObjectNode node, String fieldName, Item item) {
		int itemType = item.getDataTypeId();
		Object value = item.getValue();
				
		if(value == null) {
			node.putNull(fieldName);
			return;
		}
		
		if(value instanceof JsonNode) {
			node.set(fieldName, (JsonNode) value);
			return;
		}
		
		 // New code to check if string is JSON array
	    if (itemType == Types.TYPE_STRING && value instanceof String) {
	        String strValue = (String) value;
	        if ((strValue.startsWith("[") && strValue.endsWith("]")) || 
	            (strValue.startsWith("{") && strValue.endsWith("}"))) {
	            try {
	                // Try to parse as JSON
	                JsonNode jsonNode = mapper.readTree(strValue);
	                node.set(fieldName, jsonNode);
	                return;
	            } catch (Exception e) {
	                // Not valid JSON, continue with normal processing
	                logger.debug("Failed to parse as JSON, using as string: " + e.getMessage());
	            }
	        }
	    }
		
		 if (!(value instanceof byte[])) {
		        logger.info("value : " + value.toString());
		 }
				
    	switch(itemType) {
    	case Types.TYPE_INT :
    	case Types.TYPE_SHORT :
    	    node.put(fieldName, (int) value);
    		break;
    	case Types.TYPE_LONG :
    		node.put(fieldName, (long) value);
    		break;
    	case Types.TYPE_BIGDECIMAL :
    		BigDecimal bd = (BigDecimal)value;
    		node.put(fieldName, bd);
        	break;
        case Types.TYPE_DOUBLE :
        	node.put(fieldName, (double) value);
        	break;
        case Types.TYPE_FLOAT :
        	node.put(fieldName, (float) value);
        	break;
        case Types.TYPE_BOOLEAN :	            	
        	node.put(fieldName, (boolean) value);
        	break;
        case Types.TYPE_STRING :
        	
        	node.put(fieldName, (String) value);
        	if (value instanceof JsonNode) {
        		logger.info("value : " + (String) value );
        	} 
        	  
        	break;	
        default :
        	node.put(fieldName, (String) value);
    	}
	}
	
	private void setJsonArrayValue(ArrayNode arrayNode, Item item) {
		int itemType = item.getDataTypeId();
		Object value = item.getValue();
		if(value == null) {
			return;
		}
    	switch(itemType) {
    	case Types.TYPE_INT :
    	case Types.TYPE_SHORT :
    		arrayNode.add( (int) value);
    		break;
    	case Types.TYPE_LONG :
    		arrayNode.add( (long) value);
    		break;
    	case Types.TYPE_BIGDECIMAL :
    		arrayNode.add( (float) value);
        	break;
        case Types.TYPE_DOUBLE :
        	arrayNode.add( (double) value);
        	break;
        case Types.TYPE_FLOAT :
        	arrayNode.add( (float) value);
        	break;
        case Types.TYPE_BOOLEAN :	            	
        	arrayNode.add( (boolean) value);
        	break;
        case Types.TYPE_STRING :
        	arrayNode.add( (String) value);
        	break;	
        default :
        	arrayNode.add( (String) value);
    	}
	}

	protected String getStringValue(Object value, Item item) throws Exception{
		if (value == null) return null;
		String val="";
        if (value instanceof String){
    		String data = (String)value;

    		if (item.getDataTypeId() == Types.TYPE_BIGDECIMAL){
    			val = getFormat(data,item.getLength(),item.getDecimalPointLength());
    		}else{
    			val = data;
    		}
    	} else if (value instanceof byte[]){
    		String data = new String((byte[])value);
    		if (item.getDataTypeId() == Types.TYPE_BIGDECIMAL){
    			val = getFormat(data,item.getLength(),item.getDecimalPointLength());
    		}else{
    			val = data;
    		}
    	} else if ( value instanceof BigDecimal) {
    		String data = ((BigDecimal) value).toPlainString();
    		if (item.getDataTypeId() == Types.TYPE_BIGDECIMAL){
    			val = getFormat(data,item.getLength(),item.getDecimalPointLength());
    		}else{
    			val = data;
    		}
    	} else if ( value instanceof Integer) {
    		String data = String.valueOf(value);
    		if (item.getDataTypeId() == Types.TYPE_BIGDECIMAL){
    			val = getFormat(data,item.getLength(),item.getDecimalPointLength());
    		}else{
    			val = data;
    		}
    	} else if ( value instanceof Boolean) {
    		String data = String.valueOf(value);
    		val = data;
    	}
		return val;
	}
	@Override
	public Object getData() {
	
		if (bStaled) {
            try {
                this.data = getJSONData();
            } catch(Exception e) {
                throw new InvalidDataTypeException(e.getMessage(),"JSONMessage.getData() method", e);   
            }
            bStaled = false;
        }
		return toJsonString();
	}
	
	public String toJsonString() {
		return toJsonString(false);
	}
	
	public String toJsonString(boolean isPretty) {
		if(this.data == null) {
			return null;
		}
	 	if(this.data == null) return null;
	 	
	 	if(isPretty) return data.toPrettyString();
	 	else return data.toString();
	}

//    protected String denomalizeXPath(String xpath) {
//        String itemPath = xpath; //xpath.substring(1).replaceAll("/", "\\.");
//        //String itemPath = xpath.substring(1).replaceAll("/", "\\"+Types.FIELD_SEPARATOR);
//        if (!itemPath.endsWith("]")) {
//            itemPath = itemPath + "[0]";
//        }
//        itemPath = itemPath.replaceAll("([ㄱ-ㅎ가-힣a-zA-Z0-9_]+)(\\"+Types.FIELD_SEPARATOR+")", "$1[0]$2");
//        itemPath = itemPath.replaceFirst("\\[[0-9]+\\]", "");
//        
//      System.out.println(String.format("%s : %s", xpath, itemPath));
//        return itemPath;
//    }

	protected String denomalizeXPath(String xpath) {
        StringBuffer sb = new StringBuffer();
        String[] parts = xpath.split("\\"+ Types.FIELD_SEPARATOR);
        for(int i=0; i<parts.length; i++) {
        	if(i == 0) {
        		sb.append(parts[i]);
        	}
        	else {
        		if(parts[i].charAt(parts[i].length()-1) ==']') {
        			sb.append(parts[i]);
        		}
        		else {
        			sb.append(parts[i]).append("[0]");
        		}
        	}
        	if(i < parts.length-1) {
        		sb.append(Types.FIELD_SEPARATOR);
        	}
        }
        String itemPath = sb.toString();
        return itemPath;
    }
    
	@Override
	public String toLogString() {
		try{
			JsonNode json = getJSONData(true);
			return json.toString();
		}catch(Exception e){
			logger.error("[U] " + e.getMessage(),e);
			return null;
		}
	}
	
	private String getFormat(String value,int length,int pointLength) throws Exception {
		boolean validation = SystemKeys.isValidationEnabled();
		return getFormat(value, length,  pointLength, validation) ;
	}
	
	private String getFormat(String value, int length, int pointLength, boolean isValidation) throws Exception{
		if(isValidation) {
			if (!Converter.isValid(value,length,pointLength)){
				throw new Exception(String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d"
						, value,length,pointLength)
						);
			}
		
			boolean isMinus=false;
			String pattern = "";
			//음수/양수 check
			if (value.indexOf("-")>=0){
				isMinus = true;
			}
			String data = value.replaceAll(" ", "").replaceAll("-", "");
			if (pointLength> 0 ){//소수부가 있을 경우 
				for(int i=isMinus?1:0;i<length-pointLength-1;i++){
					pattern = pattern + "#";
				}
				pattern =pattern+".";
				for(int i=0;i<pointLength;i++){
					pattern = pattern + "0";
				}
			}else{//소수부가 없을경우
				for(int i=isMinus?1:0;i<length-pointLength;i++){
					pattern = pattern + "#";
				}
			}
			if (isMinus) {
				pattern="-"+pattern;
			}
			DecimalFormat format = new DecimalFormat(pattern);
	//		double num = Double.parseDouble(data);
			BigDecimal num = new BigDecimal(data);
			return format.format(num);
		}
		else {
			BigDecimal num = new BigDecimal(value);
			return num.toPlainString();
		}
	}
	
//	private Object toJsonObjectType(int itemType, String value) {
//    	Object jsonValueObject = null;
//    	
//    	if(value == null ) {
//    		return null;
//    	}
//    	
//    	switch(itemType) {
//    	case Types.TYPE_INT :
//    	case Types.TYPE_LONG :
//    	case Types.TYPE_SHORT :
//    	    jsonValueObject = new Integer(value);
//    		break;
//    	case Types.TYPE_DOUBLE :
//        case Types.TYPE_FLOAT :
//        	jsonValueObject = new Float(value);
//        	break;
//        case Types.TYPE_BOOLEAN :
//        	jsonValueObject = new Boolean(value);
//        	break;
//        case Types.TYPE_STRING :
//        	jsonValueObject = value;
//        	break;	
//        default :
//        	jsonValueObject = value;
//    	}
//    	return jsonValueObject;
//    }
	
	private String getHeader() {
    	return getName() + " (" + MESSAGE_NAME + ")";
    }
		    
    // 배열 처리 메소드
    private void processArrayNodes(JsonNode rootNode) {
        Iterator<String> fieldNames = rootNode.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            JsonNode node = rootNode.get(fieldName);
            
            // data_part와 같은 객체 노드 처리
            if (node.isObject()) {
                processArrayNodes(node);
            } 
            // 배열 노드 처리
            else if (node.isArray()) {
                ArrayNode arrayNode = (ArrayNode) node;
                
                // 배열 노드 처리
                if (arrayNode.size() > 0) {
                    // 배열 데이터 설정
                    try {
                    	
                    	if(this.data instanceof  ObjectNode) {
                    		 ObjectNode objNode = (ObjectNode) this.data;
                             objNode.set(fieldName, arrayNode);                    		
                    	} else if (rootNode instanceof ObjectNode) {
                    		((ObjectNode) rootNode).set(fieldName, arrayNode);
                    	}
                    	
                    	for(int i=0; i < arrayNode.size(); i++) {
                    		JsonNode itemNode = arrayNode.get(i);
                    		
                    		String itemPath = fieldName + "[" + i + "]";
                    		
                    		if(itemNode.isObject()) {
                    			processArrayNodes(itemNode);
                    		}                    		
                    	}
                    	
                    } catch (Exception e) {
                        logger.error("Error setting array data for field: " + fieldName, e);
                        // 배열 요소를 개별적으로 처리
                        for (int i = 0; i < arrayNode.size(); i++) {
                            try {
                                String itemPath = fieldName + "[" + i + "]";
                                JsonNode itemNode = arrayNode.get(i);
                                if (itemNode.isTextual()) {
                                    setString(itemPath, itemNode.asText());
                                } else {
                                    setString(itemPath, itemNode.toString());
                                }
                            } catch (Exception ex) {
                                logger.error("Error setting array item [" + i + "] for field: " + fieldName, ex);
                            }
                        }
                    }
                }
            }
        }
    }
    		
	public String toString(){
		// if staled -> reorganize data
		String jsonString = null;
		try {
    		jsonString = (String)getData();
		} catch (Exception e) {
        	logger.error("[JSONMessage] " + e.getMessage(), e);
		}

		StringBuffer sb = new StringBuffer();
		sb.append(getHeader());
		sb.append(super.toString());
		//sb.append("\n" + Constants.TAB + " +--------------------------------------------------------------------------------------------------+");
		if (this.data != null) {
			sb.append("\n" + Constants.TAB + " | data = \n" + jsonString + "");
		}
		sb.append("\n" + Constants.TAB + " +--------------------------------------------------------------------------------------------------+");
		return sb.toString();
	}
}
