package com.eactive.eai.batch.telegram;

import java.util.HashMap;

import com.eactive.eai.batch.common.StringUtil;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.dao.DAOFactory;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleListener;
import com.eactive.eai.common.lifecycle.LifecycleSupport;
import com.eactive.eai.common.util.Logger;

/**
* 1. 기능 : EAI서버 Rule 정보를 DB로 부터 로딩해 메모리에 관리하는 Manager 클래스
* 2. 처리 개요 : DB Rule 정보에 저장된 필드 추출 Rule 정보를 메모리에 로딩 관리한다.
* 3. 주의사항
*
* @author  :
* @version : v 1.0.0
* @see : 관련 기능을 참조
* @since   :
* 
*/
public class TelegramManager implements Lifecycle
{

	//디버그용 로그유틸
	private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	/**
     * TelegramManager Single Instance
     */
    private static TelegramManager instance = new TelegramManager();

    /**
     * LifeccyleSupport object
     */
    private LifecycleSupport lifecycle = new LifecycleSupport(this);

    /**
     * 기동 여부
     */
    private boolean started;

    /**
     * 전문 정보를 저장하는 collection
     */
    private HashMap<String, TelegramVO> telegrams;

    /**
    * 1. 기능 :  Default Constructor
    * 2. 처리 개요 : 전문(Telegram) 정보를 저장하기 위한 HashMap을 초기화한다.
    * 3. 주의사항
    *
    **/
    private TelegramManager() {
    	telegrams = new HashMap<String, TelegramVO>();

    }

    /**
    * 1. 기능 :  TelegramManager Singleton Object를 반환하는 getter method
    * 2. 처리 개요 : TelegramManager Singleton Object를 반환한다.
    * 3. 주의사항
    *
    * @return   TelegramManager Singleton object
    **/
    public static TelegramManager getInstance() {

        return instance;
    }


    /* ****************************************************************** */
    /*                  Web Agent 호출을 위한  메소드 정의                */
    /* ****************************************************************** */

    /**
     * 1.기능: 전문 Key에 해당하는 전문 객체를 삭제한다.
     */
    public boolean removeTelegram(String telegramKey)
    {
        TelegramVO telegramVO = telegrams.get(telegramKey);
        if(telegramVO != null)
            telegrams.remove(telegramKey);
        return true;
    }

    /**
     * 1.기능: 전문 Key에 해당하는 전문 객체를 다시 읽어온다.
     */
    public TelegramVO updateTelegram(String telegramKey)  throws Exception
    {
        // 먼저 해당 객체를 삭제한다.
		removeTelegram(telegramKey);	

        // 입력된 telegramKey에 해당하는 객체를 다시 읽어와서 추가한다.
        addTelegram(telegramKey);

        return this.getTelegramByKey(telegramKey);
    }

    /**
     * 1.기능: 전문 Key에 해당하는 전문 객체를 전체 HashMap에 추가한다.
     */
    private TelegramVO addTelegram(String telegramKey)  throws Exception
    {
        // 입력된 telegramKey에 해당하는 객체를 읽어와서 HashMap에 추가한다.
        TelegramDAO dao = (TelegramDAO)DAOFactory.newInstance().create(TelegramDAO.class);
        TelegramVO telegramVO = dao.getTelegram(telegramKey);
        telegrams.put(telegramVO.getTelegramKey(), telegramVO);

        return this.getTelegramByKey(telegramKey);
    }


    /* ****************************************************************** */
    /*                  TelegramManager 자체적인 메소드 정의              */
    /* ****************************************************************** */

    /**
     * 1. 기능 : 전문 Key에 의해서 해당 전문 객체를 반환한다.
     * 2. 처리 개요 :
     *    - HashMap(telegrams)의 Key는 전문코드와 동일하다.
     * 3. 주의사항
     *
     * @parm : 전문 key
     * @return   해당 전문 Key의 전체 필드를 담고 있는 TelegramVO 객체를 반환
     * @exception  throw TelegramNotFoundException
     **/
	public TelegramVO getTelegramByKey(String telegramKey) throws Exception
    {
        TelegramVO telegramVO = (TelegramVO)telegrams.get(telegramKey);
        if(telegramVO == null)
        {
			String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM007", new String[] {telegramKey});
			throw new Exception(errMsg);	//해당 전문(%1)이 존재하지 않습니다.
        }
        else
            return telegramVO;
    }

    /**
     * 1. 기능 : 입력된 전문코드에서 index에 해당하는 필드 객체(TelegramItemVO)를 반환한다.
     * 2. 처리 개요 :
     *     - 하나의 전문은 여러개의 TelegramItemVO의 모임으로 구성된 HashMap을 가진다.
     *     - 이 HashMap에서 입력된 index에 해당하는 객체를 반환하면 된다.
     * 3. 주의사항
     *
     * @parm : 전문 key, 해당 전문에서 추출하고자하는 필드의 index
     * @return   해당 전문에서 입력된 index에 해당하는 TelegramItemVO 객체를 반환
     * @exception  throw TelegramNotFoundException
     **/
	public TelegramItemVO getTelegramField(String telegramKey, int index)
    {
        TelegramVO telegramVO = (TelegramVO)telegrams.get(telegramKey);
        return telegramVO.getTelegramItem(index);
    }

    /**
     * 1. 기능 : 해당 전문의 필드순서에 맞게 각 필드의 길이만 반환한다.
     *           전문이 들어왔을 때에 Parsing하기 위한 용도이다.
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @parm : 전문 Key
     * @return   해당 전문의 길이 필드만으로 구성된 String 배열을 반환한다.
     * @exception  throw TelegramNotFoundException
     **/
	public String[] getTelegramFieldLengthsArray(String telegramKey)  throws Exception
    {
        // 입력된 전문코드에 해당하는 TelegramVO 객체를 찾는다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        return telegramVO.getTelegramFieldLengthsArray();
    }

    /**
     * 1. 기능 : 해당 전문의 필드순서에 맞게 각 필드의 타입만 반환한다.
     *           전문이 들어왔을 때에 Parsing하기 위한 용도이다.
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @parm : 전문 Key
     * @return   해당 전문의 타입 필드만으로 구성된 String 배열을 반환한다.
     * @exception
     **/
	public String[] getTelegramFieldTypesArray(String telegramKey)  throws Exception
    {
        // 입력된 전문코드에 해당하는 TelegramVO 객체를 찾는다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        return telegramVO.getTelegramFieldTypesArray();
    }

	public String[] getTelegramFieldNamesArray(String telegramKey)  throws Exception
    {
        // 입력된 전문코드에 해당하는 TelegramVO 객체를 찾는다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        return telegramVO.getTelegramFieldNamesArray();
    }

	public String[] getTelegramFieldIDsArray(String telegramKey)  throws Exception
    {
        // 입력된 전문코드에 해당하는 TelegramVO 객체를 찾는다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        return telegramVO.getTelegramFieldIDsArray();
    }

    /**
     * 1. 기능 : 해당 전문이 가변 길이부를 갖는 전문인지 판단한다.
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @parm : 전문 Key
     * @return   해당 전문이 가변부를 가지면 true, 아니면 false
     * @exception
     **/
	public boolean hasVariableField(String telegramKey)  throws Exception
    {
        // 입력된 전문코드에 해당하는 TelegramVO 객체를 찾는다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        return telegramVO.getVariableFieldCheckTag();
    }

    /**
     * 1. 기능 : 해당 전문의 전체 길이를 반환하는 메소드
     *           단, 가변부의 길이를 반환하지 않는다.
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @parm : 전문 Key
     * @return   해당 전문의 길이를 반환한다.
     * @exception
     **/
	public int getTelegramLength(String telegramKey)  throws Exception
    {
        return this.getTotalLength(this.getTelegramFieldLengthsArray(telegramKey));
    }


    /**
     * 1. 기능 : =============== 전문을 파싱하는 메인 메소드이다. ===============
     *           전문이 들어왔을 때에 해당 전문의 길이로 파싱한 후 String[]로 반환한다.
     *           파싱된 각각의 값에 대해서 해당 전문필드의 타입으로 형 검사를 실시한다.
     * 2. 처리 개요 :
     *     - 입력된 전문을 해당 전문코드 필드의 순서대로 파싱을 수행한 후
     *       다시 필드 타입에 맞는지 형 검사를 실시한다.
     *
     * 3. 주의사항
     * @parm : 전문 key,  입력된 전문(String)
     * @return   입력된 전문을 각 필드의 길이에 맞게 파싱한 후 String 배열로 반환한다.
     * @exception    throw TelegramNotFoundException(전문이 없는 경우),
     *               throw TelegramNotCompatable (전문의 길이가 틀리거나, 타입이 맞지 않는 경우)
     **/
    public String[] parseTelegram(String telegramKey, String telegram) throws Exception
    {
        // 이부분에 필드 타입하고 길이를 가져오는 배열을 설정하고 Validation을 부르게 하자.
		TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        String[] lengthsArray = telegramVO.getTelegramFieldLengthsArray();
        String[] typesArray = telegramVO.getTelegramFieldTypesArray();

        // 반환할 String[] 초기화
        String result[] = new String[lengthsArray.length];

        // 전문이 파싱 가능한지 미리 판단
        if(!this.checkTelegram(telegramKey, telegram)) {
			String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM009", new String[] {telegramKey});
			throw new Exception(errMsg);	//입력된 전문이 해당 전문(%1) 의 총 Size 와 일치하지 않습니다.
		}

        int beginIndex=0;
        for(int i=0; i< lengthsArray.length; i++)
        {
             String length_token = lengthsArray[i];
             String type_token = typesArray[i];

             // length별로 입력된 String을 잘라낸다.
             if(length_token.toUpperCase().equals("XX"))    // 가변길이 부분, xx는 반드시 제일 마지막으로 전달되어야 한다.
             {
                 result[i]=telegram.substring(beginIndex);
				 logger.debug("> 수신 전문필드 파싱... Index: ["+ i +"], Type: ["+ type_token +"], Length: ["+ length_token +"], Name: ["+ telegramVO.getTelegramItem(i+1).getFieldName() +"], Value: ["+ result[i] +"]");//길어서 print skip...");
             }
             else
             {
                 int delim = new Integer(length_token).intValue();
                 result[i]=telegram.substring(beginIndex, beginIndex+=delim);
				 logger.debug("> 수신 전문필드 파싱... Index: ["+ i +"], Type: ["+ type_token +"], Length: ["+ length_token +"], Name: ["+ telegramVO.getTelegramItem(i+1).getFieldName() +"], Value: ["+ result[i] +"]");
             }

             // Parsing된 결과가 정의된 Type에 맞는지 확인, 적합하지 않으면 에러 발생
             if (!this.checkType(type_token, result[i])) {
				String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM100", new String[] {Integer.toString(i), result[i], type_token});
				throw new Exception(errMsg);	//%1 번째 index 전문필드 값(%2)이 정의된 타입(%3)에 맞지 않는 부분이 있습니다.
			}
        }
        return result;
    }

	//==========================================================================================
	//이하 정영우 추가 (2006.02.20) - 응답수신 F/C에서 사용
	//
	//수신전문 문자열을 전문코드에 해당하는 필드 길이로 잘라서 리턴한다.
	public String[] parseTelegramNotCheck(String telegramKey, String telegram) throws Exception
	{
        // 이부분에 필드 타입하고 길이를 가져오는 배열을 설정하고 Validation을 부르게 하자.
		TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        String[] lengthsArray = telegramVO.getTelegramFieldLengthsArray();

        // 반환할 String[] 초기화
        String result[] = new String[lengthsArray.length];

        // 전문이 파싱 가능한지 미리 판단
        if(!this.checkTelegram(telegramKey, telegram)) {
			String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM009", new String[] {telegramKey});
			throw new Exception(errMsg);	//입력된 전문이 해당 전문(%1) 의 총 Size 와 일치하지 않습니다.
		}

        int beginIndex=0;
        for(int i=0; i< lengthsArray.length; i++)
        {
             String length_token = lengthsArray[i];

             // length별로 입력된 String을 잘라낸다.
             if(length_token.toUpperCase().equals("XX"))    // 가변길이 부분, xx는 반드시 제일 마지막으로 전달되어야 한다.
             {
                 result[i]=telegram.substring(beginIndex);
				 logger.debug("> 수신 전문필드 파싱... Index: ["+ i +"], Length: ["+ length_token +"], Name: ["+ telegramVO.getTelegramItem(i+1).getFieldName() +"], Value: ["+ result[i] +"]");//길어서 print skip...");
             }
             else
             {
                 int delim = new Integer(length_token).intValue();
                 result[i]=telegram.substring(beginIndex, beginIndex+=delim);
				 logger.debug("> 수신 전문필드 파싱... Index: ["+ i +"], Length: ["+ length_token +"], Name: ["+ telegramVO.getTelegramItem(i+1).getFieldName() +"], Value: ["+ result[i] +"]");
             }
        }
        return result;
	}

	//파싱된 수신전문을 전문코드에 해당하는 필드 타입이 맞는지 체크한다.
	public void checkParsedTelegram(String telegramKey, String[] telegramFiels) throws Exception
	{
        // 이부분에 필드 타입하고 길이를 가져오는 배열을 설정하고 Validation을 부르게 하자.
		TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
        String[] typesArray = telegramVO.getTelegramFieldTypesArray();

        for(int i=0; i< typesArray.length; i++)
        {
             String type_token = typesArray[i];

             // Parsing된 결과가 정의된 Type에 맞는지 확인, 적합하지 않으면 에러 발생
             if(!this.checkType(type_token, telegramFiels[i])) {
				String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM100", new String[] {Integer.toString(i), telegramFiels[i], type_token});
				throw new Exception(errMsg);	//%1 번째 index 전문필드 값(%2)이 정의된 타입(%3)에 맞지 않는 부분이 있습니다.
			}
        }
	}
	//==========================================================================================

    /**
     * 1. 기능 : parseTelegram() 메소드에서 호출되는 private 메소드
     *           전문의 필드의 type을 체크한다
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @parm : 전문필드 Type,  필드값(String)
     * @return   타입에 적합한 경우 true를 반환한다.
     * @exception
     **/
    private boolean checkType(String type, String str)
    {
        if(type.equals("AA")||type.equals("A"))       // 문자만 와야 됨
        {
            return StringUtil.isAlpha(str);
        }
        else if(type.equals("NN")||type.equals("N"))
        {
            return StringUtil.isNumeric(str);
        }
        else if(type.equals("AN"))
        {
            return true;
        }
        else     // 타입이 정의되지 않은 경우-이런 경우는 없어야 한다.
        {
            // 나중에 에러 처리 할 것
            return false;
        }
    }

    /**
     * 1. 기능 : parseTelegram() 메소드에서 호출되는 private 메소드
     *           전문의 전체 길이가 해당 전문정의에서 요구하는 길이와 같은지 확인한다.
     * 2. 처리 개요 :
     *     - 가변 필드가 있는 경우에는 가변 필드가 0인 경우를 고려하여 전체 길이가 정의된 길이보다 같거나 커야한다.
     *
     * 3. 주의사항
     *
     * @parm : 전문 Key,  전체전문(String)
     * @return   길이가 맞는 경우 true를 반환한다.
     * @exception
     **/
    private boolean checkTelegram(String telegramKey, String telegram) throws Exception
    {
        // Key에 해당하는 전문을 가져온다.
        TelegramVO telegramVO = this.getTelegramByKey(telegramKey);

        // 해당 전문이 가변부가 있는지 확인한다.
        boolean variableFieldCheckTag = telegramVO.getVariableFieldCheckTag();
        String[] telegramFiledLengths = telegramVO.getTelegramFieldLengthsArray();

        // 가변길이 전문이 아닌 경우 - 필드의 길이와 전문의 길이가 반드시 같아야 한다.
        if(!variableFieldCheckTag)
        {
            if(telegram.length() == this.getTotalLength(telegramFiledLengths))
            {
                return true;
            }
            else
            {
                logger.debug(" ************** 입력전문 길이 : " + telegram.length());
                logger.debug(" ************** 요구전문 길이 : " + this.getTotalLength(telegramFiledLengths));
                return false;
            }
        }
        else  // 가변길이 전문인 경우, 입력된 전문의 길이는 전문에 정의된 필드들의 길이의 합보다 크거나 같아야 된다.
        {
            if(telegram.length() >= this.getTotalLength(telegramFiledLengths))
            {
                return true;
            }
            else
            {
                logger.debug(" ************** 입력전문 길이(가변) : " + telegram.length());
                logger.debug(" ************** 요구전문 길이(가변) : " + this.getTotalLength(telegramFiledLengths));
                return false;
            }
        }

    }

    /**
     * 1. 기능 : parseTelegram() 메소드에서 호출되는 private 메소드
     *           String 배열을 받아들여 전체 값의 합을 반환한다.
     * 2. 처리 개요 :
     *     - 가변 필드가 있는 경우에는 제외하고 계산한다.
     *
     * 3. 주의사항
     *
     * @parm : 전문길이 배열
     * @return   배열의 각 항목의 값을 모두 더해서 반환한다.
     * @exception
     **/
    private int getTotalLength(String[] lengths)
    {
        int totalLength = 0;

        int i=0;
        while(i < lengths.length)
        {
            if (!lengths[i].trim().toUpperCase().equals("XX"))
               totalLength += new Integer(lengths[i]).intValue();
            i++;
        }
        return totalLength;
    }


    /**
     * 1. 기능 : =============== 전문을 생성하는 메인 메소드이다. ===============
     *           전문의 코드번호(Key)와 각 전문을 구성하는 값들을 String[] 형태로 받아들인다.
     *           String[]에서 하나씩
     * 2. 처리 개요 :
     *     - String[]에서 하나씩 값을 꺼내서 해당 필드의 Type, Length에 의해서 값을 보정한다.
     *     - 보정작업이란 입력된 값의 길이가 필드 정의보다 짧은 경우 대체 문자로 치환한다.
     *     - 대체 문자
     *        1) 숫자(NN, N): 오른쪽 정렬하고 나머지는 0으로 채운다.
     *        2) 문자(AA, A): 왼쪽 정렬하고 나머지는 공백으로 채운다.
     *        3) 문자,숫자(AN): 문자 기준으로 정렬한다.
     *
     * 3. 주의사항
     *
     * @parm : 전문 key,  전문필드의 값(String[])
     * @return   하나의 전문을 나타내는 String으로 반환
     * @exception    throw TelegramNotFoundException(전문 코드가 없는 경우),
     *               throw TelegramFieldNotCompatable (입력된 값이 정의된 Field의 길이보다 긴 경우)
     **/
    public String createTelegram(String telegramKey, String[] objs) throws Exception
    {
        String telegram = "";

		// Key에 해당하는 전문을 가져온다.
		TelegramVO telegramVO = this.getTelegramByKey(telegramKey);
		String[] telegramFieldLengthsArray = telegramVO.getTelegramFieldLengthsArray();
		String[] telegramFieldTypesArray = telegramVO.getTelegramFieldTypesArray();

		// 전문 생성이 가능한지 사전 체크
		if (objs.length != telegramFieldLengthsArray.length)
		{
			String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM011", new String[] {Integer.toString(telegramFieldLengthsArray.length), Integer.toString(objs.length)});
			throw new Exception(errMsg);	//전문 생성을 위한 요구 필드 개수가 적합하지 않습니다. (요구필드수: %1, 입력필드수: %2)
		}

		// 배열에서 값을 꺼내서 값을 모두 더한다.
		for(int i=0; i<objs.length; i++)
		{
			String fieldValue = this.createField(objs[i], telegramFieldTypesArray[i], telegramFieldLengthsArray[i], telegramVO.getTelegramItem(i+1).getFieldName());
			logger.debug("> 송신 전문필드 생성... Index: ["+ i +"], Type: ["+ telegramFieldTypesArray[i] +"], Length: ["+ telegramFieldLengthsArray[i] +"], Name: ["+ telegramVO.getTelegramItem(i+1).getFieldName() +"], Value: ["+ fieldValue +"]");
			telegram += fieldValue;
		}

        return telegram;
    }

    /**
     * 1. 기능 : createTelegram() 메소드에서 호출되는 private 메소드
     *           전달된 값을 전문 정의에 맞춰 정렬 및 Data 보정작업을 수행한다.
     *
     * 2. 처리 개요 :
     *     - 가변 필드인 경우에는 그대로 반환한다. (즉, 보정작업을 수행하지 않는다.)
     *     - 전문필드의 이름을 입력으로 받는 이유는 로깅시 어느 필드인지를 알기 위함이다.
     * 3. 주의사항
     *
     * @parm : 전문필드에 해당하는 값, 전문필드의 형, 전문필드의 길이, 전문필드의 이름
     * @return   입력된 값을 형에 따라 Data 보정작업을 수행한 String을 반환한다.
     * @exception  throw TelegramFieldNotCompatable (입력된 값이 정의된 Field의 길이보다 긴 경우)
     **/
    private String createField(String fieldContent, String fieldType, String fieldLength, String fieldName) throws Exception
    {
        // 입력값을 대문자로 변경한다. - 혹시나 소문자로 전달되는 것이 있을까봐...
        fieldType = fieldType.toUpperCase();
        fieldLength = fieldLength.toUpperCase();

        // 가변길이부인 경우 입력된 값을 그냥 반환한다.
        if(fieldLength.equals("XX"))
            return fieldContent;
        else
        {
            // 정의된 필드의 길이
            int fieldLen = new Integer(fieldLength).intValue();

            // 정의된 필드의 길이보다 큰 경우 예외 처리
            if (fieldContent.length() > fieldLen)
            {
				String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM012", new String[] {fieldName, fieldLength, Integer.toString(fieldContent.length()), fieldContent});
				throw new Exception(errMsg);	//전문필드 생성시 오류가 발생하였습니다. (전문필드명: %1, 정의된필드길이: %2, 입력된필드길이: %3, 입력된필드값: %4)
            }

            // 보정작업 구간
            if(fieldType.equals("AN")||fieldType.equals("AA")||fieldType.equals("A"))       // 문자형인 경우-왼쪽정렬 및 Blank처리
            {
                while(fieldContent.length() < fieldLen)
                {
                    fieldContent += " ";   // 공백 1칸 처리
                }
            }
            else if(fieldType.equals("NN")||fieldType.equals("N"))
            {
                while(fieldContent.length() < fieldLen)
                {
                    fieldContent = "0" + fieldContent;   // 0을 앞에 추가한다.
                }
            }
            else
            {
				String errMsg = ExceptionUtil.getErrorCode("BECEAIMTM013", new String[] {fieldType});
				throw new Exception(errMsg);	//정의되지 않은 전문필드 Type입니다. (%1)
            }
            return fieldContent;
        }
    }

    /**
     * 1. 기능 : 전체 전문을 반환하는 메소드
     * 2. 처리 개요 :
     *
     * 3. 주의사항
     *
     * @return 전체 전문의 정보
     * @exception
     **/
    public HashMap<String, TelegramVO> getAllTelegrams(){
        return this.telegrams;
    }


    /* ****************************************************************** */
    /*                  Lifecycle 인터페이스에 정의된 메소드              */
    /* ****************************************************************** */

    /**
    * 1. 기능 :  Lifecycle의 start 메서드로 TelegramManager를 초기화하는 메서드
    * 2. 처리 개요 : TelegramDAO를 이용해 추출 전문 정보 모두를 가져와 초기화한다.
    * 3. 주의사항
    *
    * @exception    LifecycleException  이미 시작되었거나,
    *               EAIServerDAO를 통해 Rule 정보를 가져온다.
    *               DAOExcepiton이 발생될 경우
    **/
    public void start() throws LifecycleException
    {
        if (started) throw new LifecycleException("BECEAIMTM014");	//TelegramMansger 가 이미 시작되었습니다.

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STARTING_EVENT, this);

        DAOFactory daoFactory = DAOFactory.newInstance();
        TelegramDAO dao = null;
        try {
            dao = (TelegramDAO)daoFactory.create(TelegramDAO.class);
            this.telegrams = dao.getAllTelegrams();

		} catch (DAOException e) {
			String errMsg = ExceptionUtil.getErrorCode(e, "BECEAIMTM015");
			throw new LifecycleException(errMsg);	//Lifecycle 에서 TelegramMansger 시작 시 (전문정보 로딩) 오류가 발생하였습니다.
        }

        started = true;

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
    }

    /**
    * 1. 기능 :  Lifecycle의 stop 메서드로 EAIServerManager를 종료하는 메서드
    * 2. 처리 개요 : 멤버에 캐싱항 EAIServer Rule 정보를 clear한다.
    * 3. 주의사항
    *
    * @exception    LifecycleException  이미 종료된 경우 발생
    **/
    public void stop() throws LifecycleException {
        // Validate and update our current component state
        if (!started) throw new LifecycleException("BECEAIMTM016");	//TelegramMansger 가 이미 종료되었습니다.

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STOPING_EVENT, this);


        started = false;
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
    }

    /**
    * 1. 기능 :  LifecycleListener를 등록하는 메서드
    * 2. 처리 개요 : LifecycleListener를 등록한다.
    * 3. 주의사항
    *
    * @param    listener    LifecycleEvent를 수신한 LifecycleListener
    **/
    public void addLifecycleListener(LifecycleListener listener)
    {
        lifecycle.addLifecycleListener(listener);
    }

    /**
    * 1. 기능 :  등록된 LifecycleListener 리스트를 반환하는 메서드
    * 2. 처리 개요 : 등록된 LifecycleListener 리스트를 반환하다.
    * 3. 주의사항
    *
    * @return   등록된 LifecycleListener 리스트
    **/
    public LifecycleListener[] findLifecycleListeners()
    {
        return lifecycle.findLifecycleListeners();
    }

    /**
    * 1. 기능 :  등록된 LifecycleListener를 삭제하는 메서드
    * 2. 처리 개요 : 파라미터의 LifecycleListener를 삭제한다.
    * 3. 주의사항
    *
    * @param    listener    삭제할 LifecycleListener
    **/
    public void removeLifecycleListener(LifecycleListener listener)
    {
        lifecycle.removeLifecycleListener(listener);
    }

    /**
    * 1. 기능 :  FlowRuleManager의 초기화 여부를 반환하는 getter 메서드
    * 2. 처리 개요 : FlowRuleManager의 초기화 여부를 반환한다.
    * 3. 주의사항
    *
    * @return   초기화 여부
    **/
    public boolean isStarted() {
        return this.started;
    }

}