    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.plugin.column;
    017
    018import java.util.Calendar;
    019
    020import org.opengion.fukurou.util.ErrorMessage;
    021import org.opengion.fukurou.util.StringUtil;
    022import org.opengion.hayabusa.db.AbstractDBType;
    023import org.opengion.hayabusa.db.DBTypeCheckUtil;
    024import org.opengion.fukurou.util.HybsDateUtil;
    025
    026/**
    027 * 文字列の時間属性(時:分:秒)の半角の時間を扱う為の、カラム属性を定義します。
    028 *
    029 * HHmmss に対応している必要があります。
    030 * (HHmmのデータでも利用可能です)
    031 *
    032 * ただし、日付の整合性チェックは行いませんが、valueAdd( String value )での
    033 * 日付の加算時には、正式な日付データにて加算します。
    034 *
    035 * タイプチェックとして、以下の条件を判定します。
    036 * ・文字列長は、直接計算で文字数との比較
    037 * ・日付使用文字チェック「('0' &gt; c || '9' &lt; c)以外」エラー
    038 * ・文字パラメータの 正規表現チェック
    039 *     例えば、24時や60分をエラーにしたい場合、｢([0-1][0-9]|[2][0-3])[0-5][0-9]｣ という
    040 *     正規表現を文字パラメータに登録すれば、チェックできます。
    041 *
    042 * @og.group データ属性
    043 * @og.rev 5.4.3.6 (2012/01/20)  タイプチェックが抜けているので追加
    044 *
    045 * @version  4.0
    046 * @author   Kazuhiko Hasegawa
    047 * @since    JDK5.0,
    048 */
    049public class DBType_HMS extends AbstractDBType {
    050        /** このプログラムのVERSION文字列を設定します。   {@value} */
    051        private static final String VERSION = "7.2.5.1 (2020/06/05)" ;
    052
    053        /**
    054         * デフォルトコンストラクター
    055         *
    056         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    057         */
    058        public DBType_HMS() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    059
    060        /**
    061         * String引数の文字列を＋１した文字列を返します。
    062         * これは、英字の場合(A,B,C など)は、B,C,D のように,最終桁の文字コードを
    063         * ＋１ します。
    064         * 文字列が数字タイプの場合は, 数字に変換して、+1 します。(桁上がりもあり)
    065         * 混在タイプの場合は,最後の桁だけを確認して ＋１します。
    066         * 引数が null の場合と、ゼロ文字列("")の場合は,物理的初期設定値(String getDefault())
    067         * の値を返します。
    068         * 24時間を超えた場合は、25時となります。
    069         *
    070         * @og.rev 6.2.2.2 (2015/04/03) 桁数可変に対応
    071         *
    072         * @param       value   String引数の文字列
    073         *
    074         * @return  String引数の文字列を＋１した文字列(１時間加算)
    075         */
    076        @Override
    077        public String valueAdd( final String value ) {
    078                if( value == null || value.isEmpty() ) { return getDefault(); }
    079
    080                // 6.2.2.2 (2015/04/03) ４桁より小さいとHHmm、それ以外は、HHmmss
    081                final boolean isHM = value.length() <= 4 ;
    082
    083                //                        HHmm    HHmmss
    084                final int hms = ( isHM ? 10100 : 1010000 ) + Integer.parseInt( value );
    085
    086                // 元の形式に準拠して返す。
    087                return String.valueOf( hms ).substring( 1 );
    088        }
    089
    090        /**
    091         * String引数の文字列に、第２引数に指定の文字列(数字、日付等)を加算して返します。
    092         *
    093         * ここでは、HHmmss 形式のデータに、時間を加算します。
    094         *
    095         * この HMS は、引数に、日付単位を指定できます。単位は、HHmmss 形式の
    096         * １文字を指定します。大文字、小文字も識別します。value="5H" とすれば、５時間、
    097         * value="5m"とすれば、５分 追加します。
    098         * 指定しない場合は、時を加算します。
    099         *
    100         * ここのデータは、時間が繰り越しても、日付に影響しません。
    101         * また、２４時間を超えた場合は、00 時に戻ります。
    102         *
    103         * @og.rev 5.6.0.3 (2012/01/24) ADD に、引数の値を加算する機能を追加します。
    104         * @og.rev 5.6.1.0 (2013/02/01) 加算する引数に、日付単位('H','m','s')を指定可能にします。
    105         * @og.rev 6.2.2.2 (2015/04/03) 桁数可変に対応
    106         *
    107         * @param   value  String引数
    108         * @param   add    加算する時間文字列(単位付き:['H','m','s'])
    109         *
    110         * @return  引数の文字列に時間を加算します。
    111         */
    112        @Override
    113        public String valueAdd( final String value,final String add ) {
    114                if( value == null || value.isEmpty() ) { return getDefault(); }
    115                // 日付文字列にダミーの年月日を追加しておく。
    116
    117                final boolean isHM = value.length() <= 4 ;
    118
    119                // ※ yyyymmd + 1HHmmss で、日付データのダミーの年月日を追加
    120                final int hms = 1000000 + Integer.parseInt( isHM ? value + "00" : value );
    121
    122                // 元の形式に準拠して返す。
    123                return HybsDateUtil.getDatePlus( ( "2010010" + hms ),add,Calendar.HOUR_OF_DAY, isHM ? "HHmm" : "HHmmss" );
    124        }
    125
    126        /**
    127         * エディターで編集されたデータを登録する場合に、データそのものを
    128         * 変換して、実登録データを作成します。
    129         * 例えば,大文字のみのフィールドなら、大文字化します。
    130         * 実登録データの作成は、DBType オブジェクトを利用しますので,
    131         * これと Editor とがアンマッチの場合は、うまくデータ変換
    132         * されない可能性がありますので、注意願います。
    133         *
    134         * @og.rev 6.2.2.2 (2015/04/03) 桁数可変に対応
    135         * @og.rev 6.2.2.3 (2015/04/10) 数値変換エラーを発生させない様にします。
    136         *
    137         * @param       value   (一般に編集データとして登録されたデータ)
    138         *
    139         * @return  修正後の文字列(一般にデータベースに登録するデータ)
    140         */
    141        @Override
    142        public String valueSet( final String value ) {
    143                if( value == null || value.isEmpty() ) { return ""; }
    144
    145                // 6.2.2.2 (2015/04/03) ４桁より小さいとHHmm、それ以外は、HHmmss
    146                final String val = StringUtil.deleteChar( value,':' );
    147                final boolean isHM = val.length() <= 4 ;                // 6.2.2.3 (2015/04/10) バグ修正
    148
    149                try {
    150                        //                        HHmm    HHmmss
    151        //              final int hms = ( isHM ? 10000 : 1000000 ) + Integer.parseInt( value );
    152                        final int hms = ( isHM ? 10000 : 1000000 ) + Integer.parseInt( val );           // 6.2.2.3 (2015/04/10) バグ修正
    153
    154                        // 元の形式に準拠して返す。
    155                        return String.valueOf( hms ).substring( 1 );
    156                }
    157                catch( final NumberFormatException ex ) {
    158                        return val;             // 6.2.2.3 (2015/04/10) 一応、":" 削除後の文字列を返す。
    159                }
    160        }
    161
    162        /**
    163         * データが登録可能かどうかをチェックします。
    164         * データがエラーの場合は、そのエラー内容を返します。
    165         *
    166         * @og.rev 5.2.3.6 (2012/01/20) 数値のみに限定するために追加
    167         * @og.rev 5.6.0.3 (2012/01/24) ADD に、引数の値を加算する機能を追加します。
    168         * @og.rev 6.2.2.2 (2015/04/03) 桁数可変に対応
    169         * @og.rev 6.8.4.1 (2017/12/18) 24時間以上の表記に対応するため、isStrict属性を加味します。
    170         * @og.rev 7.2.5.1 (2020/06/05) 数値変換エラーの前にチェックを入れます。
    171         *
    172         * @param   key         キー
    173         * @param   value       値
    174         * @param   sizeX       整数部分の文字列の長さ
    175         * @param   sizeY       小数部分の文字列の長さ
    176         * @param   typeParam   dbType パラメータ(文字パラメータ)
    177         * @param   isStrict    厳密にチェックするかどうか[true:する/false:標準的]
    178         *
    179         * @return  エラー内容
    180         * @og.rtnNotNull
    181         */
    182        @Override
    183        public ErrorMessage valueCheck( final String key ,final String value ,
    184                                                                        final int sizeX ,final int sizeY ,final String typeParam ,final boolean isStrict) {
    185                final String checkVal = valueSet(value); // ：は念のため外しておく
    186
    187                final ErrorMessage msg = new ErrorMessage();
    188                if( checkVal == null || checkVal.isEmpty() ) { return msg; }
    189
    190                final int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1;
    191                if( isStrict ) {
    192                        if( len != checkVal.length() ) {
    193                                // 文字列の長さが指定の長さと異なります。
    194                                msg.addMessage( 0,ErrorMessage.NG,"ERR0011", key,value, String.valueOf( value.length() ), String.valueOf( len ) );
    195                        }
    196                }
    197                else {
    198                        if( len < checkVal.length() ) {
    199                                // 文字列の長さが指定の長さよりも長いです。
    200                                msg.addMessage( 0,ErrorMessage.NG,"ERR0006",key,value,
    201                                                                                String.valueOf( value.length() ),String.valueOf( len ) );
    202                        }
    203                }
    204
    205                // 7.2.5.1 (2020/06/05) 文字の範囲チェックは、ymdFormatCheck の中で行っている。
    206//              // 5.6.0.3 (2012/01/24) 文字の範囲チェック
    207//              String check = DBTypeCheckUtil.rangeCheck( checkVal, '0', '9' );
    208//              if( check != null ) {
    209//                      // 指定の文字以外の文字が使われています。
    210//                      msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check );
    211//              }
    212
    213                String check = null;
    214                // 6.8.4.1 (2017/12/18) 24時間以上の表記に対応するため、isStrict属性を加味します。
    215                if( isStrict ) {
    216                        // 5.6.0.3 (2012/01/24) 時分秒の整合性チェック
    217                        check = DBTypeCheckUtil.hmsFormatCheck( checkVal );
    218                        if( check != null ) {
    219                                // 指定の文字以外の文字が使われています。
    220                                msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check );
    221                        }
    222                }
    223                else {
    224                        check = DBTypeCheckUtil.rangeCheck( checkVal, '0', '9' );
    225                        if( check != null ) {
    226                                // 指定の文字以外の文字が使われています。
    227                                msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check );
    228                        }
    229                }
    230
    231                // 3.6.0.0 (2004/09/22) dbType パラメータ(文字パラメータ)を使用したマッチチェック
    232                check = DBTypeCheckUtil.matcheCheck( checkVal,typeParam );
    233                if( check != null ) {
    234                        // 指定の文字以外の文字が使われています。
    235                        msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check );
    236                }
    237
    238                return msg;
    239        }
    240}