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 }