/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

package org.opengion.hayabusa.taglib;

import static org.opengion.fukurou.util.StringUtil.nval;

import javax.jms.QueueSession;

import org.opengion.fukurou.queue.QueueInfo;
import org.opengion.fukurou.queue.QueueSend;
import org.opengion.fukurou.queue.QueueSendFactory;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;

/**
 * キュー送信 キュー送信用のタグです。
 *
 *@og.formSample 
 * ●形式：&lt;og:queueSend queueType=&quot;mq&quot; mqQueueName=&quot;queue01&quot; message=&quot;テキスト&quot; /&gt;
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 * 
 * ●Tag定義：
 *    &lt;og:queueSend
 *        jmsServer                      【TAG】JMSサーバの接続先を指定します。JNDI名で指定します。(初期値:jms/Default)
 *                                                          ※別途コンテキストファイルに接続情報が記載されている必要があります。
 *        queueType                    【TAG】タイプ(MQ,SQS)を指定します。
 *        mqTransacted               【TAG】トランザクション確認応答フラグを指定します。(MQ用)(初期値:false)
 *                                                          true:トランザクション確認応答 false: 確認応答タイプに指定した確認応答
 *        mqAcknowledgeMode  【TAG】確認応答タイプを指定します。(MQ用)(初期値:1)
 *                                                          1:AUTO_ACKNOWLEDTE(自動応答:１回の配信を保障)
 *                                                          2:CLIENT_ACKNOWLEDE(クライアント応答)
 *                                                          3:DUPS_OK_ACKNOWLEDTE(自動応答：複数回の配信可能性あり)
 *        mqQueueName            【TAG】キュー名を指定します。(MQ用)
 *        message                       【TAG】送信するメッセージを指定します。
 *        sqsFifoGroupId              【TAG】グループIDを指定します。(SQSのFIFOキュータイプ用)
 *        sqsFifoDedupliId           【TAG】重複排除IDを指定します。(SQSのFIFOキュータイプ用)
 * 
 * ● 使用例
 *        ・&lt;og:queueSend queueType=&quot;mq&quot; mqQueueName=&quot;queue01&quot; message=&quot;送信テキスト&quot; /&gt;
 *        ・&lt;og:queueSend queueType=&quot;mq&quot; mqQueueName=&quot;queue01&quot; /&gt;
 *               送信テキスト
 *           &lt;/og:queueSend&gt;
 *        ・&lt;og:queueSend queueType=&quot;sqs&quot; sqsGroupId=&quot;group01&quot; message=&quot;送信テキスト&quot; /&gt;
 *        
 * @og.group 画面部品
 * 
 * @og.rev 5.10.14.0 (2019/08/01) 新規作成
 * 
 * @version 5
 * @author oota
 * @sinse JDK7
 * 
 */
public class QueueSendTag extends CommonTagSupport {
	private static final String VERSION = "5";
	private static final long serialVersionUID = -4787270475247539761L;

	// 変数宣言
	private String jmsServer = null;
	private static final String CLOUD_SQS_ACCESS_KEY = HybsSystem.sys( "CLOUD_SQS_ACCESS_KEY" );
	private static final String CLOUD_SQS_SECRET_KEY = HybsSystem.sys( "CLOUD_SQS_SECRET_KEY" );
	private Boolean mqTransacted = false;
	private int mqAcknowledgeMode = QueueSession.AUTO_ACKNOWLEDGE;
	private String mqQueueName = null;
	private Boolean mqAsync = false;
	private String message = null;
	private String queueType = null;
	private String sqsFifoGroupId = null;
	private String sqsFifoDedupliId = null;

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 */
	@Override
	protected void release2() {
		super.release2();
		jmsServer = null;
		mqTransacted = false;
		mqAcknowledgeMode = QueueSession.AUTO_ACKNOWLEDGE;
		mqQueueName = null;
		mqAsync = false;
		message = null;
		queueType = null;
		sqsFifoGroupId = null;
		sqsFifoDedupliId = null;
	}

	/**
	 * Taglibの開始タグが見つかった時に処理する doStartTag() をオーバライドします。
	 * 
	 * @return 後続処理のsiji 
	 * 
	 */
	@Override
	public int doStartTag() {
		if( useTag() ) {
			// Body部を評価。
			return EVAL_BODY_BUFFERED;		// Body を評価する
		}
		return SKIP_BODY;		// Body を評価しない
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() をオーバーライドします。 
	 * 
	 * @return 後続処理の指示
	 */
	@Override
	public int doAfterBody() {
		// 属性項目のmessageを優先。
		if (StringUtil.isNull(message)) {
			message = getBodyString();
		}
		return SKIP_BODY;
	}

	/**
	 * Taglibの終了タグが見つかった時に処理する doEndTag() をオーバーライドします。
	 *
	 * @og.rev 5.10.15.0 (2019/08/30)アクセスキー修正
	 *
	 *  @return 後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();

		if( useTag() ) {
			// QueueSendクラスの生成
			QueueSend queueSend = QueueSendFactory.newQueueSend(queueType);
	
			try {
				// 1. 接続
				// @og.rev 5.10.15.0 (2019/08/30) sqs用のアクセスキーは引数から設定
				// queueSend.connect(jmsServer);
				queueSend.connect(jmsServer, CLOUD_SQS_ACCESS_KEY, CLOUD_SQS_SECRET_KEY);
	
				// 2. 送信キュー情報の設定
				QueueInfo queueInfo = new QueueInfo();
				// sql用情報
				queueInfo.setSqsFifoGroupId(sqsFifoGroupId);
				queueInfo.setSqsFifoDedupliId(sqsFifoDedupliId);
				// mq用情報
				queueInfo.setMqTransacted(mqTransacted);
				queueInfo.setMqAcknowledgeMode(mqAcknowledgeMode);
				queueInfo.setMqQueueName(mqQueueName);
				// メッセージ
				queueInfo.setMessage(message);
	
				// 3. 送信処理
				queueSend.sendMessage(queueInfo);
			} finally {
				// 4. 接続クローズ
				queueSend.close();
			}
		}
		
		return EVAL_PAGE;
	}

	/** Setter */
	/**
	 * 【TAG】メッセージサーバのURLを指定します。
	 * 
	 * @og.tag
	 * 送信先のメッセージサーバのURLを指定します。
	 * 
	 * @param server JMSサーバの接続先
	 */
	public void setJmsServer(final String server) {
		jmsServer = nval(getRequestParameter(server), jmsServer);
	}

	/**
	 * 【TAG】MQトランザクション処理判定を指定します。
	 * 
	 * @og.tag
	 * MQトランザクションの処理判定を指定します。
	 * true：受信側でコミット、ロールバックのトランザクション応答を行います。
	 * ※trueの場合は、MQ確認応答タイプは無効になります。
	 * false：受信側はMQ確認応答タイプに指定した値によって、確認応答を行います。
	 * 
	 * @param flg トランザクション処理フラグ
	 */
	public void setMqTransacted(final String flg) {
		mqTransacted = nval(getRequestParameter(flg), mqTransacted);
	}

	/**
	 * 【TAG】MQ確認応答タイプを指定します。
	 * 
	 * @og.tag
	 * MQ確認応答タイプを指定します。
	 * ※MQトランザクション処理判定にはfalseを指定して下さい。
	 * 
	 * 1：AUTO_ACKNOWLEDGE
	 * メッセージの配信の通知をjmsサーバーが自動的に処理するモードです。
	 * １回だけの配信を保障します。
	 * 2：CLIENT_ACKNOWLEDGE
	 * 確認応答を受信側が行うモードです。
	 * 受信側に確認応答の実行が必要です。
	 * 3：DUPS_OK_ACKNOWLEDGE
	 * AUTO_AKNOWLEDGEと同様にjmsサーバーが自動的に処理を行います。
	 * 複数回配信される可能性があります。(処理が軽い事がメリットです。
	 * 基本的にはAUTO_ACKNOWLEDGEを推奨します。)
	 * 
	 * @param mode 確認応答モード
	 */
	public void setMqAcknowledgeMode(final String mode) {
		mqAcknowledgeMode = nval(getRequestParameter(mode), mqAcknowledgeMode);
	}

	/**
	 * 【TAG】MQキュー名を指定します。
	 * 
	 * @og.tag
	 * MQタイプのキューを利用時、
	 * メッセージを格納するキュー名を指定します。
	 * 
	 * @param qName MQキュー名
	 */
	public void setMqQueueName(final String qName) {
		mqQueueName = nval(getRequestParameter(qName), mqQueueName);
	}

	/**
	 * 【TAG】メッセージを指定します。
	 * 
	 * @og.tag
	 * 送信するメッセージを指定します。
	 * 
	 * @param mess メッセージ
	 */
	public void setMessage(final String mess) {
		message = nval(getRequestParameter(mess), message);
	}

	/**
	 * 【TAG】キューのタイプを指定します。
	 * 
	 * @og.tag
	 * 利用するメッセージサーバのタイプを指定します。
	 * 下記のタイプが利用可能です。
	 * 
	 * mq : ActiveQueue or AmazonMQ
	 * sqs：AmazonSQS
	 * 
	 * @param qType キュータイプ
	 */
	public void setQueueType(final String qType) {
		queueType = nval(getRequestParameter(qType), queueType);
	}

	/**
	 * 【TAG】SQSのFIFOタイプキューのグループIDを指定します。
	 * 
	 * @og.tag
	 * awsのSQSのFIFOタイプキューを利用時、
	 * グループIDを指定します。
	 * 同一の値内で、FIFOの配信順序が保障されます。
	 * 
	 * @param sqsGid SQSFIFOタイプキューのグループID
	 */
	public void setSqsFifoGroupId(final String sqsGid) {
		sqsFifoGroupId = nval(getRequestParameter(sqsGid), sqsFifoGroupId);
	}

	/**
	 * 【TAG】 SQSのFIFOタイプキューの重複排除IDを指定します。
	 * 
	 * @og.tag
	 * awsのSQSのFIFOタイプキューを利用時、
	 * 重複排除IDを指定します。
	 * 5分間同一の値が送信された場合、キューに格納しない機能です。
	 * aws側の設定で、メッセージを暗号化した値を、自動設定することも可能です。
	 * 
	 * @param sqsFifoDid SQSFIFOタイプキューの重複禁止ID
	 */
	public void setSqsFifoDedupliId(final String sqsFifoDid) {
		sqsFifoDedupliId = nval(getRequestParameter(sqsFifoDid), sqsFifoDedupliId);
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 * 
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return org.opengion.fukurou.util.ToString.title(this.getClass().getName())
				.println("VERSION", VERSION)
				.println("jmsServer ", jmsServer)
				.println("mqTransacted", mqTransacted)
				.println("mqAcknowledgeMode", mqAcknowledgeMode)
				.println("mqQueueName", mqQueueName)
				.println("mqAsync", mqAsync)
				.println("message", message)
				.println("queueType", queueType)
				.println("sqsFifoGroupId", sqsFifoGroupId)
				.println("sqsFifoDedupliId", sqsFifoDedupliId).fixForm().toString();
	}
}
