001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.mail;
017
018import org.opengion.fukurou.system.OgRuntimeException ;                 // 6.4.2.0 (2016/01/29)
019import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
020import java.util.concurrent.ConcurrentHashMap;                                  // 6.4.3.1 (2016/02/12) refactoring
021import java.util.concurrent.ConcurrentSkipListMap;                              // 6.4.3.1 (2016/02/12) refactoring
022
023import org.opengion.fukurou.system.DateSet;                                             // 6.4.2.0 (2016/01/29)
024import org.opengion.fukurou.db.DBUtil;
025import org.opengion.fukurou.db.ApplicationInfo;
026import org.opengion.fukurou.util.StringUtil;
027import org.opengion.hayabusa.common.HybsSystem;
028
029import static org.opengion.fukurou.util.StringUtil.nval;                // 6.4.3.3 (2016/03/04)
030
031/**
032 * メールモジュール関係の機能の一部を他から使用するためのクラスです。
033 * 
034 * ※MailSenderTagからGE32,34へ履歴を出力する機能を追加する際に、モジュール系の動作を本パッケージに集約しておくために作成。
035 *   必要としている箇所のみ実装。
036 *   
037 * @og.rev 5.9.2.3 (2015/11/27) 新規作成
038 *
039 * @og.group メールモジュール
040 *
041 * @version  4.0
042 * @author   Takahashi Masakazu
043 * @since    JDK1.6
044 */
045public class MailModuleUtil {
046
047        // Ver4互換モード対応
048        private static final String CONTENTS = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "CONTENT" : "CONTENTS";
049
050        // 6.4.1.1 (2016/01/16) selYkno → SEL_YKNO , insGE32 → INS_GE32 , insGE34 → INS_GE34 refactoring
051        private static final String     SEL_YKNO        = "SELECT GE32S02.NEXTVAL YKNO FROM DUAL";
052        private static final String     INS_GE32                = "INSERT INTO GE32(YKNO,PARA_KEY,PTN_ID,FROM_ADDR,TITLE,"+CONTENTS+",ATTACH1,ATTACH2,ATTACH3,ATTACH4,ATTACH5,DYSET,USRSET,PGUPD,SYSTEM_ID,FGJ)"
053                                                                                        + " VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'1')";
054        private static final String INS_GE34            = "INSERT INTO GE34(YKNO,DST_ID,GROUP_ID,DST_NAME,DST_ADDR,DST_KBN,FGJ,DYSET,USRSET,PGUPD)"
055                                                                                        + " VALUES(?,?,?,?,?,?,?,?,?,?)";
056
057        // 内部データのカラム番号(履歴テーブル)
058        private static final int GE32_YKNO              = 0 ;
059        private static final int GE32_PARAKEY   = 1 ;
060        private static final int GE32_PTN_ID    = 2;
061        private static final int GE32_FROM_ADDR = 3;
062        private static final int GE32_TITLE     = 4;
063        private static final int GE32_CONTENTS  = 5;
064        // private static final int GE32_ATTACH1        = 6;
065        // private static final int GE32_ATTACH2        = 7;
066        // private static final int GE32_ATTACH3        = 8;
067        // private static final int GE32_ATTACH4        = 9;
068        // private static final int GE32_ATTACH5        = 10;
069        private static final int GE32_DYSET             = 11;
070        private static final int GE32_USRSET    = 12;
071        private static final int GE32_PGUPD     = 13;
072        private static final int GE32_SYSTEM_ID = 14;
073        // 内部データのカラム番号(履歴テーブル)
074        private static final int GE34_YKNO              = 0 ;
075        private static final int GE34_DST_ID    = 1 ;
076        private static final int GE34_GROUP_ID  = 2 ;
077        private static final int GE34_DST_NAME  = 3 ;
078        private static final int GE34_DST_ADDR  = 4 ;
079        private static final int GE34_DST_KBN   = 5 ;
080        private static final int GE34_FGJ               = 6 ;
081        private static final int GE34_DYSET             = 7 ;
082        private static final int GE34_USRSET    = 8 ;
083        private static final int GE34_PGUPD     = 9 ;
084
085        // アドレスマップ
086        private static final int IDX_DST_ADDR   = 0;
087        private static final int IDX_DST_KBN    = 1;
088
089        /** メール送信区分 {@value} */
090        private static final int KBN_TO                 = 0 ;   // メール送信区分(TO)
091        /** メール送信区分 {@value} */
092        private static final int KBN_CC                 = 1 ;   // メール送信区分(CC)
093        /** メール送信区分 {@value} */
094        private static final int KBN_BCC                = 2 ;   // メール送信区分(BCC)
095
096        /** 6.4.3.1 (2016/02/12) PMD refactoring. TreeMap → ConcurrentSkipListMap に置き換え。  */
097        private final ConcurrentMap<String, String[]> mailDstMap = new ConcurrentSkipListMap<>() ;                      // 6.4.3.3 (2016/03/04)
098
099        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。  */
100        private final ConcurrentMap<String, String> initParamMap = new ConcurrentHashMap<>();           // パラメータマップ
101
102        protected final String DBID = HybsSystem.sys( "RESOURCE_DBID" );                // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
103
104        /** コネクションにアプリケーション情報を追記するかどうか指定 */
105        private static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
106
107        /** アプリケーション情報 */
108        private static final ApplicationInfo APP_INFO;                          // 6.4.1.1 (2016/01/16) appInfo → APP_INFO refactoring
109
110        static {
111                if( USE_DB_APPLICATION_INFO ) {
112                        APP_INFO = new ApplicationInfo();
113                        // ユーザーID,IPアドレス,ホスト名
114                        APP_INFO.setClientInfo( "MailModuel", HybsSystem.HOST_ADRS, HybsSystem.HOST_NAME );
115                        // 画面ID,操作,プログラムID
116                        APP_INFO.setModuleInfo( "MailModuel", "MailManager", "MailManager" );
117                }
118                else {
119                        APP_INFO = null;
120                }
121        }
122
123        /**
124         * デフォルトコンストラクター
125         *
126         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
127         */
128        public MailModuleUtil() { super(); }            // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
129
130        /**
131         * 履歴テーブル(GE32)と宛先テーブル(GE34)に登録します。
132         * 登録時に、桁数オーバーにならないように、テーブル定義の桁数を上限として、
133         * 登録前に各項目の桁数整理を行います。
134         * 
135         * @og.rev 5.9.3.0 (2015/12/04) 添付ファイル対応
136         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
137         * @og.rev 6.4.3.2 (2016/02/19) Map を、 keySet() ではなく、values() に変更します。
138         *
139         */
140        public void commitMailDB(){
141                // 履歴テーブルの追加
142                String[] insGE32Args = new String[15];
143                final String ykno = getYkno();
144                final String[] attachFiles = StringUtil.csv2Array( initParamMap.get( "FILES" ) ); // 5.9.3.0
145
146                insGE32Args[GE32_YKNO]          = ykno;
147                insGE32Args[GE32_PARAKEY]       = initParamMap.get( "PARAKEY" );
148                insGE32Args[GE32_PTN_ID]        = trim( initParamMap.get( "PTN_ID" ), 20 );
149                insGE32Args[GE32_FROM_ADDR] = trim( initParamMap.get( "FROM"   ), 100);
150                insGE32Args[GE32_TITLE]         = trim( initParamMap.get( "TITLE"  ), 300);
151                insGE32Args[GE32_CONTENTS]      = initParamMap.get( "CONTENT" );        
152        //      insGE32Args[GE32_ATTACH1]       = "";
153        //      insGE32Args[GE32_ATTACH2]       = "";
154        //      insGE32Args[GE32_ATTACH3]       = "";
155        //      insGE32Args[GE32_ATTACH4]       = "";
156        //      insGE32Args[GE32_ATTACH5]       = "";
157                // 5.9.3.0
158                if( attachFiles != null ) {
159                        final int attSize = attachFiles.length;
160                        for( int i = 0; i < attSize; i++ ) {
161                                insGE32Args[6 + i] = trim( attachFiles[i], 256);
162                        }
163                }
164
165                insGE32Args[GE32_DYSET]         = DateSet.getDate( "yyyyMMddHHmmss" );                                          // 6.4.2.0 (2016/01/29)
166                insGE32Args[GE32_USRSET]        = initParamMap.get( "LOGIN_USERID" );
167                insGE32Args[GE32_PGUPD]         = initParamMap.get( "PGID" );
168                insGE32Args[GE32_SYSTEM_ID] = initParamMap.get( "SYSTEM_ID" );
169                DBUtil.dbExecute( INS_GE32, insGE32Args, APP_INFO, DBID );                                                      // 5.5.5.1 (2012/08/07)
170
171                // 宛先テーブル追加
172                String[] insGE34Args = new String[10];
173                insGE34Args[GE34_YKNO]= ykno;
174                // 6.4.3.2 (2016/02/19) Map を、 keySet() ではなく、values() に変更します。
175                for( final String[] vals : mailDstMap.values() ) {
176                        insGE34Args[GE34_DST_ID]        = trim( vals[IDX_DST_ADDR], 10 );
177                        insGE34Args[GE34_GROUP_ID]      = "";
178                        insGE34Args[GE34_DST_NAME]      = "";
179                        insGE34Args[GE34_DST_ADDR]      = trim( vals[IDX_DST_ADDR], 100 );
180                        insGE34Args[GE34_DST_KBN]       = vals[IDX_DST_KBN];
181                        insGE34Args[GE34_FGJ]           = "1";
182                        insGE34Args[GE34_DYSET]         = DateSet.getDate( "yyyyMMddHHmmss" );                          // 6.4.2.0 (2016/01/29)
183                        insGE34Args[GE34_USRSET]        = initParamMap.get( "LOGIN_USERID" );
184                        insGE34Args[GE34_PGUPD]         = initParamMap.get( "PGID" );
185                        DBUtil.dbExecute( INS_GE34, insGE34Args, APP_INFO, DBID );                                              // 5.5.5.1 (2012/08/07)
186                }
187
188        }
189
190        /**
191         * パラメータマップをセットします。
192         *
193         * @param       params  パラメータのマップ
194         */
195
196        /**
197         * パラメータからマップをセットします。
198         * 
199         * @og.rev 5.9.3.0 (2015/11/30) files追加
200         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
201         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. Map → ConcurrentMap に置き換え。
202         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
203         * 
204         * @param systemId      システムID(not null)
205         * @param from          FROMアドレス(not null)
206         * @param tos           TOアドレス(カンマ区切り)
207         * @param ccs           CCアドレス(カンマ区切り)
208         * @param bccs          BCCアドレス(カンマ区切り)
209         * @param content       本文
210         * @param title         タイトル
211         * @param userid        登録ユーザ
212         * @param pgid          登録PG
213         * @param files         添付ファイル
214         */
215        public void setInitParams( final String systemId, final String from, final String[] tos, final String[] ccs
216                                                                ,final String[] bccs, final String content, final String title, final String userid, final String pgid
217                                                                ,final String[] files ) {
218
219                // 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
220                if( systemId == null || from == null ) {
221                        final String errMsg = "systemId または、from  が null です。"
222                                                + " systemId=" + systemId + " , from=" + from  ;
223                        throw new OgRuntimeException( errMsg );
224                }
225
226                initParamMap.clear();
227
228                initParamMap.put( "SYSTEM_ID"   , systemId      );
229                initParamMap.put( "FROM"                , from          );
230                initParamMap.put( "TO"                  , StringUtil.array2csv( tos ) );
231                initParamMap.put( "CC"                  , StringUtil.array2csv( ccs ) );
232                initParamMap.put( "BCC"                 , StringUtil.array2csv( bccs ) );
233                initParamMap.put( "CONTENT"             , nval( content         , "No Content" ) );
234                initParamMap.put( "TITLE"               , nval( title           , "No Title" ) );
235                initParamMap.put( "DATE"                , DateSet.getDate("yyyy/MM/dd") );                              // 6.4.2.0 (2016/01/29)
236                initParamMap.put( "TIME"                , DateSet.getDate("HH:mm:ss") );                                // 6.4.2.0 (2016/01/29)
237                initParamMap.put( "LOGIN_USERID", nval( userid          , "No UserID" ) );
238                initParamMap.put( "PGID"                , nval( pgid            , "No PGID" ) );
239                initParamMap.put( "FILES"               , StringUtil.array2csv( files ) );                              // 5.9.3.0 (2015/12/04)
240
241                getDstMap( tos, ccs, bccs );
242
243        }
244
245        /**
246         * 指定の長さ以内の文字列を返します。
247         *
248         * @og.rev 5.9.1.3 (2015/10/30) 文字数ではなくByte数に変更
249         *
250         * @param       src             オリジナルの文字列
251         * @param       maxLen  指定の長さ
252         *
253         * @return      指定の長さに短縮された文字列
254         */
255        private String trim( final String src, final int maxLen ) {
256                String rtn = src;
257                if( src != null && src.length() > maxLen ) {
258                        rtn = StringUtil.cut( src, maxLen );
259                }
260                return rtn;
261        }
262
263        /**
264         * 要求NOを採番します。
265         * この要求NOで履歴テーブル(GE32)と宛先テーブル(GE30)の関連付けを持たせます。
266         *
267         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
268         *
269         * @return      要求NO
270         */
271        private String getYkno() {
272                final String[][] tmp = DBUtil.dbExecute( SEL_YKNO, new String[0], APP_INFO, DBID );             // 5.5.5.1 (2012/08/07)
273                if( tmp == null || tmp.length == 0 ) {
274                        final String errMsg = "要求NO採番エラー"
275                                                + " SQL=" + SEL_YKNO ;          // 5.1.8.0 (2010/07/01) errMsg 修正
276                        throw new OgRuntimeException( errMsg );
277                }
278                return tmp[0][0];
279        }
280
281        /**
282         * 送信先のアドレスをセットします。
283         *
284         * @og.rev 6.4.3.1 (2016/02/12) インスタンス変数で初期化した、ConcurrentSkipListMap を使用します。
285         *
286         * @param toId  送信先TOのアドレス
287         * @param ccId  送信先CCのアドレス
288         * @param bccId 送信先BCCのアドレス
289         */
290        private void getDstMap( final String[] toId, final String[] ccId, final String[] bccId  ){
291                // 送信先(TO、CC、BCC)のマップを初期化します。
292                mailDstMap.clear();
293
294                // 送信先(TO、CC、BCC)のマップに、値をセットします。セット順ではなく、自然ソート順です。
295                setDstAddrMap( mailDstMap , bccId, KBN_BCC );
296                setDstAddrMap( mailDstMap , ccId,  KBN_CC  );
297                setDstAddrMap( mailDstMap , toId,  KBN_TO  );
298        }
299
300        /**
301         * 送信先のアドレス・マップを作成します。
302         *
303         * @og.rev 6.4.3.1 (2016/02/12) インスタンス変数で初期化した、ConcurrentSkipListMap を使用します。
304         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
305         *
306         * @param       dstMap  設定するMapオブジェクト
307         * @param       dstBuf  送信先配列
308         * @param       kbn             送信区分[0:TO/1:CC/2:BCC]
309         */
310        private void setDstAddrMap( final ConcurrentMap<String, String[]> dstMap, final String[] dstBuf, final int kbn ){
311                // IDX_DST_ADDR ,IDX_DST_KBN
312                final String[] dstInit = { "", Integer.toString( kbn ) };
313
314                final int len = dstBuf.length;
315                for( int i=0; i < len; i++ ){
316                        String[] indMember = dstInit.clone();
317                        indMember[IDX_DST_ADDR] = dstBuf[i];                    // メールアドレス
318
319                        dstMap.put( dstBuf[i], indMember );
320                }
321        }
322}