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.fukurou.model.NativeType; 019import org.opengion.fukurou.util.ErrorMessage; 020import org.opengion.fukurou.util.StringUtil; 021 022/** 023 * 一般的な半角文字列を扱う為の、カラム属性を定義します。 024 * 025 * 半角文字列とは、「 c < 0x20 || c > 0x7e 以外」でのみ 026 * 構成された文字列のことです。 027 * 028 * タイプチェックとして、以下の条件を判定します。 029 * ・文字列長は、Byte換算での文字数との比較 030 * ・半角文字列チェック「 c < 0x20 || c > 0x7e 以外」エラー 031 * ・文字パラメータの 正規表現チェック 032 * ・クロスサイトスクリプティングチェック 033 * 034 * @og.group データ属性 035 * 036 * @version 4.0 037 * @author Kazuhiko Hasegawa 038 * @since JDK5.0, 039 */ 040public abstract class AbstractDBType implements DBType { 041 042 private final String defValue ; // データのデフォルト値 043 044 /** 045 * デフォルトコンストラクター 046 * 047 * @og.rev 4.0.0.0 (2005/01/31) type 廃止 048 */ 049 public AbstractDBType() { 050 this( "" ); // データのデフォルト値 051 } 052 053 /** 054 * コンストラクター 055 * 056 * 各サブクラスのタイプ値とデフォルト値を設定して、オブジェクトを構築します。 057 * 058 * @og.rev 4.0.0.0 (2005/01/31) type 廃止 059 * 060 * @param defValue データのデフォルト値 061 */ 062 public AbstractDBType( final String defValue ) { 063 this.defValue = defValue; 064 } 065 066 /** 067 * NATIVEの型の識別コードを返します。 068 * 069 * @og.rev 3.5.4.7 (2004/02/06) 新規作成 070 * @og.rev 4.1.1.2 (2008/02/28) Enum型(fukurou.model.NativeType)に変更 071 * 072 * @return NATIVEの型の識別コード(DBType で規定) 073 * @see org.opengion.fukurou.model.NativeType 074 */ 075 public NativeType getNativeType() { 076// return NATIVE_STRING; 077 return NativeType.STRING; 078 } 079 080 /** 081 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 082 * 083 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 084 * なお、エラーチェックは行われません。 085 * 実行前に、必ず valueCheck( String value ,int len ) を行う必要があります。 086 * 087 * @og.rev 3.5.4.5 (2004/01/23) エンコード指定に変更します。 088 * 089 * @param value FILL埋めする文字列 090 * @param sizeX 整数部分の文字列の長さ 091 * @param sizeY 少数部分の文字列の長さ 092 * @param encode 固定長で変換する文字エンコード 093 * 094 * @return FILL埋めした新しい文字列 095 */ 096 public String valueFill( final String value ,final int sizeX ,final int sizeY,final String encode ) { 097 int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1; 098 099 return StringUtil.stringFill( value,len,encode ); 100 } 101 102 /** 103 * そのDBTypeの,デフォルトの値(物理的初期設定値)を返します。 104 * 105 * 一般に、文字列の場合は,ゼロストリング"" 数字の場合は "0" です。 106 * 107 * @return 物理的初期設定値 108 */ 109 public String getDefault() { 110 return defValue; 111 } 112 113 /** 114 * String引数の文字列を+1した文字列を返します。 115 * 116 * これは、英字の場合(A,B,C など)は、B,C,D のように,最終桁の文字コードを 117 * +1 します。 118 * 文字列が数字タイプの場合は, 数字に変換して、+1 します。 119 * 最終桁が、"9","z","Z" および、その全角文字の場合、"0","a","Z" および、その全角文字に 120 * 変換後、ひとつ上の桁で、同様の +1 操作を行います。 121 * 最も上位の桁が、これらの繰り上がり桁の場合は、すべての桁が初期化された状態に戻ります。 122 * 例:123 ⇒ 124 , ABC ⇒ ABD , 789 ⇒ 790 , XYZ ⇒ XXZ , 123 * ABC123 ⇒ ABC124 , AB99 ⇒ AC00 , 12ZZ99 ⇒ 13AA00 , ZZZZ ⇒ AAAA 124 * 引数が null の場合と、ゼロ文字列("")の場合は,物理的初期設定値(String getDefault()) 125 * の値を返します。 126 * 127 * @og.rev 4.0.0.0 (2005/01/31) Addの方法を変更(汎用的なAdd) 128 * 129 * @param value String引数 130 * 131 * @return 引数の文字列を+1した文字列。 132 */ 133 public String valueAdd( final String value ) { 134 if( value == null || value.length() == 0 ) { return getDefault(); } 135 136 char[] chs = value.toCharArray() ; 137 138 for( int i=chs.length-1; i>=0; i-- ) { 139 boolean over = true; 140 switch( chs[i] ) { 141 case '9' : chs[i] = '0' ; break; 142 case 'z' : chs[i] = 'a' ; break; 143 case 'Z' : chs[i] = 'A' ; break; 144 case '9' : chs[i] = '0'; break; 145 case 'z' : chs[i] = 'a'; break; 146 case 'Z' : chs[i] = 'A'; break; 147 default : chs[i]++; over=false; break; 148 } 149 if( !over ) { break; } // キャリーオーバーしていなければ、終了 150 } 151 152 return new String( chs ); 153 } 154 155 /** 156 * String引数の文字列に、第2引数に指定の文字列(数字、日付等)を加算して返します。 157 * 158 * これは、valueAdd( String ) と本質的には同じ動きをしますが、任意の文字列を加算する 159 * ため、主として、数字系や日付系の DBType にのみ実装します。 160 * 実装がない場合は、UnsupportedOperationException を throw します。 161 * 162 * 第2引数 が、null の場合は、+1 する valueAdd( String )が呼ばれます。 163 * これは、将来的には、valueAdd( String ) を無くすことを意味します。 164 * 165 * @og.rev 5.6.0.3 (2012/01/24) ADD に、引数の値を加算する機能を追加します。 166 * 167 * @param value String引数 168 * @param add 加算する文字列(null の場合は、従来と同じ、+1 します。) 169 * 170 * @return 引数の文字列第2引数に指定の文字列(数字、日付等)を加算した文字列。 171 * @throws UnsupportedOperationException 実装が存在しない場合 172 */ 173 public String valueAdd( final String value,final String add ) { 174 if( add == null || add.isEmpty() ) { return valueAdd( value ); } 175 176 String errMsg = "このクラスでは、引数付の任意の加算は実装されていません。" 177 + getClass().getName() + " Action=[ADD]" 178 + " oldValue=[" + value + "] newValue=[" + add + "]" ; 179 throw new UnsupportedOperationException( errMsg ); 180 } 181 182 /** 183 * エディターで編集されたデータを登録する場合に、データそのものを変換して、実登録データを作成します。 184 * 185 * 例えば,大文字のみのフィールドなら、大文字化します。 186 * 実登録データの作成は、DBType オブジェクトを利用しますので, 187 * これと CellEditor とがアンマッチの場合は、うまくデータ変換 188 * されない可能性がありますので、注意願います。 189 * 190 * @og.rev 3.3.3.0 (2003/07/09) 前後のスペースを取り除いておく。 191 * @og.rev 3.3.3.1 (2003/07/18) 後ろスペースを取り除く。(StringUtil#rTrim) 192 * 193 * @param value (一般に編集データとして登録されたデータ) 194 * 195 * @return 修正後の文字列(一般にデータベースに登録するデータ) 196 */ 197 public String valueSet( final String value ) { 198 return StringUtil.rTrim( value ); 199 } 200 201 /** 202 * action で指定されたコマンドを実行して、値の変換を行います。 203 * 204 * oldValue(旧データ)は、元のDBTableModelに設定されていた値です。通常は、 205 * この値を使用してカラム毎に変換を行います。newValue(新データ)は、引数で 206 * 指定された新しい値です。この値には、パラメータを指定して変換方法を 207 * 制御することも可能です。 208 * 指定のアクションがカラムで処理できない場合は、エラーになります。 209 * 210 * @param action アクションコマンド 211 * @param oldValue 入力データ(旧データ) 212 * @param newValue 入力データ(新データ) 213 * 214 * @return 実行後のデータ 215 */ 216 public String valueAction( final String action,final String oldValue,final String newValue ) { 217 String errMsg = "このクラスでは、このアクションは実装されていません。" 218 + getClass().getName() + " Action=[" + action + "]" 219 + " oldValue=[" + oldValue + "] newValue=[" + newValue + "]" ; 220 throw new UnsupportedOperationException( errMsg ); 221 } 222 223 /** 224 * データが登録可能かどうか[true/false]をチェックします。 225 * 226 * データがエラーの場合は、そのエラー内容を返します。 227 * 228 * @og.rev 2.1.1.1 (2002/11/15) HTMLタグチェックのメソッドの共有化。 229 * @og.rev 3.0.1.3 (2003/03/11) DBTypeCheckUtilクラスを利用するように修正 230 * @og.rev 3.6.0.0 (2004/09/22) dbType パラメータを引数に追加 231 * @og.rev 5.2.2.0 (2010/11/01) 厳密にチェック(isStrict=true)するフラグを追加 232 * 233 * @param key キー 234 * @param value 値 235 * @param sizeX 整数部分の文字列の長さ 236 * @param sizeY 少数部分の文字列の長さ 237 * @param typeParam dbType パラメータ 238 * @param isStrict 厳密にチェックするかどうか [true:する/false:標準的] 239 * 240 * @return エラー内容 241 */ 242// public ErrorMessage valueCheck( final String key ,final String value , 243// final int sizeX ,final int sizeY ,final String typeParam ) { 244 public ErrorMessage valueCheck( final String key ,final String value , 245 final int sizeX ,final int sizeY ,final String typeParam ,final boolean isStrict) { 246 247 ErrorMessage msg = new ErrorMessage(); 248 if( value == null || value.length() == 0 ) { return msg; } 249 250 int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1; 251 if( len < value.length() ) { 252 // 文字列の長さが指定の長さよりも長いです。 253 msg.addMessage( 0,ErrorMessage.NG,"ERR0006",key,value, 254 String.valueOf( value.length() ),String.valueOf( len ) ); 255 } 256 257 StringBuilder val = new StringBuilder(); 258 boolean isError = false; 259 for( int i=0; i<value.length(); i++ ) { 260 char ch = value.charAt( i ); 261 if( ch < 0x20 || ch > 0x7e ) { 262 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 263 isError = true; 264 } 265 else { 266 val.append( ch ); 267 } 268 } 269 if( isError ) { 270 // 指定の文字以外の文字が使われています。 271 msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,val.toString() ); 272 } 273 274 // 3.6.0.0 (2004/09/22) dbType パラメータを使用したマッチチェック 275 String check = DBTypeCheckUtil.matcheCheck( value,typeParam ); 276 if( check != null ) { 277 // 指定の文字以外の文字が使われています。 278 msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check ); 279 } 280 281 // クロスサイトスクリプティング対策:'<', '>' は登録させない。 282 msg = xssCheck( key ,value, msg ); 283 return msg; 284 } 285 286 /** 287 * HTMLタグかどうかをチェックします。 288 * 289 * クロスサイトスクリプティング対策として、'<', '>' は登録させない。 290 * 291 * @og.rev 2.1.1.1 (2002/11/15) HTMLタグチェックのメソッドの共有化。 292 * 293 * @param key タグのキー 294 * @param value 対象の値 295 * @param msg ErrorMessageオブジェクト 296 * 297 * @return エラー内容(エラーを追加した、ErrorMessageオブジェクト) 298 */ 299 protected ErrorMessage xssCheck( final String key ,final String value, final ErrorMessage msg ) { 300 StringBuilder val = new StringBuilder(); 301 boolean isError = false; 302 for( int i=0; i<value.length(); i++ ) { 303 char ch = value.charAt( i ); 304 if( ch == '<' || ch == '>' ) { 305 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 306 isError = true; 307 } 308 else { 309 val.append( ch ); 310 } 311 } 312 if( isError ) { 313 // HTMLタグは登録できません。 314 msg.addMessage( 0,ErrorMessage.NG,"ERR0010", key,val.toString() ); 315 } 316 return msg; 317 } 318}