/* $Id: MailExecutionInfo.java,v 1.3 2007/11/13 06:58:25 nito Exp $
 *
 * Copyright (c)ARGO 21, Corporation. 2005.  All rights reserved.
 * 
 * This file is part of Nautica Workflow Core.
 * 
 *  Nautica Workflow Core is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2.1 of the License, or
 *  (at your option) any later version.
 * 
 *  Nautica Workflow Core is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Nautica Workflow Core Core; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
 */
package jp.co.argo21.nautica.workflow.ta;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import jp.co.argo21.nautica.workflow.wfmc.Attribute;

/**
 * メール送信ツールエージェント用のアプリケーション実行情報クラス
 * 
 * @author kiyoda(Argo 21, Corp.)
 * @version $Revision: 1.3 $
 * @since Nautica Workflow 1.0
 */
public class MailExecutionInfo extends AppExecutionInfo
{

	/** シリアルバージョンID */
	private static final long serialVersionUID = 1L;

	/* メール送信用実行情報のメッセージタイプ */
	private static final int MESSAGE_TYPE = 802;

	/* メール送信元 */
	private InternetAddress from = null;

	/* メール送信先(TO) */
	private InternetAddress[] to = null;

	/* メール送信先(CC) */
	private InternetAddress[] cc = null;

	/* メール送信先(BCC) */
	private InternetAddress[] bcc = null;

	/* メールタイトル */
	private String subject = null;

	/* メール本文 */
	private String body = null;

	/* 添付ファイル */
	private String[] attachmentFiles = null;

	/**
	 * 引数付コンストラクタ
	 * 
	 * @param appName
	 *            アプリケーション名
	 * @param toolAgent
	 *            ツールエージェントのクラス名
	 * @param wid
	 *            作業項目ID
	 * @param handler
	 *            ツールエージェントハンドラ（＝作業項目ID）
	 * @param attrList
	 *            引数リスト
	 */
	MailExecutionInfo(String appName, String toolAgent, String wid,
			int handler, Attribute[] attrList)
	{
		super(MESSAGE_TYPE);
		this.setAppName(appName);
		this.setToolAgent(toolAgent);
		this.setWid(wid);
		this.setHandler(handler);
		this.setAttributes(attrList);
	}

	MailExecutionInfo(HashMap<String, Serializable> map)
	{
		super(map);
	}

	/**
	 * 送信元のアドレスを取得する。
	 * 
	 * このメソッドを実行する前には、必ずparseメソッドを使用すること。 parseメソッドが使用される前は必ずnullが返る。
	 * 送信元アドレスが指定されていない場合は、nullが返る。
	 * 
	 * @return 送信元アドレス
	 */
	public InternetAddress getFrom()
	{
		return this.from;
	}

	/**
	 * 送信先(TO)のアドレスを取得する。
	 * 
	 * このメソッドを実行する前には、必ずparseメソッドを使用すること。 parseメソッドが使用される前は必ずnullが返る。
	 * 送信先アドレスが指定されていない場合は、空の配列が返る。
	 * 
	 * @return 送信先(TO)アドレス
	 */
	public InternetAddress[] getTo()
	{
		return this.to;
	}

	/**
	 * 送信先(CC)のアドレスを取得する。
	 * 
	 * このメソッドを実行する前には、必ずparseメソッドを使用すること。 parseメソッドが使用される前は必ずnullが返る。
	 * 送信先アドレスが指定されていない場合は、空の配列が返る。
	 * 
	 * @return 送信先(CC)アドレス
	 */
	public InternetAddress[] getCC()
	{
		return this.cc;
	}

	/**
	 * 送信先(TO)のアドレスを取得する。
	 * 
	 * このメソッドを実行する前には、必ずparseメソッドを使用すること。 parseメソッドが使用される前は必ずnullが返る。
	 * 送信先アドレスが指定されていない場合は、空の配列が返る。
	 * 
	 * @return 送信先(TO)アドレス
	 */
	public InternetAddress[] getBCC()
	{
		return this.bcc;
	}

	/**
	 * メールタイトルを取得する。
	 * 
	 * メールタイトルはエンコードされていないので、 設定時にエンコード名を指定してエンコードすること。
	 * 
	 * @return メールタイトル
	 */
	public String getSubject()
	{
		return this.subject;
	}

	/**
	 * メール本文を取得する。
	 * 
	 * メール本文はエンコードされていないので、 設定時にエンコード名を指定してエンコードすること。
	 * 
	 * @return メール本文
	 */
	public String getBody()
	{
		return this.body;
	}

	/**
	 * 添付ファイルのリストを取得する。
	 * 
	 * メールに添付するファイルの絶対パスの配列を取得する。 このメソッドを実行する前には、必ずparseメソッドを使用すること。
	 * parseメソッドが使用される前は必ずnullが返る。 添付ファイルが指定されていない場合は、空の配列が返る。
	 * 
	 * @return 添付ファイルの絶対パスの配列
	 */
	public String[] getAttachmentFiles()
	{
		return this.attachmentFiles;
	}

	/**
	 * メール送信用にパラメータを解釈する。
	 * 
	 * @param encode
	 *            エンコード名
	 * @throws AddressException
	 *             送信元、送信先アドレスが RFC822 構文に準拠していない場合
	 * @throws UnsupportedEncodingException
	 *             サポートされていないエンコード名を指定した場合
	 */
	public void parse(String encode) throws AddressException,
			UnsupportedEncodingException
	{
		Attribute[] attributes = getAttributes();

		// 送信元の設定
		from = parseInternetAddress(attributes,
					"MAIL_FROM_ADDRESS", "MAIL_FROM_NAME", encode);
		// 送信先(TO)の設定
		to = parseInternetAddresses(attributes,
					"MAIL_TO_ADDRESS", "MAIL_TO_NAME", encode);
		// 送信先(CC)の設定
		cc = parseInternetAddresses(attributes,
					"MAIL_CC_ADDRESS", "MAIL_CC_NAME", encode);
		// 送信先(BCC)の設定
		bcc = parseInternetAddresses(attributes,
					"MAIL_BCC_ADDRESS", "MAIL_BCC_NAME", encode);

		// メールタイトルの設定
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().equals("MAIL_SUBJECT")) {
				this.subject = attr.getValue();
				break;
			}
		}

		// メール本文の設定
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().equals("MAIL_BODY")) {
				buf.append(attr.getValue());
			}
		}
		String str = new String(buf);
		if (str != null) {
			this.body = str;
		}

		// 添付ファイル名の設定
		List<String> tempList = new ArrayList<String>();
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().equals("MAIL_ATTACHMENT_FILE")) {
				tempList.add(attr.getValue());
			}
		}
		this.attachmentFiles = (String[]) tempList.toArray(new String[0]);

	}

	/**
	 * メール送信のパラメータを解析して、InternetAddressオブジェクトを生成する。
	 * 
	 * メール送信のパラメータから、指定されたパラメータ名のアドレスと個人名を取得し、 InternetAddressオブジェクトを生成する。<br>
	 * 同じパラメータ名の複数の値が存在する場合は、最初の値を使用する。
	 * 
	 * @param addr
	 *            アドレスのパラメータ名
	 * @param personal
	 *            個人名のパラメータ名
	 * @param encode
	 *            エンコード名
	 * @return InternetAddressオブジェクト
	 * @throws AddressException
	 *             アドレスが RFC822 構文に準拠していない場合
	 * @throws UnsupportedEncodingException
	 *             サポートされていないエンコード名を指定した場合
	 */
	private InternetAddress parseInternetAddress(Attribute[] attributes, String addr, String personal,
			String encode) throws AddressException,
			UnsupportedEncodingException
	{

		// アドレスを取得
		String address = null;
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().equals(addr)) {
				address = attr.getValue();
				break;
			}
		}
		// 名称を取得
		String name = null;
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().equals(personal)) {
				name = attr.getValue();
				break;
			}
		}

		InternetAddress result = null;
		if (name != null) {
			result = new InternetAddress(address, name, encode);
		} else {
			result = new InternetAddress(address);
		}
		return result;
	}

	/**
	 * メール送信のパラメータを解析して、InternetAddressオブジェクトの配列を生成する。
	 * 
	 * メール送信のパラメータから、指定されたパラメータ名のアドレスと個人名を取得し、 InternetAddressオブジェクトの配列を生成する。
	 * 
	 * @param addr
	 *            アドレスのパラメータ名
	 * @param personal
	 *            個人名のパラメータ名
	 * @param encode
	 *            エンコード名
	 * @return InternetAddressオブジェクトの配列
	 * @throws AddressException
	 *             アドレスが RFC822 構文に準拠していない場合
	 * @throws UnsupportedEncodingException
	 *             サポートされていないエンコード名を指定した場合
	 */
	private InternetAddress[] parseInternetAddresses(Attribute[] attributes, String addr,
			String personal, String encode) throws AddressException,
			UnsupportedEncodingException
	{

		// アドレスを取得
		Map<String, String> addresses = new Hashtable<String, String>();
		String addrExpr = "^" + addr + "[1-9][0-9]*$";
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().matches(addrExpr)) {
				addresses.put(attr.getName(), attr.getValue());
			}
		}
		// 名前情報を取得
		Map<String, String> personals = new Hashtable<String, String>();
		String personalExpr = "^" + personal + "[1-9][0-9]*$";
		for (int i = 0; i < attributes.length; i++) {
			Attribute attr = attributes[i];
			if (attr.getName().matches(personalExpr)) {
				personals.put(attr.getName(), attr.getValue());
			}
		}
		// 設定
		List<InternetAddress> tempList = new ArrayList<InternetAddress>();
		for (String addrKey : addresses.keySet()) {
			String personalKey = addrKey.replaceAll(addr, personal);
			String addrValue = (String) addresses.get(addrKey);
			String personalValue = (String) personals.get(personalKey);
			InternetAddress temp = null;
			if (personalValue != null) {
				temp = new InternetAddress(addrValue, personalValue, encode);
			} else {
				temp = new InternetAddress(addrValue);
			}
			tempList.add(temp);
		}

		return (InternetAddress[]) tempList.toArray(new InternetAddress[0]);
	}
}
