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 }