package com.eactive.eai.common.util;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.common.EAITable;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.messagekey.MessageKeyFldVO;
import com.eactive.eai.common.messagekey.MessageKeyGroupVO;
import com.eactive.eai.common.messagekey.MessageKeyManager;
import com.eactive.eai.common.messagekey.MessageKeyVO;
import com.eactive.eai.transformer.message.ISO8583MessageFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.solab.iso8583.IsoMessage;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONValue;

import java.nio.charset.Charset;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class MessageKeyExtractor {

	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	private static final ObjectMapper objectMapper = new ObjectMapper();
    
	/**
     * Private 생성자
     * Instance를 생성하지 못함
     */
	private MessageKeyExtractor()
    {
    	
    }


    /** 
    * 1. 기능 : 메시지에서 특정필드의 값을 추출하는 메소드
    * 2. 처리 개요 : 
    *     - MessageKeyManager에서 Rule정보를 조회
    *     - 조회된 Rule을 기반으로 MessageUtil을 통해 기능 처리
    * 3. 주의사항 
    *	
	*	@param adapterName 업무 Adapter 이름
    *	@param message 변환대상 Object
    *   @return 결과 String 값(키값)
	*/ 
    public static String[] getMessageKeyValue(String fadapterGroupName, Object message) 
    throws Exception {
    	return getMessageKeyValue( fadapterGroupName, message, true , false);
    }
    
    
    private static String getAdapterCahrset(String adapterGroupName) {
    	AdapterManager adapterManager = AdapterManager.getInstance();
		AdapterGroupVO group = adapterManager.getAdapterGroupVO(adapterGroupName);
		return StringUtils.defaultIfBlank(group.getMessageEncode(), Charset.defaultCharset().name());		
    }
    
    /** 
    * 1. 기능 : 메시지에서 특정필드의 값을 추출하는 메소드
    * 2. 처리 개요 : 
    *     - MessageKeyManager에서 Rule정보를 조회
    *     - 조회된 Rule을 기반으로 MessageUtil을 통해 기능 처리
    * 3. 주의사항 
    *	
	*	@param adapterName 업무 Adapter 이름
    *	@param message 변환대상 Object
    *	@param isTrim trim 여부
    *	@param isDynamic true 이면 컬럼 Default값으로 비교 해서 값이 있으면 룰적용 값이 없으면 룰 제거
    *   @return 결과 String 값(키값)
	*/ 
    public static String[] getMessageKeyValue(String fadapterGroupName, Object message, boolean isTrim, boolean isDynamic) 
    	    throws Exception {
        
    	String[] keys = null;
    	String key = null;
        MessageKeyVO msgKey = null;
        
        String keyCode = fadapterGroupName + "I";
        try {
            MessageKeyManager manager = MessageKeyManager.getInstance();
            msgKey = manager.getMessageKey(keyCode);
//            String msgType = msgKey.getMsgTp();
            
            int groupSize = msgKey.getAlMsgGroups().size();
            
            keys = new String[groupSize];
            
            if(logger.isInfo()) {
            	logger.info("MessageKeyExtractor] CURRENT RULE =" + keyCode
            			+", GROUP SIZE [" + groupSize +"]");
            }
            
            String colType = msgKey.getMsgTp();
            byte[] bytesMessage = null;
            String stringMessage = null;
            Object json = null;
            
            IsoMessage parsedIsoMessage = null;
            
            // 처음에만 message conversion을 하고 재사용한다.(tuning)
        	if(groupSize > 0) {	            		
				if (EAITable.ASCII_TYPE.equals(colType) || EAITable.EBCDIC_TYPE.equals(colType)
//						|| EAITable.ISO85-83_TYPE.equals(colType) || EAITable.ISO85-83_H2H_TYPE.equals(colType)) {
						|| ISO8583MessageFactory.isISO8583Message(colType)) {
					if(message instanceof String) {
						String inboundCahrset = getAdapterCahrset(fadapterGroupName);
						bytesMessage = ((String) message).getBytes(inboundCahrset);
					}
					else {
						bytesMessage = (byte[]) message;
					}
				}
            	else if(EAITable.XML_TYPE.equals(colType)) {
            		stringMessage = (String)message;
            	}
            	else if(EAITable.JSON_TYPE.equals(colType)) {
                    json = JSONValue.parse((String)message);
            	}				
        	}
        	
            for(int g=0; g<groupSize; g++) {
            	key = "";
            	try {
	            	MessageKeyGroupVO groupVo = msgKey.getMessageKeyGroup(g);
	            	if(groupVo == null) {
	            		throw new Exception("MessageKeyGroupVO is NULL");
	            	}
	            	int fldSize = groupVo.getMessageKeyFldLength();
	            	
	            	if(logger.isInfo()) {
	                	logger.info("MessageKeyExtractor] CURRENT RULE [" + keyCode +"] group idx=" + g + 
	                			 ", CURRENT RULE FIELDS SIZE [" + fldSize +"]");
	                }
	            	//------------------------------------------------------
		            // 전문구조(ASCII, EBCDIC)가 아닌 경우에
	            	// BwkColStart, BwkColLength가 0 이 아닌 경우
	            	// 추출된 값에서 등록된 길이만큼 잘라낸다
	            	//------------------------------------------------------
	            	for(int i=0; i< fldSize; i++) {
		                MessageKeyFldVO keyFld = groupVo.getMessageKeyFld(i);
		                if(keyFld == null) continue;
		                
		                String tmp = ""; 
		                
		                if(EAITable.ASCII_TYPE.equals(colType)) {
		                    tmp = MessageUtil.getAscBytes(bytesMessage, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                }
		                else if(EAITable.EBCDIC_TYPE.equals(colType)) {
		                    tmp = MessageUtil.getEbcdicBytes(bytesMessage, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                }
//		                else if(EAITable.XML_TYPE.equals(colType) || EAITable.UXML_TYPE.equals(colType)) {
		                else if(EAITable.XML_TYPE.equals(colType)) {
		                    if(stringMessage != null) {
		                    	tmp = MessageUtil.getXmlFld(stringMessage, keyFld.getBwkColNm());
		                    	tmp = subString(tmp, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                    }
		                }
//		                else if(EAITable.JSON_TYPE.equals(colType) || EAITable.UJSON_TYPE.equals(colType)) {		                	
		                else if(EAITable.JSON_TYPE.equals(colType)) {		                	
		                	tmp = MessageUtil.getJSONValue(json, keyFld.getBwkColNm());
		                	tmp = subString(tmp, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                }
		                else if(EAITable.JAVAOBJECT_TYPE.equals(colType)) {
		                    tmp = (String)ObjectUtil.getProperty(message, keyFld.getBwkColNm());
		                    tmp = subString(tmp, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                }
//						else if (EAITable.ISO85-83_TYPE.equals(colType) || EAITable.ISO85-83_H2H_TYPE.equals(colType)) {
						else if (ISO8583MessageFactory.isISO8583Message(colType)) {
							// ISO8583은 Field를 숫자 형태의 인덱스로 구분한다. 
		                	int index = Integer.parseInt(keyFld.getBwkColNm());
		                	
		                	// Message Type은 파싱 항목에서 제외되기 때문에 0값으로 판단 BYTES 동일하고 처리한다.
		                	if (index == 0) {
		                		tmp = MessageUtil.getAscBytes((byte[])message, keyFld.getBwkColStart(), keyFld.getBwkColLength());
		                	} else {
		                		try{
		                			if(parsedIsoMessage == null){
		                				parsedIsoMessage = MessageUtil.parseIsoMessage((byte[]) message, colType);
		                			}
		                			tmp = MessageUtil.getISO8583Fld(parsedIsoMessage, index);
		                			tmp = subString(tmp, keyFld.getBwkColStart(), keyFld.getBwkColLength());

		                		} catch (Exception e) {
		                			logger.error("parse error", e);
		                		}
		                	}
						}
		                
		                if (isDynamic){
	  		                if(keyFld.getBwkColDef()!= null && keyFld.getBwkColDef().trim().length()>0){
	  		                	//정상값 위치에 값이 들어올경우 추출한 값과 다를 경우 룰을 제거 한다.
	  		                	if(tmp != null && ( !keyFld.getBwkColDef().equals(tmp.trim()) ) ){
	  		                		key ="";
	  		                		break;
	  		                	}
	  		                }
		                }
		                
		                // Key 값이 여러 필드로 구성될 경우 고려함
		                key = key + tmp;                
		        
		                if(key!= null && key.length() > 0) {
		                	if (isTrim){
		                		key = key.trim();
		                	}
		                }
		            } // Field Loop
            	}
            	catch(Exception ex) {
            		if(logger.isWarn()) {
	                	logger.info("MessageKeyExtractor] CURRENT RULE [" + keyCode +"] group idx=" + g +  
	                			 ", 추출 중 에러 -" + ex.getMessage());
	                }
            		key = "";
            	}
	            keys[g] = key;
            } // Group Loop  
        } catch(Exception e) {
        	String[] args = new String[1];
        	args[0] = fadapterGroupName;
            throw new Exception(ExceptionUtil.make(e, "RECEAICME001", args));
        }
        return keys;
    }
  

    public static String subString(String key, int start, int length) {
    	String returnKey = "";
    	
    	if(start ==0 && length == 0) return key;
    	
    	if(key == null || key.length() <(start+length)) {
    		return key;
    	}
    	else {
    		returnKey = key.substring(start, (start+length));
    	}
    	return returnKey;
    }

	/**
	 * EAI 메시지가 정상인지 오류인지 판별하는 기능
	 *
	 * <pre>
	 * 1. 처리 개요
	 *   - MessageKeyManager를 통해 메시지 분기 룰 조회
	 *   - 룰이 있는 경우:
	 *     1) 메시지 타입(XML/JSON 등)에 따라 지정된 필드값 추출
	 *     2) XPath/JSONPath 등 특수 패턴 처리
	 *     3) 추출된 값을 정의된 정상값과 비교 (@예약어 처리)
	 *   - 룰이 없는 경우 정상 메시지로 처리
	 *
	 * 2. 입력 파라미터 예시
	 *   - XML 메시지, XPath 사용:
	 *     adapterGroupName: "REST_OUT"
	 *     message: "<response><code>0000</code></response>"
	 *     분기조건: //response/code = @eq:0000
	 *
	 *   - JSON 메시지, JSONPath 사용:
	 *     adapterGroupName: "REST_OUT"
	 *     message: {"response":{"code":"0000"}}
	 *     분기조건: $.response.code = @contains:0000,2000
	 *
	 * 3. 주의사항
	 *   - message 파라미터는 XML의 경우 String 또는 byte[], JSON의 경우 String 타입 지원
	 *   - 필드값 비교시 대소문자 구분
	 *   - XPath/JSONPath 사용시 해당 표현식 문법 준수 필요
	 * </pre>
	 *
	 * @param fadapterGroupName Adapter 그룹명 (메시지 분기 룰 조회용 키)
	 * @param message 업무메시지 Object (XML, JSON 등)
	 * @return boolean 정상 메시지 여부 (정상:true / 오류:false)
	 * @throws Exception 메시지 처리 중 오류 발생시
	 */
	public static boolean isSuccessMessage(String fadapterGroupName, Object message)
			throws Exception {
		String key = "";

		String keyCode = fadapterGroupName + "O";

		try {
			MessageKeyManager manager = MessageKeyManager.getInstance();
			MessageKeyVO msgKey = manager.getMessageKey(keyCode);

			if(msgKey == null || "I".equals(msgKey.getExrTp())) {
				if (logger.isDebug()) logger.debug("MessageKeyExtractor] isSuccessMessage AdapterGroupName[" +
						keyCode +
						"] : 메시지 정상여부 확인 룰이 없는 경우 정상메시지변환룰을 사용함.");
				return true;
			}

			byte[] bytesMessage = null;
			String stringMessage = null;
			Object json = null;

			String colType = msgKey.getMsgTp();
			int groupSize = msgKey.getAlMsgGroups().size();

			// 처음에만 message conversion을 하고 재사용한다. (tuning)
			if(groupSize > 0) {
				if(EAITable.ASCII_TYPE.equals(colType) || EAITable.EBCDIC_TYPE.equals(colType) ) {
					bytesMessage = (byte[])message;
				}
				else if(EAITable.XML_TYPE.equals(colType) ) {
					if(message instanceof byte[]) {
						stringMessage = new String((byte[])message);
					}
					else if(message instanceof String) {
						stringMessage = (String)message;
					}
				}
				else if(EAITable.JSON_TYPE.equals(colType)) {
					json = JSONValue.parse((String)message);
				}
			}

			for(int g=0; g<groupSize; g++) {
				MessageKeyGroupVO groupVo = msgKey.getMessageKeyGroup(g);
				if(groupVo == null) {
					throw new Exception("MessageKeyGroupVO is null");
				}
				if(groupVo.getMessageKeyFldLength() > 0) {
					MessageKeyFldVO keyFld = groupVo.getMessageKeyFld(0);
					if(keyFld == null) {
						throw new Exception("MessageKeyFldVO is null");
					}

					// 메시지 타입별 필드값 추출
					if(EAITable.ASCII_TYPE.equals(colType)) {
						key = MessageUtil.getAscBytes(bytesMessage, keyFld.getBwkColStart(), keyFld.getBwkColLength());
					}
					else if(EAITable.EBCDIC_TYPE.equals(colType)) {
						key = MessageUtil.getEbcdicBytes(bytesMessage, keyFld.getBwkColStart(), keyFld.getBwkColLength());
					}
					else if(EAITable.XML_TYPE.equals(colType)) {
						if(stringMessage != null) {
							key = extractXmlValue(stringMessage, keyFld.getBwkColNm());
						}
					}
					else if(EAITable.JSON_TYPE.equals(colType)) {
						key = extractJsonValue(json, keyFld.getBwkColNm());
					}
					else if(EAITable.JAVAOBJECT_TYPE.equals(colType)) {
						key = (String)ObjectUtil.getProperty(message, keyFld.getBwkColNm());
					}

					if(key == null) key = "";
					if (logger.isDebug()) logger.debug("MessageKeyExtractor] isSuccessMessage KEY VALUE["+key+"], DEF["+keyFld.getBwkColDef()+"]");

					if(compareMessageValue(key, keyFld.getBwkColDef())) {
						return true;
					}
				}
			}
			return false;
		} catch(Exception e) {
			throw new Exception(ExceptionUtil.make(e,"RECEAICME002"));
		}
	}

	/**
	 * 메시지 값 비교를 수행하는 메소드
	 */
	private static boolean compareMessageValue(String actualValue, String expectedValue) {
		if(actualValue == null) actualValue = "";
		if(expectedValue == null) return false;

		// 예약어로 시작하는 경우
		if(expectedValue.startsWith("@")) {
			return compareWithReservedWord(actualValue, expectedValue);
		}

		// 일반 equals 비교
		return actualValue.equals(expectedValue);
	}

	/**
	 * 예약어를 포함한 값 비교 처리
	 * @param actualValue 실제 값
	 * @param definition 정의된 값 (예약어 포함 가능)
	 * @return 비교 결과
	 */
	public static boolean compareWithReservedWord(String actualValue, String definition) {
		if (actualValue == null) actualValue = "";
		if (definition == null) return false;

		// 예약어가 없는 경우 단순 equals 비교
		if (!definition.startsWith("@")) {
			return actualValue.equals(definition);
		}

		try {
			// 1. 기본 비교
			if (definition.startsWith("@eq:")) {
				return actualValue.equals(definition.substring(4));
			}
			if (definition.startsWith("@ne:")) {
				return !actualValue.equals(definition.substring(4));
			}
			if ("@null".equals(definition)) {
				return actualValue == null || actualValue.isEmpty();
			}
			if ("@!null".equals(definition)) {
				return actualValue != null && !actualValue.isEmpty();
			}

			// 2. 문자열 패턴
			if (definition.startsWith("@contains:")) {
				String[] values = definition.substring(10).split(",");
				for (String value : values) {
					if (actualValue.equals(value.trim())) {
						return true;
					}
				}
				return false;
			}
			if (definition.startsWith("@!contains:")) {
				String[] values = definition.substring(11).split(",");
				for (String value : values) {
					if (actualValue.equals(value.trim())) {
						return false;
					}
				}
				return true;
			}
			if (definition.startsWith("@starts:")) {
				return actualValue.startsWith(definition.substring(8));
			}
			if (definition.startsWith("@ends:")) {
				return actualValue.endsWith(definition.substring(6));
			}

			// 3. 숫자 비교
			if (definition.startsWith("@gt:") ||
					definition.startsWith("@lt:") ||
					definition.startsWith("@ge:") ||
					definition.startsWith("@le:")) {

				double actualNum;
				double defNum;

				try {
					actualNum = Double.parseDouble(actualValue);
					if (definition.startsWith("@gt:")) {
						defNum = Double.parseDouble(definition.substring(4));
						return actualNum > defNum;
					}
					if (definition.startsWith("@lt:")) {
						defNum = Double.parseDouble(definition.substring(4));
						return actualNum < defNum;
					}
					if (definition.startsWith("@ge:")) {
						defNum = Double.parseDouble(definition.substring(4));
						return actualNum >= defNum;
					}
					if (definition.startsWith("@le:")) {
						defNum = Double.parseDouble(definition.substring(4));
						return actualNum <= defNum;
					}
				} catch (NumberFormatException e) {
					logger.error("숫자 변환 실패: " + e.getMessage());
					return false;
				}
			}

			// 인식할 수 없는 예약어
			logger.warn("인식할 수 없는 예약어 패턴: " + definition);
			return false;

		} catch (Exception e) {
			logger.error("비교 처리 중 오류 발생: " + e.getMessage());
			return false;
		}
	}

	/**
	 * XML 메시지에서 필드값을 추출하는 메소드
	 */
	private static String extractXmlValue(String message, String fieldName) {
		if(fieldName == null) return "";

		// XPath 처리
		if(fieldName.startsWith("//")) {
			return MessageUtil.getXmlFldByXPath(message, fieldName);
		}

		// 일반 태그 처리
		return MessageUtil.getXmlFld(message, fieldName);
	}

	/**
	 * JSON 메시지에서 필드값을 추출하는 메소드
	 */
	private static String extractJsonValue(Object json, String fieldName) {
		if(fieldName == null) return "";

		// JSONPath 처리
		if(fieldName.startsWith("$.")) {
			return MessageUtil.getJSONValueByPath(json, fieldName);
		}

		// 일반 필드 처리
		return MessageUtil.getJSONValue(json, fieldName);
	}

    public static String[] getMessageKeyValueForRest(String fadapterGroupName, Object message, Properties prop, String type, boolean isTrim) throws Exception {

		String[] keys = null;
		String key = null;
		MessageKeyVO msgKey = null;
		String extUri = null;
		Properties header = null;
		String method = null;

		// 2009.12.30
		// 어댑터명과 기능구분코드 조합으로 변경
		String keyCode = fadapterGroupName + "I";
		try {
			MessageKeyManager manager = MessageKeyManager.getInstance();
			msgKey = manager.getMessageKey(keyCode);
			String msgType = msgKey.getMsgTp();
			
			if ("url".equals(type)){
				extUri = prop.getProperty("INBOUND_EXTURI");
				if (extUri == null ){
					throw new Exception("Can't find ext url");
				}
			} else if ("header".equals(type)){
				Object obj = prop.get("INBOUND_HEADER");
				if (obj == null){
					throw new Exception("Can't find header");
				}
				if (obj instanceof Properties){
					header = (Properties)obj;
				} else{
					throw new Exception("Can't find header");
				}
			} else if ("data".equals(type)){
				method = prop.getProperty("INBOUND_METHOD");
				if (method == null || "".equals(method.trim())){
					throw new Exception("Can't find method");
				}
			} else {
				throw new Exception ("not support type["+type+"]");
			}

			int groupSize = msgKey.getAlMsgGroups().size();

			keys = new String[groupSize];

			if (logger.isInfo()) {
				logger.info("MessageKeyExtractor] CURRENT RULE =" + keyCode + ", GROUP SIZE [" + groupSize + "]");
			}

			for (int g = 0; g < groupSize; g++) {
				key = "";
				try {
					MessageKeyGroupVO groupVo = msgKey.getMessageKeyGroup(g);
					int fldSize = groupVo.getMessageKeyFldLength();

					if (logger.isInfo()) {
						logger.info("MessageKeyExtractor] CURRENT RULE [" + keyCode + "] group idx=" + g
								+ ", CURRENT RULE FIELDS SIZE [" + fldSize + "]");
					}
					String colType = msgKey.getMsgTp();
					for (int i = 0; i < fldSize; i++) {
						MessageKeyFldVO keyFld = groupVo.getMessageKeyFld(i);
						String tmp = "";
						if ("url".equals(type)){
							tmp = getUrlValue(extUri, keyFld.getBwkClassNm(),keyFld.getBwkColNm());
						} else if ("header".equals(type)){
							tmp = header.getProperty(keyFld.getBwkColNm().toLowerCase(),"");
						} else if ("data".equals(type)){
	  		                if ("GET".equals(method) || "DELETE".equals(method)){
  	  		                    if(message instanceof byte[]) {
  	  		                    	tmp = getParameterValue(new String((byte[])message), keyFld.getBwkColNm());
  	  		                    }else if(message instanceof String) {
  	  		                    	tmp = getParameterValue((String)message, keyFld.getBwkColNm());
  	  		                    	
  	  		                    }
	  		                }else{
	  	  		                if(EAITable.JSON_TYPE.equals(colType)) {
	  	  		                    if(message instanceof byte[]) {
	  	  		                    	Object json = JSONValue.parse(new String((byte[])message));
	  	  		                        tmp = MessageUtil.getJSONValue(json, keyFld.getBwkColNm());

	  	  		                    }
	  	  		                    else if(message instanceof String) {
	  	  		                    	Object json = JSONValue.parse((String)message);
	  	  		                        tmp = MessageUtil.getJSONValue(json, keyFld.getBwkColNm());
	  	  		                    }
	  	  		                } // end JSON
	  	  		                else if(EAITable.XML_TYPE.equals(colType)) {
	  	  		                    if(message instanceof byte[]) {
	  	  		                        tmp = MessageUtil.getXmlFld(new String((byte[])message), keyFld.getBwkColNm());
	  	  		                    }
	  	  		                    else if(message instanceof String) {
	  	  		                        tmp = MessageUtil.getXmlFld((String)message, keyFld.getBwkColNm());
	  	  		                    }
	  	  		                    tmp = subString(tmp, keyFld.getBwkColStart(), keyFld.getBwkColLength());
	  	  		                }
	  		                }
						} else {
							throw new Exception ("not support type["+type+"]");
						}
						

						//if (keyFld.getBwkColDef().trim().length() > 0) {
						if (StringUtils.isNotBlank(keyFld.getBwkColDef())) {
							// 정상값 위치에 값이 들어올경우
							// 추출한 값과 다를 경우 룰을 제거 한다.
							if (!keyFld.getBwkColDef().equals(tmp.trim())) {
								key = "";
								break;
							}
						}

						// Key 값이 여러 필드로 구성될 경우 고려함
						if (tmp != null) {
							key = key + tmp;
						}

						if (key != null && key.length() > 0) {
							if (isTrim) {
								key = key.trim();
							}
						}

					} // Field Loop
				} catch (Exception ex) {
					if (logger.isWarn()) {
						logger.info("MessageKeyExtractor] CURRENT RULE [" + keyCode + "] group idx=" + g
								+ ", extract error -" + ex.getMessage());
					}
					key = "";
				}
				keys[g] = key;
			} // Group Loop
		} catch (Exception e) {
			String[] args = new String[1];
			args[0] = fadapterGroupName;
			throw new Exception(ExceptionUtil.make(e, "RECEAICME001", args));
		}
		return keys;
	}
    
    private static String getUrlValue(String uri, String pattern, String key) throws Exception{
		String[] uris = uri.split("/");
		String[] patterns = pattern.split("/");
		if (patterns.length != uris.length){
			return "";
		}
		for(int i=0; i<patterns.length;i++){
			Matcher matcher = Pattern.compile("\\$\\{([a-zA-Z0-9]*)\\}").matcher(patterns[i].trim());
			if (matcher.find()) { 
				if (key.equals(matcher.group(1).trim())){
					return uris[i];
				}
			}
			
		}
		return "";
	}
    
    private static String getParameterValue(String message, String key) throws Exception{
		String[] messages = message.split("&");
		String[] data = null;
		for(int i=0; i< messages.length;i++){
			data = messages[i].split("=",2);
			if (data.length == 2 && key.equals(data[0])){
				return data[1];
			}
		}
		return "";
	}
}