View Javadoc
1   /*
2    * Copyright 2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.orangesignal.csv;
18  
19  import java.io.Serializable;
20  import java.util.regex.Pattern;
21  
22  /**
23   * 区切り文字形式情報を提供します。<p>
24   * このクラスは、区切り文字や囲み文字、エスケープ文字など CSV 形式に関する設定情報を管理します。
25   * 
26   * @author Koji Sugisawa
27   */
28  public class CsvConfig implements Serializable, Cloneable {
29  
30  	private static final long serialVersionUID = -7531286991159010295L;
31  
32  	/**
33  	 * デフォルトの区切り文字 (,) です。
34  	 */
35  	public static final char DEFAULT_SEPARATOR = ',';
36  
37  	/**
38  	 * デフォルトの囲み文字 (") です。
39  	 */
40  	public static final char DEFAULT_QUOTE = '"';
41  
42  	/**
43  	 * デフォルトのエスケープ文字 (\) です。
44  	 */
45  	public static final char DEFAULT_ESCAPE = '\\';
46  
47  	/**
48  	 * デフォルトの先頭から読飛ばす論理行数 ({@value}) です。
49  	 */
50  	public static final int DEFAULT_SKIP_LINES = 0;
51  
52  	/**
53  	 * デフォルトの囲み文字出力方法の種類 ({@link QuotePolicy#ALL}) です。
54  	 * 
55  	 * @since 1.1
56  	 */
57  	public static final QuotePolicy DEFAULT_QUOTE_POLICY = QuotePolicy.ALL;
58  
59  	// ------------------------------------------------------------------------
60  
61  	/**
62  	 * 区切り文字を保持します。
63  	 */
64  	private char separator;
65  
66  	/**
67  	 * 囲み文字を保持します。
68  	 */
69  	private char quote;
70  
71  	/**
72  	 * エスケープ文字を保持します。
73  	 */
74  	private char escape;
75  
76  	/**
77  	 * 囲み文字を無効にするかどうかを保持します。
78  	 */
79  	private boolean quoteDisabled;
80  
81  	/**
82  	 * エスケープ文字を無効にするかどうかを保持します。
83  	 */
84  	private boolean escapeDisabled;
85  
86  	/**
87  	 * 値の改行文字列を置換える文字列を保持します。
88  	 */
89  	private String breakString;
90  
91  	/**
92  	 * 値がないことを表す文字列を保持します。
93  	 */
94  	private String nullString;
95  
96  	/**
97  	 * 値がないことを表す文字列の大文字と小文字を区別するかどうかを保持します。
98  	 */
99  	private boolean ignoreCaseNullString;
100 
101 	/**
102 	 * 値より前のホワイトスペースを除去するかどうかを保持します。
103 	 */
104 	private boolean ignoreLeadingWhitespaces;
105 
106 	/**
107 	 * 値より後ろのホワイトスペースを除去するかどうかを保持します。
108 	 */
109 	private boolean ignoreTrailingWhitespaces;
110 
111 	/**
112 	 * 空行を無視するかどうかを保持します。
113 	 */
114 	private boolean ignoreEmptyLines;
115 
116 	/**
117 	 * 無視する行の正規表現パターン群を保持します。
118 	 */
119 	private Pattern[] ignoreLinePatterns;
120 
121 	/**
122 	 * 先頭から読飛ばす論理行数を保持します。
123 	 */
124 	private int skipLines = DEFAULT_SKIP_LINES;
125 
126 	/**
127 	 * 囲み文字出力方法の種類を保持します。
128 	 */
129 	private QuotePolicy quotePolicy = DEFAULT_QUOTE_POLICY;
130 
131 	/**
132 	 * UTF-8 エンコーディングでの出力時に BOM (Byte Order Mark) を付与するかどうかを保持します。
133 	 */
134 	private boolean utf8bomPolicy;
135 
136 	/**
137 	 * 可変項目数を許可するかどうかを保持します。
138 	 * 
139 	 * @since 2.1
140 	 */
141 	private boolean variableColumns = true;
142 
143 	/**
144 	 * データ出力時の改行文字列を保持します。
145 	 */
146 	private String lineSeparator = System.getProperty("line.separator");
147 
148 	// ------------------------------------------------------------------------
149 	// コンストラクタ
150 
151 	/**
152 	 * デフォルトコンストラクタです。
153 	 */
154 	public CsvConfig() {
155 		this(DEFAULT_SEPARATOR, DEFAULT_QUOTE, DEFAULT_ESCAPE, true, true);
156 	}
157 
158 	/**
159 	 * コンストラクタです。
160 	 *
161 	 * @param separator 区切り文字
162 	 */
163 	public CsvConfig(final char separator) {
164 		this(separator, DEFAULT_QUOTE, DEFAULT_ESCAPE, true, true);
165 	}
166 
167 	/**
168 	 * コンストラクタです。
169 	 *
170 	 * @param separator 区切り文字
171 	 * @param quote 囲み文字
172 	 * @param escape エスケープ文字
173 	 * @throws IllegalArgumentException {@code quote} または {@code escape} が {@code separator} と同一文字の場合
174 	 */
175 	public CsvConfig(final char separator, final char quote, final char escape) {
176 		this(separator, quote, escape, false, false);
177 	}
178 
179 	/**
180 	 * コンストラクタです。
181 	 *
182 	 * @param separator 区切り文字
183 	 * @param quote 囲み文字
184 	 * @param escape エスケープ文字
185 	 * @param quoteDisabled 囲み文字を無効にするかどうか
186 	 * @param escapeDisabled エスケープ文字を無効にするかどうか
187 	 * @throws IllegalArgumentException {@code quote} または {@code escape} が {@code separator} と同一文字の場合
188 	 */
189 	public CsvConfig(final char separator, final char quote, final char escape, final boolean quoteDisabled, final boolean escapeDisabled) {
190 		this.separator = separator;
191 		this.quote = quote;
192 		this.escape = escape;
193 		this.quoteDisabled = quoteDisabled;
194 		this.escapeDisabled = escapeDisabled;
195 	}
196 
197 	// ------------------------------------------------------------------------
198 
199 	/**
200 	 * 区切り文字および囲み文字、エスケープ文字の組合せを検証します。
201 	 *
202 	 * @throws IllegalArgumentException 区切り文字および囲み文字、エスケープ文字の組合せが不正な場合
203 	 */
204 	public void validate() {
205 		// 区切り文字に改行文字が指定された場合は例外をスローします。
206 		if (separator == '\r' || separator == '\n') {
207 			throw new IllegalArgumentException("Invalid separator character");
208 		}
209 		// 囲み文字に区切り文字と同じ文字や改行文字が指定された場合は例外をスローします。
210 		if (!quoteDisabled && (quote == separator || quote == '\r' || quote == '\n')) {
211 			throw new IllegalArgumentException("Invalid quote character");
212 		}
213 		// エスケープ文字文字に区切り文字と同じ文字や改行文字が指定された場合は例外をスローします。
214 		if (!escapeDisabled && (escape == separator || escape == '\r' || escape == '\n')) {
215 			throw new IllegalArgumentException("Invalid escape character");
216 		}
217 	}
218 
219 	// ------------------------------------------------------------------------
220 	// セッター/ゲッター
221 
222 	/**
223 	 * 区切り文字を返します。
224 	 *
225 	 * @return 区切り文字
226 	 */
227 	public char getSeparator() { return separator; }
228 
229 	/**
230 	 * 区切り文字を設定します。
231 	 *
232 	 * @param separator 区切り文字
233 	 */
234 	public void setSeparator(final char separator) { this.separator = separator; }
235 
236 	/**
237 	 * 囲み文字を返します。
238 	 *
239 	 * @return 囲み文字
240 	 */
241 	public char getQuote() { return quote; }
242 
243 	/**
244 	 * 囲み文字を設定します。
245 	 *
246 	 * @param quote 囲み文字
247 	 */
248 	public void setQuote(final char quote) { this.quote = quote; }
249 
250 	/**
251 	 * エスケープ文字を返します。
252 	 *
253 	 * @return エスケープ文字
254 	 */
255 	public char getEscape() { return escape; }
256 
257 	/**
258 	 * エスケープ文字を設定します。
259 	 *
260 	 * @param escape エスケープ文字
261 	 */
262 	public void setEscape(final char escape) { this.escape = escape; }
263 
264 	/**
265 	 * 囲み文字を無効にするかどうかを返します。
266 	 *
267 	 * @return 囲み文字を無効にするかどうか
268 	 */
269 	public boolean isQuoteDisabled() { return quoteDisabled; }
270 
271 	/**
272 	 * 囲み文字を無効にするかどうかを設定します。
273 	 *
274 	 * @param disabled 囲み文字を無効にするかどうか
275 	 */
276 	public void setQuoteDisabled(final boolean disabled) { this.quoteDisabled = disabled; }
277 
278 	/**
279 	 * エスケープ文字を無効にするかどうかを返します。
280 	 *
281 	 * @return エスケープ文字を無効にするかどうか
282 	 */
283 	public boolean isEscapeDisabled() { return escapeDisabled; }
284 
285 	/**
286 	 * エスケープ文字を無効にするかどうかを設定します。
287 	 *
288 	 * @param disabled エスケープ文字を無効にするかどうか
289 	 */
290 	public void setEscapeDisabled(final boolean disabled) { this.escapeDisabled = disabled; }
291 
292 	/**
293 	 * 値の改行文字列を置換える文字列を返します。
294 	 * 
295 	 * @return 値の改行文字列を置換える文字列
296 	 */
297 	public String getBreakString() { return breakString; }
298 
299 	/**
300 	 * 値の改行文字列を置換える文字列を設定します。
301 	 * 
302 	 * @param breakString 値の改行文字列を置換える文字列
303 	 */
304 	public void setBreakString(final String breakString) { this.breakString = breakString; }
305 
306 	/**
307 	 * 値がないことを表す文字列を返します。
308 	 *
309 	 * @return 値がないことを表す文字列
310 	 */
311 	public String getNullString() { return nullString; }
312 
313 	/**
314 	 * 値がないことを表す文字列を設定します。
315 	 *
316 	 * @param nullString 値がないことを表す文字列
317 	 */
318 	public void setNullString(final String nullString) {
319 		setNullString(nullString, false);
320 	}
321 
322 	/**
323 	 * 値がないことを表す文字列を設定します。
324 	 *
325 	 * @param nullString 値がないことを表す文字列
326 	 * @param ignoreCase 大文字と小文字を区別するかどうか
327 	 */
328 	public void setNullString(final String nullString, final boolean ignoreCase) {
329 		this.nullString = nullString;
330 		this.ignoreCaseNullString = ignoreCase;
331 	}
332 
333 	/**
334 	 * 値がないことを表す文字列の大文字と小文字を区別するかどうかを返します。
335 	 * 
336 	 * @return 値がないことを表す文字列の大文字と小文字を区別するかどうか
337 	 */
338 	public boolean isIgnoreCaseNullString() { return ignoreCaseNullString; }
339 
340 	/**
341 	 * 値がないことを表す文字列の大文字と小文字を区別するかどうかを設定します。
342 	 * 
343 	 * @param ignoreCaseNullString 値がないことを表す文字列の大文字と小文字を区別するかどうか
344 	 * @since 1.2.2
345 	 */
346 	public void setIgnoreCaseNullString(final boolean ignoreCaseNullString) {
347 		this.ignoreCaseNullString = ignoreCaseNullString;
348 	}
349 
350 	/**
351 	 * 値より前のホワイトスペースを除去するかどうかを返します。
352 	 *
353 	 * @return 値より前のホワイトスペースを除去するかどうか
354 	 */
355 	public boolean isIgnoreLeadingWhitespaces() { return ignoreLeadingWhitespaces; }
356 
357 	/**
358 	 * 値より前のホワイトスペースを除去するかどうかを設定します。
359 	 *
360 	 * @param ignore 値より前のホワイトスペースを除去するかどうか
361 	 * @see Character#isWhitespace(char)
362 	 */
363 	public void setIgnoreLeadingWhitespaces(final boolean ignore) { this.ignoreLeadingWhitespaces = ignore; }
364 
365 	/**
366 	 * 値より後ろのホワイトスペースを除去するかどうかを返します。
367 	 *
368 	 * @return 値より後ろのホワイトスペースを除去するかどうか
369 	 */
370 	public boolean isIgnoreTrailingWhitespaces() { return ignoreTrailingWhitespaces; }
371 
372 	/**
373 	 * 値より後ろのホワイトスペースを除去するかどうかを設定します。
374 	 *
375 	 * @param ignore 値より後ろのホワイトスペースを除去するかどうか
376 	 * @see Character#isWhitespace(char)
377 	 */
378 	public void setIgnoreTrailingWhitespaces(final boolean ignore) { this.ignoreTrailingWhitespaces = ignore; }
379 
380 	/**
381 	 * 空行を無視するかどうかを返します。
382 	 *
383 	 * @return 空行を無視するかどうか
384 	 */
385 	public boolean isIgnoreEmptyLines() { return ignoreEmptyLines; }
386 
387 	/**
388 	 * 空行を無視するかどうかを設定します。
389 	 *
390 	 * @param ignore 空行を無視するかどうか
391 	 */
392 	public void setIgnoreEmptyLines(final boolean ignore) { this.ignoreEmptyLines = ignore; }
393 
394 	/**
395 	 * 無視する行の正規表現パターン群を返します。
396 	 *
397 	 * @return 無視する行の正規表現パターン群
398 	 */
399 	public Pattern[] getIgnoreLinePatterns() { return ignoreLinePatterns; }
400 
401 	/**
402 	 * 無視する行の正規表現パターン群を設定します。
403 	 *
404 	 * @param ignoreLinePatterns 無視する行の正規表現パターン群
405 	 */
406 	public void setIgnoreLinePatterns(final Pattern...ignoreLinePatterns) { this.ignoreLinePatterns = ignoreLinePatterns; }
407 
408 	/**
409 	 * ファイルの先頭から読飛ばす行数を返します。
410 	 *
411 	 * @return ファイルの先頭から読飛ばす行数
412 	 */
413 	public int getSkipLines() { return skipLines; }
414 
415 	/**
416 	 * ファイルの先頭から読飛ばす行数を設定します。
417 	 *
418 	 * @param skipLines ファイルの先頭から読飛ばす行数
419 	 */
420 	public void setSkipLines(final int skipLines) { this.skipLines = skipLines; }
421 
422 	/**
423 	 * データ出力時の改行文字列を返します。
424 	 *
425 	 * @return データ出力時の改行文字列
426 	 */
427 	public String getLineSeparator() { return lineSeparator; }
428 
429 	/**
430 	 * データ出力時の改行文字列を設定します。
431 	 *
432 	 * @param lineSeparator データ出力時の改行文字列
433 	 */
434 	public void setLineSeparator(final String lineSeparator) { this.lineSeparator = lineSeparator; }
435 
436 	/**
437 	 * 囲み文字出力方法の種類を返します。
438 	 * 
439 	 * @return 囲み文字出力方法の種類
440 	 * @since 1.1
441 	 */
442 	public QuotePolicy getQuotePolicy() { return quotePolicy; }
443 
444 	/**
445 	 * 囲み文字出力方法の種類を設定します。
446 	 * 
447 	 * @param quotePolicy 囲み文字出力方法の種類
448 	 * @throws IllegalArgumentException {@code quotePolicy} が {@code null} の場合
449 	 * @since 1.1
450 	 */
451 	public void setQuotePolicy(final QuotePolicy quotePolicy) {
452 		if (quotePolicy == null) {
453 			throw new IllegalArgumentException("QuotePolicy must not be null");
454 		}
455 		this.quotePolicy = quotePolicy;
456 	}
457 
458 	/**
459 	 * UTF-8 エンコーディングでの出力時に BOM (Byte Order Mark) を付与するかどうかを返します。
460 	 * 
461 	 * @return UTF-8 エンコーディングでの出力時に BOM (Byte Order Mark) を付与するかどうか
462 	 * @since 1.2.9
463 	 */
464 	public boolean isUtf8bomPolicy() { return utf8bomPolicy; }
465 
466 	/**
467 	 * UTF-8 エンコーディングでの出力時に BOM (Byte Order Mark) を付与するかどうかを設定します。
468 	 * 
469 	 * @param utf8bomPolicy UTF-8 エンコーディングでの出力時に BOM (Byte Order Mark) を付与するかどうか
470 	 * @since 1.2.9
471 	 */
472 	public void setUtf8bomPolicy(final boolean utf8bomPolicy) { this.utf8bomPolicy = utf8bomPolicy; }
473 
474 	/**
475 	 * 可変項目数を許可するかどうかを返します。
476 	 * 
477 	 * @return 可変項目数を許可するかどうか
478 	 * @since 2.1
479 	 */
480 	public boolean isVariableColumns() { return variableColumns; }
481 
482 	/**
483 	 * 可変項目数を許可するかどうかを設定します。
484 	 * 
485 	 * @param variableColumns 可変項目数を許可するかどうか
486 	 * @since 2.1
487 	 */
488 	public void setVariableColumns(final boolean variableColumns) { this.variableColumns = variableColumns; }
489 
490 	/**
491 	 * {@inheritDoc}
492 	 * @since 1.1
493 	 */
494 	@Override public CsvConfig clone() { return (CsvConfig) SerializationUtils.clone(this); }
495 
496 }