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.fukurou.util; 017 018 import java.io.UnsupportedEncodingException; 019 import java.util.List; 020 import java.util.ArrayList; 021 import java.util.Arrays; 022 023 /** 024 * FixLengthData.java は、固定長??タを作?するための簡易クラスです? 025 * 026 * ??タの?(String[])を?それぞれの中で?桁数にあわせて、スペ?ス埋めします? 027 * ??目間に、追?るスペ?ス数は、setAddLength( int[] ) メソ?で? 028 * ??目のタイ?半角文字?全角混在、数?の??、setType( int[] ) メソ?行います? 029 * 030 * こ?クラスは同期処??保障されて?せん? 031 * 032 * @og.rev 5.6.6.0 (2013/07/05) keys の整合?チェ?を追? 033 * 034 * @version 4.0 035 * @author Kazuhiko Hasegawa 036 * @since JDK5.0, 037 */ 038 public final class FixLengthData { 039 040 /** ?タイプ?定義変数?X:半角文?{@value} */ 041 public static final int X = 0 ; 042 /** ?タイプ?定義変数?S:数?前空白) {@value} */ 043 public static final int S = 1 ; // 5.6.6.0 (2013/07/05) 前空白詰めに変更 044 /** ?タイプ?定義変数?K:半角?角混在 {@value} */ 045 public static final int K = 2 ; 046 /** ?タイプ?定義変数?X9:数?前ゼロ) {@value} */ 047 public static final int S0 = 3 ; // 5.6.6.0 (2013/07/05) 前ゼロ詰めを変更 048 049 /** ?間空白配?の定義変数?T:タブ区? {@value} */ 050 public static final int T = -1 ; // 5.6.6.0 (2013/07/05) タブ区? 051 public static final int T2 = -2 ; // 5.6.6.0 (2013/07/05) タブ区? 052 public static final int T3 = -3 ; // 5.6.6.0 (2013/07/05) タブ区? 053 public static final int T4 = -4 ; // 5.6.6.0 (2013/07/05) タブ区? 054 055 private static final String[] TAB = new String[] { "","\t","\t\t","\t\t\t","\t\t\t\t" }; 056 057 private static final String CR = System.getProperty("line.separator"); 058 059 /** 初期 ENCODE ?{@value} */ 060 public static final String ENCODE = "Windows-31J" ; 061 062 private final int[] addLen ; // ?ータ間に追?るスペ?スを設定する? 063 private final int[] type ; // ?ータの固定長形式? 0:半角文?1:数?前空白) 2:半角?角混在 3:数?前ゼロ) 064 private final int size ; // ??タの個数 065 // private String encode = ENCODE; // 5.6.6.0 (2013/07/05) ? 066 067 private int[] maxLen = null; // ?変数。各??タの?長を記?する? 068 private String[] fill_X = null; // スペ?スの?? 069 private String[] fill_S = null; // ゼロの?? 070 private String[] addSpc = null; // ?変数。addLen で?された?数??空白を管?ます? 071 private final List<String[]> list = new ArrayList<String[]>(); 072 073 /** 074 * ??タの?数を指定して、オブジェクトを構築します? 075 * 076 * @og.rev 5.6.6.0 (2013/07/05) addLen の代わりに、addSpc で管?ます? 077 * 078 * @param len ??タの?数 079 */ 080 public FixLengthData( final int len ) { 081 size = len ; 082 addLen = new int[size]; 083 type = new int[size]; 084 maxLen = new int[size]; 085 } 086 087 /** 088 * ?間空白配?と??目のタイプ?列を?して、オブジェクトを構築します? 089 * どちらも、int型?列なので??番に注意してください? 090 * 091 * @og.rev 5.6.6.0 (2013/07/05) 新規追? 092 * 093 * @param inAddLen ??タの?間空白配? 094 * @param inType ??タの??目のタイプ?? 095 * @see #setAddLength( int[] ) 096 * @see #setType( int[] ) 097 * @throws IllegalArgumentException 引数?null の場? 098 */ 099 public FixLengthData( final int[] inAddLen,final int[] inType ) { 100 if( inAddLen == null || inType == null ) { 101 String errMsg = "?間空白配? また???目のタイプ?列に、null は、指定できません?; 102 throw new IllegalArgumentException( errMsg ); 103 } 104 105 size = inAddLen.length ; 106 107 addLen = new int[size]; 108 type = new int[size]; 109 maxLen = new int[size]; 110 111 setAddLength( inAddLen ); 112 setType( inType ); 113 } 114 115 /** 116 * ??タの全角混在時に??長を算?するのに使用する エンコード方式を?します? 117 * 固定長では、基本?は、?角2Byte 半角1Byte で換算すべきです? 118 * 設定?が?null また?、ゼロ??の場合?、NullPointerException ?throw されます? 119 * 初期値は?Windows-31J" です? 120 * 121 * @og.rev 5.6.6.0 (2013/07/05) ?。基本?外部からエンコード指定する??な?? 122 * 123 * @param encode 全角混在時?固定長?数算?エンコー? 124 * @throws IllegalArgumentException 引数?null また?、ゼロ??の場? 125 */ 126 // public void setEncode( final String encode ) { 127 // if( encode == null || encode.length() == 0 ) { 128 // String errMsg = "エンコードに、null また?、ゼロ??は、指定できません?; 129 // throw new IllegalArgumentException( errMsg ); 130 // } 131 // 132 // this.encode = encode; 133 // } 134 135 /** 136 * ??タの?に対応した?固定時の間に挿入する空白?数を指定します? 137 * 初期値は? です? 138 * 139 * @og.rev 5.6.6.0 (2013/07/05) addLen の代わりに、addSpc で管?ます? 140 * 141 * @param inAddLen ??タの?間空白配? 142 * @throws IllegalArgumentException 引数の??タ件数が?コンストラクタで?した数と異なる?? 143 */ 144 public void setAddLength( final int[] inAddLen ) { 145 int len = (inAddLen == null) ? 0 : inAddLen.length ; 146 if( len != size ) { 147 String errMsg = "引数の??タ件数が?コンストラクタで?した数と異なります?" 148 + "SIZE=[" + size + "] , 引数長=[" + len + "]" ; 149 throw new IllegalArgumentException( errMsg ); 150 } 151 152 System.arraycopy( inAddLen,0,addLen,0,size ); 153 } 154 155 /** 156 * ??タの??目のタイ?半角文字?数?を指定します? 157 * X:半角文字?場合?、データを前方に、余った?を後方にスペ?スを埋めます? 158 * S:数?前空白)の場合?、データを後方に、余った?を空白を前方に埋めます? 159 * S0:数?前ゼロ)の場合?、データを後方に、余った?をゼロを前方に埋めます? 160 * K:半角?角混在の場合?、ENCODE(Windows-31J) で?数を求めるとともに、X:半角文字と同様?処?行います? 161 * 初期値は、X:半角文?です? 162 * 163 * @param inType ??タの??目のタイプ?? 164 * @see #X 165 * @see #S 166 * @see #S0 167 * @see #K 168 * @throws IllegalArgumentException 引数の??タ件数が?コンストラクタで?した数と異なる?? 169 */ 170 public void setType( final int[] inType ) { 171 int len = (inType == null) ? 0 : inType.length ; 172 if( len != size ) { 173 String errMsg = "引数の??タ件数が?コンストラクタで?した数と異なります?" 174 + "SIZE=[" + size + "] , 引数長=[" + len + "]" ; 175 throw new IllegalArgumentException( errMsg ); 176 } 177 178 System.arraycopy( inType,0,type,0,size ); 179 } 180 181 /** 182 * ??タの??目に対応した?列データを設定します? 183 * 配???タを登録しながら、各?の???タ長をピ?ア??して?ます? 184 * 185 * @param inData ??タの??目の配???タ 186 * @throws IllegalArgumentException 引数の??タ件数が?コンストラクタで?した数と異なる?? 187 */ 188 public void addListData( final String[] inData ) { 189 int len = (inData == null) ? 0 : inData.length ; 190 if( len != size ) { 191 String errMsg = "引数の??タ件数が?コンストラクタで?した数と異なります?" 192 + "SIZE=[" + size + "] , 引数長=[" + len + "]" ; 193 throw new IllegalArgumentException( errMsg ); 194 } 195 196 // ???タ長の取得?み行っておきます? 197 try { 198 for( int i=0; i<size; i++ ) { 199 if( inData[i] != null ) { 200 if( type[i] == K ) { 201 len = inData[i].getBytes( ENCODE ).length ; 202 } 203 else { 204 len = inData[i].length(); 205 } 206 if( maxLen[i] < len ) { maxLen[i] = len; } 207 } 208 } 209 } 210 catch( UnsupportedEncodingException ex ) { 211 String errMsg = "??タの変換に失敗しました?" + ENCODE + "]" ; 212 throw new RuntimeException( errMsg,ex ); 213 } 214 list.add( inData ); 215 } 216 217 /** 218 * ??行に対する固定文字数に設定された??を返します? 219 * 引数の行番号は、addListData(String[])メソ?で登録された?番です? 220 * 221 * @og.rev 5.6.6.0 (2013/07/05) addLen の代わりに、addSpc で管?ます? 222 * 223 * @param line 行番号(addListData で登録した? 224 * 225 * @return 固定文字数に設定された?? 226 */ 227 public String getFixData( final int line ) { 228 if( fill_X == null ) { makeSpace(); } // 初期処? 229 230 String[] data = list.get( line ); 231 StringBuilder rtn = new StringBuilder(); 232 for( int i=0; i<size; i++ ) { 233 String dt = ( data[i] == null ) ? "" : data[i] ; 234 switch( type[i] ) { 235 case X: // ?を出力してから、スペ?スで埋める? 236 rtn.append( dt ); 237 rtn.append( fill_X[i].substring( dt.length() ) ); 238 break; 239 case S: // 空白で埋めてから、文字を出力する? 240 rtn.append( fill_X[i].substring( dt.length() ) ); 241 rtn.append( dt ); 242 break; 243 case S0: // ゼロで埋めてから、文字を出力する? 244 rtn.append( fill_S[i].substring( dt.length() ) ); 245 rtn.append( dt ); 246 break; 247 case K: // 全角を含?字を出力してから、スペ?スで埋める? 248 try { 249 int len = dt.getBytes( ENCODE ).length ; 250 rtn.append( dt ); 251 rtn.append( fill_X[i].substring( len ) ); 252 } 253 catch( UnsupportedEncodingException ex ) { 254 String errMsg = "??タの変換に失敗しました?" + ENCODE + "]" ; 255 throw new RuntimeException( errMsg,ex ); 256 } 257 break; 258 default: // 基本?ありえな? 259 String errMsg = "不正な種別が指定されました[" + type[i] + "]" ; 260 throw new RuntimeException( errMsg ); 261 // break; 262 } 263 rtn.append( addSpc[i] ); // 5.6.6.0 (2013/07/05) ?間?スペ?スを?? 264 } 265 return rtn.toString(); 266 } 267 268 /** 269 * ??タの??目に対応した?列データを?すべて設定します? 270 * ここでは??列?配?型データを受け取り???、addListData( String[] )? 271 * 実行して?す? 272 * 簡易的なメソ?です? 273 * 274 * @og.rev 5.6.6.0 (2013/07/05) 新規追? 275 * 276 * @param inData ??タの??目の配???タの配? 277 * @see #addListData( String[] ) 278 * @throws IllegalArgumentException 引数の??タ件数が?コンストラクタで?した数と異なる?? 279 */ 280 public void addAllListData( final String[][] inData ) { 281 for( int i=0; i<inData.length; i++ ) { 282 addListData( inData[i] ); 283 } 284 } 285 286 /** 287 * ?登録済みのすべての??タを?結して出力します? 288 * 連結時には、改行コードを設定して?す? 289 * 290 * @og.rev 5.6.6.0 (2013/07/05) getAllFixData( StringBuilder ) を使用するように?処?変更 291 * 292 * @return 固定文字数に設定された?? 293 * @see #getFixData( int ) 294 * @see #getAllFixData( StringBuilder ) 295 */ 296 public String getAllFixData() { 297 return getAllFixData( new StringBuilder( 1000 ) ).toString(); 298 299 // StringBuilder buf = new StringBuilder( 1000 ); 300 // 301 // int len = list.size(); 302 // for( int i=0; i<len; i++ ) { 303 // buf.append( getFixData( i ) ).append( CR ); 304 // } 305 // 306 // return buf.toString(); 307 } 308 309 /** 310 * ?登録済みのすべての??タを引数のStringBuilderに連結して返します? 311 * 連結時には、改行コードを設定して?す? 312 * return オブジェクト?、この引数と同??オブジェクトです? 313 * 314 * @og.rev 5.6.6.0 (2013/07/05) 新規追? 315 * 316 * @param buf 連結に使用する StringBuilder 317 * @return 固定文字数に設定された StringBuilder(入力と同じ) 318 * @see #getFixData( int ) 319 * @see #getAllFixData() 320 */ 321 public StringBuilder getAllFixData( final StringBuilder buf ) { 322 int len = list.size(); 323 for( int i=0; i<len; i++ ) { 324 buf.append( getFixData( i ) ).append( CR ); 325 } 326 327 return buf; 328 } 329 330 /** 331 * 固定文字?を作?するための種となるスペ?ス??とゼロ??を作?します? 332 * 333 * @og.rev 5.6.6.0 (2013/07/05) addLen の代わりに、addSpc で管?ます? 334 */ 335 private void makeSpace() { 336 fill_X = new String[size]; 337 fill_S = new String[size]; 338 addSpc = new String[size]; 339 char[] ch ; 340 341 int startCnt = 0; // 先?からの?数 342 for( int i=0; i<size; i++ ) { 343 // char[] ch = new char[maxLen[i]+addLen[i]]; 344 // addLen に、T(タ?が指定された場合?addSpc は?の倍数になるよ?調整する? 345 startCnt += maxLen[i]; 346 int addCnt = addLen[i] ; 347 if( addCnt < 0 ) { // T,T2,T3,T4 のケース 348 // addSpc[i] = TAB[-addCnt]; 349 addCnt = (-4*addCnt) - (startCnt % 4); // TAB数に合わせたスペ?スに換算した数 350 } 351 // else { 352 ch = new char[addCnt]; 353 Arrays.fill( ch, ' ' ); 354 addSpc[i] = String.valueOf( ch ); 355 // } 356 startCnt += addCnt ; 357 358 ch = new char[maxLen[i]]; 359 switch( type[i] ) { 360 case S0: 361 Arrays.fill( ch, '0' ); 362 fill_S[i] = String.valueOf( ch ); 363 break; 364 case X: 365 case S: 366 case K: 367 Arrays.fill( ch, ' ' ); 368 fill_X[i] = String.valueOf( ch ); 369 break; 370 default: // 基本?ありえな? 371 String errMsg = "不正な種別が指定されました[" + type[i] + "]" ; 372 throw new RuntimeException( errMsg ); 373 // break; 374 } 375 } 376 } 377 378 /** 379 * ?変数の??タと、最大値のキャ?ュをクリアします? 380 * 381 * それ以外?変数(size、addLength、type)は、設定時のまま残って?す? 382 * 383 */ 384 public void clear() { 385 list.clear() ; 386 maxLen = new int[size]; 387 fill_X = null; // スペ?スの?? 388 fill_S = null; // ゼロの?? 389 addSpc = null; // ?間空白 390 } 391 }