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     */
016    package org.opengion.hayabusa.resource;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.common.HybsSystemException;
020    
021    import java.util.Calendar;
022    import java.util.Map;
023    import java.util.SortedMap;
024    import java.util.TreeMap ;
025    import java.util.BitSet ;
026    
027    /**
028     * 事業æ‰?CDJGS) 毎ã?休日カレンãƒ?ƒ‡ãƒ¼ã‚¿ã‚ªãƒ–ジェクトã§ã™ã?
029     *
030     * カレンãƒ?ƒ‡ãƒ¼ã‚¿ã¯ã€æŒ‡å®šã?事業æ‰?«é–¢ã—ã¦ã€ã™ã¹ã¦ã®ä¼‘æ—¥æƒ??ã‚’æŒã£ã¦ã?¾ã™ã?
031     * å…??カレンãƒ?ƒ†ãƒ¼ãƒ–ル(GE13)ã® ?‘æ—¥(DY1)?žï¼“1日(DY31)ã¾ã§ã®æ—¥ä»˜ã‘æ¬?«å¯¾ã—ã¦ã€?
032     * 休日日付ã‘㮠年月日 ã«å¯¾ã™ã‚‹ã€ä¼‘æ—¥ã‹ã©ã?‹ã‚’判断ã§ãã‚‹ã?‘ã®æƒ??ã‚’ä¿æŒã—ã¾ã™ã?
033     * 具体的ã«ã¯ã€ä¼‘æ—¥ã®å¹´æœˆæ—¥ã«å¯¾ã™ã‚‹ List ã‚’æŒã¤ã“ã¨ã«ãªã‚Šã¾ã™ã?
034     * ã“ã?クラスã¯ã€ãƒ‘ãƒ?‚±ãƒ¼ã‚¸ãƒ—ライベã?トã«ãªã£ã¦ã?¾ã™ã?ã“ã?オブジェクトを作æ?ã™ã‚‹ã®ã¯ã€?
035     * CalendarFactory#getCalendarData( String ) ã§è¡Œã„ã¾ã™ã?引数ã¯ã€äº‹æ¥­æ‰?‚³ãƒ¼ãƒ?cdjgs)ã§ã™ã?
036     * ã“ã?カレンãƒ?‚ªãƒ–ジェクトを使用ã™ã‚‹ã«ã¯ã€äº‹æ¥­æ‰?‚«ãƒ¬ãƒ³ãƒ?ƒ†ãƒ¼ãƒ–ル(GE13) を使用ã™ã‚‹
037     * ã“ã¨ã‚’許å¯ã—ã¦ãŠãå¿?¦ãŒã‚りã¾ã™ã?
038     * 許å¯ã¯ã€ã‚·ã‚¹ãƒ?ƒ ãƒ‘ラメータ ã® USE_CALENDAR_DATABASE 属æ?ã‚?true ã«
039     * 設定ã—ã¾ã?åˆæœŸå€¤ã¯ã€äº’æ›æ€§å„ªå…ˆã? false ã§ã™ã?)
040     * ã“ã?ã€ã‚«ãƒ¬ãƒ³ãƒ?ƒ†ãƒ¼ãƒ–ルã¯ã€GE13 固定ã§ã™ã?ä»–ã?ãƒ??ブルを使用ã™ã‚‹å ´åˆã?ã€?
041     * ビュー等を作æ?ã™ã‚‹å¿?¦ãŒã‚りã¾ã™ã?
042     * カレンãƒ?ƒ†ãƒ¼ãƒ–ル ã¯ã€??常 DEFAULT DBIDを使用ã—ã¾ã™ãŒã€RESOURCE_CALENDAR_DBID
043     * を設定ã™ã‚‹ã“ã¨ã§ã€ä»–ã?ãƒ??タベã?スã‹ã‚‰èª­ã¿å–ã‚‹ã“ã¨ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã?
044     *
045     * @og.rev 3.6.0.0 (2004/09/17) æ–°è¦ä½œæ?
046     * @og.group リソース管ç?
047     *
048     * @version  4.0
049     * @author   Kazuhiko Hasegawa
050     * @since    JDK5.0,
051     */
052    class CalendarDBData implements CalendarData {
053            private final SortedMap<String,BitSet> ymMap  = new TreeMap<String,BitSet>() ;      // 休日日付ã‘ãƒ??ã‚¿ã‚’å¹´æœˆã‚’ã‚­ãƒ¼ã«æŒã¡ã¾ã™ã?
054    //      private final Calendar today = Calendar.getInstance();  // 3.8.8.6 (2007/04/20) å»?­¢
055    
056            /**
057             * コンストラクタ
058             *
059             * é…å?æ–?­—å?ã®ãƒ??ã‚¿ã‚’å?ã«ã€CalendarDBDataオブジェクトを構築ã—ã¾ã™ã?
060             * ã“ã?コンストラクタã¯ã€ä»–ã?パッケージã‹ã‚‰å‘¼ã³å‡ºã›ãªã?‚ˆã?«ã€?
061             * パッケージプライベã?トã«ã—ã¦ãŠãã¾ã™ã?
062             * 年月データã¯ã€??ç¶šã§ã‚ã‚‹å¿?¦ãŒã‚りã¾ã™ã?
063             * é€”ä¸­ã«æŠœã‘ãŒã‚ã‚‹ã‹ã©ã?‹ã®ãƒã‚§ãƒ?‚¯ã‚’行ã„ã¾ã™ã?
064             *
065             * @param       data    ãƒ??タベã?ス検索ãƒ??ã‚¿
066             * @param       isFlat  縦æŒã¡(false)ã‹æ¨ªæŒã¡(true)ã®åŒºåˆ¥
067             */
068            CalendarDBData( final String[][] data,final boolean isFlat ) {
069                    if( isFlat ) {
070                            callFlatTable( data );
071                    }
072                    else {
073                            callVerticalTable( data );
074                    }
075    
076                    // 3.7.1.1 (2005/05/31)
077    //              today.set( Calendar.HOUR_OF_DAY ,12 );  // 昼ã«ã‚»ãƒ?ƒˆ
078    //              today.set( Calendar.MINUTE ,0 );
079    //              today.set( Calendar.SECOND ,0 );
080            }
081    
082            /**
083             * 横æŒã¡(フラãƒ?ƒˆ)é…å?æ–?­—å?ã®ãƒ??ã‚¿ã‚’å?ã«ã€æ—¥ä»˜æƒ…報を構築ã—ã¾ã™ã?
084             * 年月データã¯ã€??ç¶šã§ã‚ã‚‹å¿?¦ãŒã‚りã¾ã™ã?
085             * é€”ä¸­ã«æŠœã‘ãŒã‚ã‚‹ã‹ã©ã?‹ã®ãƒã‚§ãƒ?‚¯ã‚’行ã„ã¾ã™ã?
086             *
087             * @og.rev 3.8.8.0 (2007/12/22) 休日ãŒå?ããªã??åˆã§ã‚‚ã?日付設定ã™ã‚‹ã?
088             *
089             * @param data String[][]
090             *                     [0]:å¹´æœ?YYYYMM) 200406 ã¨ã?†å½¢å¼?
091             *                     [1]?ž[31] 1æ—¥??1æ—¥ã®ãƒ??ã‚¿
092             *                           0:平日 / ãã?ä»?休日
093             */
094            private void callFlatTable( final String[][] data ) {
095                    for( int ym=0; ym<data.length; ym++ ) {
096                            String yyyymm = data[ym][0] ;
097                            if( yyyymm.length() != 6 ) {
098                                    String errMsg = "å¹´æœ?YYYYMM)ã¯ã€YYYYMM(例ï¼?00406) ã¨ã?†å½¢å¼ã§æŒ?®šã—ã¦ä¸‹ã•ã??"
099                                                            + " YYYYMM [" + yyyymm + "]" ;
100                                    throw new HybsSystemException( errMsg );
101                            }
102    
103                            Calendar month = HybsSystem.getCalendar( yyyymm + "01" );       // 当月
104                            int lastDay = month.getActualMaximum( Calendar.DAY_OF_MONTH );  // 月末日
105    
106                            BitSet ymData = new BitSet( lastDay+1 );
107                            for( int d=1; d<=lastDay; d++ ) {
108                                    if( ! "0".equals( data[ym][d] ) ) {
109                                            // 日付ã‘ã®ãƒ“ットを立ã¦ã¾ã™ã?
110                                            ymData.set( d );
111                                    }
112                            }
113    
114                            // 日付ã‘ã®ã‚­ãƒ¼ãŒã‚りã?休日設定ãŒã‚れã°ã€æœ‰åŠ¹æœˆã¨ã¿ãªã—ã?ã‚»ãƒ?ƒˆã—ã¾ã™ã?
115                            // 3.8.8.0 (2007/12/22) 休日ãŒå?ããªã??åˆã§ã‚‚ã?日付設定ã™ã‚‹ã?
116                            ymMap.put( yyyymm,ymData );
117                    }
118            }
119    
120            /**
121             * 縦æŒã¡(ãƒã?ãƒ?‚£ã‚«ãƒ«)é…å?æ–?­—å?ã®ãƒ??ã‚¿ã‚’å?ã«ã€æ—¥ä»˜æƒ…報を構築ã—ã¾ã™ã?
122             * 年月データã¯ã€??ç¶šã§ã‚ã‚‹å¿?¦ãŒã‚りã¾ã™ã?
123             * é€”ä¸­ã«æŠœã‘ãŒã‚ã‚‹ã‹ã©ã?‹ã®ãƒã‚§ãƒ?‚¯ã‚’行ã„ã¾ã™ã?
124             *
125             * @og.rev 3.8.8.0 (2007/12/22) 休日ãŒå?ããªã??åˆã§ã‚‚ã?日付設定ã™ã‚‹ã?
126             *
127             * @param data String[][]
128             *                     [0]:å¹´æœ?YYYYMMDD) 20040601 ã¨ã?†å½¢å¼?
129             *                     [1] 0:平日 / ãã?ä»?休日
130             */
131            private void callVerticalTable( final String[][] data ) {
132                    String bk_yyyymm = null;
133                    BitSet ymData = null;
134                    for( int ymd=0; ymd<data.length; ymd++ ) {
135                            if( data[ymd][0].length() != 8 ) {
136                                    String errMsg = "年月日(YYYYMMDD)ã¯ã€YYYYMMDD(例ï¼?0040601) ã¨ã?†å½¢å¼ã§æŒ?®šã—ã¦ä¸‹ã•ã??"
137                                                            + " YYYYMMDD [" + data[ymd][0] + "]" ;
138                                    throw new HybsSystemException( errMsg );
139                            }
140    
141                            String yyyymm = data[ymd][0].substring( 0,6 ) ;
142                            if( ! yyyymm.equals( bk_yyyymm ) ) {    // 月ã?ブレイク
143                                    // 日付ã‘ã®ã‚­ãƒ¼ãŒã‚りã?休日設定ãŒã‚れã°ã€æœ‰åŠ¹æœˆã¨ã¿ãªã—ã?ã‚»ãƒ?ƒˆã—ã¾ã™ã?
144                                    // 3.8.8.0 (2007/12/22) 休日ãŒå?ããªã??åˆã§ã‚‚ã?日付設定ã™ã‚‹ã?
145                                    if( ymData != null && bk_yyyymm != null ) {
146                                            ymMap.put( bk_yyyymm,ymData );
147                                    }
148                                    bk_yyyymm = yyyymm;
149    
150                                    Calendar month = HybsSystem.getCalendar( yyyymm + "01" );       // 当月
151                                    int lastDay = month.getActualMaximum( Calendar.DAY_OF_MONTH );  // 月末日
152    
153                                    ymData = new BitSet( lastDay+1 );
154                            }
155    
156                            if( ! "0".equals( data[ymd][1] ) ) {
157                                    // 日付ã‘ã®ãƒ“ットを立ã¦ã¾ã™ã?
158                                    int dt = Integer.parseInt( data[ymd][0].substring( 6 ) );
159                                    ymData.set( dt );
160                            }
161                    }
162                    // 日付ã‘ã®ã‚­ãƒ¼ãŒã‚りã?休日設定ãŒã‚れã°ã€æœ‰åŠ¹æœˆã¨ã¿ãªã—ã?ã‚»ãƒ?ƒˆã—ã¾ã™ã?
163                    // 3.8.8.0 (2007/12/22) 休日ãŒå?ããªã??åˆã§ã‚‚ã?日付設定ã™ã‚‹ã?
164                    if( ymData != null && bk_yyyymm != null ) {
165                            ymMap.put( bk_yyyymm,ymData );
166                    }
167            }
168    
169            /**
170             * æŒ?®šã?日付ã‘ãŒã?休日ã‹ã©ã?‹ã‚’è¿”ã—ã¾ã™ã?
171             * æŒ?®šã?日付ã‘ãŒã?ãƒ??タベã?スã«è¨­å®šã•れã¦ã?ªã??åˆã?ã€ã™ã¹ã¦ä¼‘æ—¥ã‚?
172             * è¿”ã™ã“ã¨ã§ã€å­˜åœ¨ã—ãªã?º‹ã‚’示ã—ã¾ã™ã?
173             *
174             * @param  day Calendar æŒ?®šã?日付ã‘
175             *
176             * @return      休日?štrue ãれ以外:false
177             *
178             */
179            public boolean isHoliday( final Calendar day ) {
180                    String yyyymm = cal2YM( day );
181                    BitSet ymData = ymMap.get( yyyymm );
182    
183                    if( ymData != null ) {
184                            return ymData.get( day.get( Calendar.DATE ) );
185                    }
186                    else {
187                            return true;    // DB 上ã«ç™»éŒ²ã•れã¦ã?ªã??åˆã?ã€ã™ã¹ã¦ä¼‘æ—¥ã¨ã™ã‚‹ã€?
188                    }
189            }
190    
191            /**
192             * æŒ?®šã?日付ã‘ã‹ã‚‰ã€ç¯?›²ã®é–“ã«ã€æœ¬æ—¥ã‚’å«ã‚?‹ã©ã?‹ã‚’è¿”ã—ã¾ã™ã?
193             * æŒ?®šã?日付ã‘ãŒã?キャãƒ?‚·ãƒ¥ã—ã¦ã?‚‹ãƒ??ã‚¿ã®æœ?¤§ã¨æœ?°ã?é–“ã«
194             * 存在ã—ãªã??åˆã?ã€å¸¸ã« false ã«ãªã‚Šã¾ã™ã?
195             * 判定ã?ã€å¹´æœˆæ—¥ã®é ?›®ã®ã¿ã§æ¯”è¼?—ã€æ™‚åˆ?§’ã?無視ã—ã¾ã™ã?
196             *
197             * @og.rev 3.7.1.1 (2005/05/31) æ–°è¦è¿½åŠ?
198             * @og.rev 3.8.8.6 (2007/04/20) today を毎回求ã‚ã¾ã™ã?(キャãƒ?‚·ãƒ¥å¯¾ç­?
199             *
200             * @param  day Calendar æŒ?®šã?開始日付ã‘
201             * @param       scope   ç¯?›²ã®æ—¥æ•°
202             *
203             * @return      本日?štrue ãれ以外:false
204             */
205            public boolean isContainedToday( final Calendar day,final int scope ) {
206                    final boolean rtnFlag;
207    
208                    Calendar today = Calendar.getInstance();
209                    today.set( Calendar.HOUR_OF_DAY ,12 );  // 昼ã«ã‚»ãƒ?ƒˆ
210                    today.set( Calendar.MINUTE ,0 );
211                    today.set( Calendar.SECOND ,0 );
212    
213                    if( scope == 1 ) {
214                            // false ã®ç¢ºçŽ??é«˜ã„æ–¹ã‹ã‚‰ã€æ¯”è¼?—ã¾ã™ã?
215                            rtnFlag = day.get( Calendar.DATE )  == today.get( Calendar.DATE  ) &&
216                                                    day.get( Calendar.MONTH ) == today.get( Calendar.MONTH ) &&
217                                                    day.get( Calendar.YEAR )  == today.get( Calendar.YEAR  ) ;
218                    }
219                    else {
220                            Calendar next = (Calendar)day.clone();
221                            next.add( Calendar.DATE,scope );
222                            rtnFlag = day.before( today ) && next.after( today ) ;
223                    }
224                    return rtnFlag ;
225            }
226    
227            /**
228             * æŒ?®šã?é–‹å§‹ã?終äº?—¥ã®æœŸé–“ã«ã€å¹³æ—¥(ç¨¼åƒæ—¥)ãŒä½•æ—¥ã‚ã‚‹ã‹æ±‚ã‚ã¾ã™ã?
229             * 調査月ãŒã€ãƒ‡ãƒ¼ã‚¿ãƒ™ã?ス上ã«å­˜åœ¨ã—ã¦ã?ªã??åˆã?ã€ã‚¨ãƒ©ãƒ¼ã¨ã—ã¾ã™ã?
230             * é–‹å§‹ã¨çµ‚äº?ŒåŒã˜æ—¥ã®å ´åˆã?ã€?¼‘ã‚’è¿”ã—ã¾ã™ã?
231             *
232             * @param  start Calendar 開始日付ã‘(ç¨¼åƒæ—¥ã«å«ã‚ã¾ã?
233             * @param  end   Calendar 終äº?—¥ä»˜ã‘(ç¨¼åƒæ—¥ã«å«ã‚ã¾ã?
234             *
235             * @return      ç¨¼åƒæ—¥æ•°
236             *
237             */
238            public int getKadoubisu( final Calendar start,final Calendar end ) {
239    
240                    String stYM = cal2YM( start );
241                    String edYM = cal2YM( end );
242    
243                    SortedMap<String,BitSet> subMap = ymMap.subMap( stYM,edYM+"\0" ) ;        // 終äº?‚­ãƒ¼ã¯ãã?ã¾ã¾ã§ã¯å«ã¾ã‚Œãªã?Ÿã‚ã?
244    
245                    @SuppressWarnings("rawtypes")
246                    Map.Entry[] entrys = (subMap.entrySet()).toArray( new Map.Entry[subMap.size()] );
247    
248                    int holidaySu = 0;
249                    for( int i=0; i<entrys.length; i++ ) {
250                            String ym = (String)entrys[i].getKey();
251                            BitSet bt ;
252                            if( stYM.equals( ym ) ) {
253                                    bt = ((BitSet)entrys[i].getValue()).get( start.get( Calendar.DATE ),31 );
254                            }
255                            else if( edYM.equals( ym ) ) {
256                                    bt = ((BitSet)entrys[i].getValue()).get( 1,end.get( Calendar.DATE )+1 );
257                            }
258                            else {
259                                    bt = (BitSet)entrys[i].getValue();
260                            }
261                            holidaySu += bt.cardinality() ;
262                    }
263    
264                    long diff = start.getTimeInMillis() - end.getTimeInMillis() ;
265                    int dayCount = (int)(diff/(1000*60*60*24)) + 1; // end ã‚‚å«ã‚??ã§?‹ï¼‘å¿?¦?
266    
267                    return dayCount - holidaySu ;
268            }
269    
270            /**
271             * æŒ?®šã?é–‹å§‹æ—¥ã«å¹³æ—¥ã®ã¿æœŸé–“を加算ã—ã¦æ±‚ã‚られる日付ã‘ã‚’è¿”ã—ã¾ã™ã?
272             * ã“れã¯ã€å®Ÿç¨¼åƒæ—¥è¨ˆç®—ã«ä½¿ç”¨ã—ã¾ã™ã?
273             * 例ãˆã°ã€start=20040810 , span=5 ã§ã€ä¼‘æ—¥ãŒãªã‘れã°ã€?0,11,12,13,14 ã¨ãªã‚Šã?
274             * 20040815 ã‚’è¿”ã—ã¾ã™ã?
275             * æŒ?®šã?日付ã‘ã‚??期間åŠ?®—後ã?日付ã‘ãŒã?キャãƒ?‚·ãƒ¥ã—ã¦ã?‚‹ãƒ??ã‚¿ã®
276             * æœ?¤§ã¨æœ?°ã?é–“ã«å­˜åœ¨ã—ãªã??åˆã?ã€ã‚¨ãƒ©ãƒ¼ã¨ã—ã¾ã™ã?
277             *
278             * @param  start Calendar   開始日付ã‘(YYYYMMDD å½¢å¼?
279             * @param       span    稼動期�
280             *
281             * @return Calendar é–‹å§‹æ—¥ã‹ã‚‰ç¨¼å‹•期間をåŠ?®—ã—ãŸæ—¥ä»˜ã‘(当日をå«ã‚?
282             *
283             */
284            public Calendar getAfterDay( final Calendar start,final int span ) {
285                    Calendar today = (Calendar)(start.clone());
286                    int suSpan = span ;
287                    while( suSpan > 0 ) {
288                            if( ! isHoliday( today ) ) { suSpan--; }
289                            today.add(Calendar.DATE, 1);            // æ—¥ã«ã¡ã‚’é?ã‚ã‚‹ã€?
290                    }
291                    return today ;
292            }
293    
294            /**
295             * カレンãƒ?‚ªãƒ–ジェクトよりã?年月を YYYYMM å½¢å¼ã«ã—㟠æ–?­—å?ã‚’è¿”ã—ã¾ã™ã?
296             *
297             * @return  カレンãƒ??YYYYMM æ–?­—å?
298             */
299            private String cal2YM( final Calendar cal ) {
300                    return String.valueOf(
301                                            cal.get( Calendar.YEAR ) * 100 +
302                                            cal.get( Calendar.MONTH ) + 1 );
303            }
304    
305            /**
306             * オブジェクトã?識別å­ã¨ã—ã¦?Œè©³ç´°ãªã‚«ãƒ¬ãƒ³ãƒ?ƒ…報を返ã—ã¾ã™ã?
307             *
308             * @return  詳細ãªã‚«ãƒ¬ãƒ³ãƒ?ƒ…å ±
309             */
310            public String toString() {
311                    StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
312                    rtn.append( "CLASS   : ").append( getClass().getName() ).append( HybsSystem.CR );       // クラスå?
313    
314                    @SuppressWarnings("rawtypes")
315                    Map.Entry[] entrys = (ymMap.entrySet()).toArray( new Map.Entry[ymMap.size()] );
316    
317                    for( int i=0; i<entrys.length; i++ ) {
318                            String yyyymm = (String)entrys[i].getKey();
319    
320                            rtn.append( yyyymm );
321                            rtn.append( ":" );
322                            rtn.append( (BitSet)entrys[i].getValue() );
323                            rtn.append( HybsSystem.CR );
324                    }
325    
326                    return rtn.toString();
327            }
328    }