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.db; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.fukurou.util.StringUtil; 020 021/** 022 * DBカラムの属性チェックに使用されるメソッドを集約した、クラスです。 023 * 024 * 全変数は、public static final 宣言されており、全メソッドは、public static synchronized 宣言されています。 025 * 026 * @og.group データ属性 027 * 028 * @version 4.0 029 * @author Kazuhiko Hasegawa 030 * @since JDK5.0, 031 */ 032public final class DBTypeCheckUtil { 033 /** String を Byte[]に変換するコード 034 * 例:) "MS932" , "JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS" 035 */ 036 private static final String CODE = HybsSystem.sys( "DB_ENCODE" ); 037 038 // 5.3.9.0 (2011/09/01) 文字数チェック方式の指定 039 private static final boolean USE_TEXT_LEN ; 040 static { 041 String useTextLen = HybsSystem.sys( "DB_USE_TEXT_LENGTH" ); 042 if( useTextLen != null ) { 043 USE_TEXT_LEN = Boolean.valueOf( useTextLen ).booleanValue(); 044 } 045 else { 046 USE_TEXT_LEN = false; 047 } 048 } 049 050 /** 051 * オブジェクトを作らせない為の、private コンストラクタ 052 */ 053 private DBTypeCheckUtil() {} 054 055 /** 056 * 文字列に使われている文字の範囲チェックを行います。 057 * 058 * 最小文字から最大文字、および、許可される文字を指定します。 059 * それ以外は、エラーと判定されます。 060 * ここで判定される以外に細かい制限をかけたい場合は、別のチェックと併用してください。 061 * 062 * @og.rev 5.6.0.3 (2012/01/24) 新規追加 063 * 064 * @param value 元の文字列 065 * @param minCh 許可される文字の最小値(含む) 066 * @param maxCh 許可される文字の最大値(含む) 067 * 068 * @return 範囲チェックエラー文字列(正常時は、null) 069 */ 070 public static String rangeCheck( final String value ,final char minCh ,final char maxCh ) { 071 StringBuilder val = new StringBuilder(); 072 boolean isError = false; 073 for( int i=0; i<value.length(); i++ ) { 074 char ch = value.charAt( i ); 075 if( minCh <= ch && ch <= maxCh ) { 076 val.append( ch ); 077 } 078 else { 079 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 080 isError = true; 081 } 082 } 083 084 return ( isError ? val.toString() : null ); 085 } 086 087 /** 088 * 文字列の長さ(整数部)をチェックします。 089 * 090 * @param value 元の文字列 091 * @param sizeX 整数部分の文字列の長さ 092 * @param sizeY 少数部分の文字列の長さ 093 * 094 * @return エラー文字列長さ(正常時は、null) 095 */ 096 public static String sizeXCheck( final String value ,final int sizeX ,final int sizeY ) { 097 int valuesizeX; 098 int pos = value.indexOf( '.' ); 099 if( pos >= 0 ) { 100 valuesizeX = pos; 101 } 102 else { 103 valuesizeX = value.length(); 104 } 105 if( value.charAt(0) == '-' ) { valuesizeX--; } 106 107 if( valuesizeX > sizeX ) { 108 // 整数部の長さが指定の長さよりも長いです。 109 return String.valueOf(valuesizeX); 110 } else { 111 return null; 112 } 113 } 114 115 /** 116 * 文字列の長さ(小数部)をチェックします。 117 * 118 * @param value 元の文字列 119 * @param sizeX 整数部分の文字列の長さ 120 * @param sizeY 少数部分の文字列の長さ 121 * 122 * @return エラー文字列長さ(正常時は、null) 123 */ 124 public static String sizeYCheck( final String value ,final int sizeX ,final int sizeY ) { 125 if( sizeY == 0 ) { 126 return null; 127 } 128 int valuesizeY; 129 int pos = value.indexOf( '.' ); 130 if( pos >= 0 ) { 131 valuesizeY = value.length() - pos - 1; 132 } 133 else { 134 valuesizeY = 0; 135 } 136 137 if( valuesizeY > sizeY ) { 138 // 少数部の長さが指定の長さよりも長いです。 139 return String.valueOf(valuesizeY); 140 } else { 141 return null; 142 } 143 } 144 145 /** 146 * 文字列の小数点の位置をチェックします。 147 * 小数点(.)が、2箇所以上存在する(存在する位置が異なる)場合エラー 148 * 149 * @param value 元の文字列 150 * 151 * @return エラー文字列(正常時は、null) 152 */ 153 public static String decimalPointCheck( final String value ) { 154 String rtn = null; 155 if( value.indexOf( '.' ) != value.lastIndexOf( '.' ) ) { 156 rtn = changeErrorPath( value, '.' ); 157 } 158 return rtn ; 159 } 160 161 /** 162 * 文字列の符号の位置をチェックします。 163 * マイナス(-)が、存在しないか、先頭以外の場合は、エラー 164 * 165 * @param value 元の文字列 166 * 167 * @return エラー文字列(正常時は、null) 168 */ 169 public static String decimalCodeCheck( final String value ) { 170 String rtn = null; 171 if( value.lastIndexOf( '-' ) > 0 ) { 172 rtn = changeErrorPath( value, '-' ); 173 } 174 return rtn ; 175 } 176 177 /** 178 * 文字列の整合性(整数)をチェックします。 179 * 0〜9およびマイナス(-)を許可します。 180 * 181 * @param value 元の文字列 182 * 183 * @return エラー文字列(正常時は、null) 184 */ 185 public static String numberFormatCheck( final String value ) { 186 boolean isError = false; 187 int i = 0; 188 char ch; 189 while( i<value.length() ) { 190 ch = value.charAt( i ); 191 if( ( '0'>ch || '9'<ch ) && ( '-'!=ch ) ) { 192 isError = true; 193 break; 194 } 195 i++; 196 } 197 if( isError ) { 198 StringBuilder val = new StringBuilder(); 199 for( i=0; i<value.length(); i++ ) { 200 ch = value.charAt( i ); 201 if( ( '0'>ch || '9'<ch ) && ( '-'!=ch ) ) { 202 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 203 } 204 else { 205 val.append( ch ); 206 } 207 } 208 return val.toString(); 209 } else { 210 return null; 211 } 212 } 213 214 /** 215 * 文字列の整合性(小数)をチェックします。 216 * 0〜9、マイナス(-)および小数点(.)を許可します。 217 * 218 * og.rev 4.2.4.0 (2008/06/26) '.' or '-' のみはエラー 219 * 220 * @param value 元の文字列 221 * 222 * @return エラー文字列(正常時は、null) 223 */ 224 public static String decimalFormatCheck( final String value ) { 225 boolean isError = false; 226 int i = 0; 227 char ch; 228 while( i<value.length() ) { 229 ch = value.charAt( i ); 230 if( ( '0'>ch || '9'<ch ) && ( '.'!=ch ) && ( '-'!=ch ) ) { 231 isError = true; 232 break; 233 } 234 i++; 235 } 236 237 // 4.2.4.0 (2008/06/26) '.' or '-' のみはエラー 238 if( ( value.length() ==1 ) && ( value.charAt( 0 ) == '.' || value.charAt( 0 ) == '-' ) ) { 239 isError = true; 240 } 241 242 if( isError ) { 243 StringBuilder val = new StringBuilder(); 244 for( i=0; i<value.length(); i++ ) { 245 ch = value.charAt( i ); 246 if( ( '0'>ch || '9'<ch ) && ( '.'!=ch ) && ( '-'!=ch ) ) { 247 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 248 } 249 else { 250 val.append( ch ); 251 } 252 } 253 return val.toString(); 254 } else { 255 return null; 256 } 257 } 258 259 /** 260 * 日付文字列の整合性をチェックします。 261 * 262 * 整合性といっても、DBType_DATE のような厳密なチェックは、行いません。 263 * ここでは、yyyyMM(6桁)、yyyyMMdd(8桁)、yyyyMMddHHmmss(14桁) の3種類のみ 264 * 対象にします。 265 * "0000XXXX" , "9999XXXX" は、常に許可されます。 266 * 月と日の関係も、ありません。(20130231 は OK) 267 * あくまで、月は、1〜12 の範囲、日は、1〜31の範囲チェックです。 268 * 269 * 厳密な日付チェックを行いたい場合は、DBType_DATE を使用してください。 270 * 271 * @og.rev 5.6.0.3 (2012/01/24) 新規追加 272 * 273 * @param value 元の文字列(nullは不可) 274 * 275 * @return エラー文字列(正常時は、null) 276 */ 277 public static String ymdFormatCheck( final String value ) { 278 if( value.startsWith( "0000" ) || value.startsWith( "9999" ) ) { return null; } // 無条件 OK 279 280 int len = value.length() ; 281 if( len >= 6 ) { // 月のチェック 282 String val = ymdhmsCheck( value,4,6,1,12 ); 283 if( val != null ) { return val; } 284 } 285 286 if( len >= 8 ) { // 日のチェック 287 String val = ymdhmsCheck( value,6,8,1,31 ); 288 if( val != null ) { return val; } 289 } 290 291 if( len >= 10 ) { // 時のチェック 292 String val = ymdhmsCheck( value,8,10,0,24 ); // 240000 は許可します。 293 if( val != null ) { return val; } 294 } 295 296 if( len >= 12 ) { // 分のチェック 297 String val = ymdhmsCheck( value,10,12,0,60 ); // 60分は許可します。 298 if( val != null ) { return val; } 299 } 300 301 if( len == 14 ) { // 秒のチェック 302 String val = ymdhmsCheck( value,12,14,0,60 ); // うるう秒とは言いませんが、60秒は許可します。 303 if( val != null ) { return val; } 304 } 305 306 return null; 307 } 308 309 /** 310 * 時刻文字列の整合性をチェックします。 311 * 312 * 整合性といっても、DBType_DATE のような厳密なチェックは、行いません。 313 * ここでは、HHmmss(6桁) のみ対象にします。 314 * 315 * @og.rev 5.6.0.3 (2012/01/24) 新規追加 316 * 317 * @param value 元の文字列(nullは不可) 318 * 319 * @return エラー文字列(正常時は、null) 320 */ 321 public static String hmsFormatCheck( final String value ) { 322 int len = value.length() ; 323 324 if( len >= 2 ) { // 時のチェック 325 String val = ymdhmsCheck( value,0,2,0,24 ); // 240000 は許可します。 326 if( val != null ) { return val; } 327 } 328 329 if( len >= 4 ) { // 分のチェック 330 String val = ymdhmsCheck( value,2,4,0,60 ); // 60分は許可します。 331 if( val != null ) { return val; } 332 } 333 334 if( len == 6 ) { // 秒のチェック 335 String val = ymdhmsCheck( value,4,6,0,60 ); // うるう秒とは言いませんが、60秒は許可します。 336 if( val != null ) { return val; } 337 } 338 339 return null; 340 } 341 342 /** 343 * 月、日、時、分、秒 のチェック用メソッド 344 * 345 * 同じようなパターンでチェックする為、共通メソッド化しておきます。 346 * 347 * @param value 元の文字列 348 * @param st チェック開始桁数 349 * @param ed チェック終了桁数 (val.length() を超えない事) 350 * @param minSu 許可範囲の最小値 351 * @param maxSu 許可範囲の最大値 352 * 353 * @return エラー文字列(正常な場合は、null) 354 */ 355 public static String ymdhmsCheck( final String value, final int st , final int ed , final int minSu , final int maxSu ) { 356 String rtn = null; 357 358 int dt = Integer.parseInt( value.substring( st,ed ) ); 359 if( dt < minSu || maxSu < dt ) { 360 rtn = value.substring( 0,st ) + "<span class=\"NG\">" + value.substring( st,ed ) + "</span>" + value.substring( ed ) ; 361 } 362 return rtn; 363 } 364 365 /** 366 * 文字列のエラー文字列を返します。 367 * 368 * @param val 元の文字列 369 * @param inChar エラー対象文字 370 * 371 * @return エラー文字列 372 */ 373 private static String changeErrorPath( final String val, final char inChar ) { 374 StringBuilder buf = new StringBuilder(); 375 for( int i=0; i<val.length(); i++ ) { 376 char ch = val.charAt( i ); 377 if( inChar==ch ) { 378 buf.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 379 } else { 380 buf.append( ch ); 381 } 382 } 383 return buf.toString(); 384 } 385 386 /** 387 * 文字列の長さをチェックします。 388 * バイト数に換算して比較チェックします。 389 * 390 * @og.rev 3.0.1.3 (2003/03/11) メソッド新規追加 391 * @og.rev 3.5.5.3 (2004/04/09) StringUtil の CODE を使用したメソッドを削除する。 392 * @og.rev 5.3.9.0 (2011/09/01) DB_USE_TEXT_LENGTH を考慮した、「文字数」、「バイト数」チェック 393 * 394 * @param value 元の文字列 395 * @param len 文字列の長さ 396 * 397 * @return エラー文字列(正常時は、null) 398 */ 399 public static String byteLengthCheck( final String value ,final int len ) { 400 String rtn = null; 401 402 // 5.3.9.0 (2011/09/01) 「文字数」、「バイト数」チェック 403 final int valLen ; 404 if( USE_TEXT_LEN ) { // true:「文字数」チェック方式 405 valLen = value.length(); 406 } 407 else { // false:「バイト数」チェック方式 408 byte[] byteValue = StringUtil.makeByte( value,CODE ); // 3.5.5.3 (2004/04/09) 409 valLen = byteValue.length; 410 } 411 412// byte[] byteValue = StringUtil.makeByte( value,CODE ); // 3.5.5.3 (2004/04/09) 413 414// if( byteValue.length > len ) { 415// rtn = String.valueOf( byteValue.length ); 416// } 417 418 if( valLen > len ) { 419 rtn = String.valueOf( valLen ); 420 } 421 422 return rtn ; 423 } 424 425 /** 426 * 文字列の整合性を、dbType パラメータを利用してチェックします。 427 * regex が、null または、長さゼロの文字列の場合は、なにもしません。 428 * 429 * @og.rev 3.6.0.0 (2004/09/22) 新規作成 430 * 431 * @param value 元の文字列 432 * @param regex チェックする正規表現文字列 433 * 434 * @return エラー文字列(正常時は、null) 435 */ 436 public static String matcheCheck( final String value,final String regex ) { 437 if( regex == null || regex.length() == 0 ) { return null; } 438 439 if( value.matches( regex ) ) { 440 return null; 441 } 442 else { 443 return "<span class=\"NG\">" + value + "</span> regex=" + regex ; 444 } 445 } 446}