com.univocity.parsers.common.CommonSettings Maven / Gradle / Ivy
Show all versions of univocity-parsers Show documentation
/*******************************************************************************
* Copyright 2014 Univocity Software Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.univocity.parsers.common;
import com.univocity.parsers.annotations.*;
import com.univocity.parsers.common.fields.*;
import com.univocity.parsers.common.processor.*;
import java.util.*;
import java.util.Map.*;
/**
* This is the parent class for all configuration classes used by parsers ({@link AbstractParser}) and writers ({@link AbstractWriter})
*
* By default, all parsers and writers work with, at least, the following configuration options:
*
*
* - format (each file format provides its default): the input/output format of a given file
* - nullValue (defaults to null):
*
when reading, if the parser does not read any character from the input, the nullValue is used instead of an empty string
*
when writing, if the writer has a null object to write to the output, the nullValue is used instead of an empty string
* - maxCharsPerColumn (defaults to 4096): The maximum number of characters allowed for any given value being written/read.
*
You need this to avoid OutOfMemoryErrors in case a file does not have a valid format. In such cases the parser might just keep reading from the input
* until its end or the memory is exhausted. This sets a limit which avoids unwanted JVM crashes.
* - maxColumns (defaults to 512): a hard limit on how many columns a record can have.
* You need this to avoid OutOfMemory errors in case of inputs that might be inconsistent with the format you are dealing with
* - skipEmptyLines (defaults to true):
*
when reading, if the parser reads a line that is empty, it will be skipped.
*
when writing, if the writer receives an empty or null row to write to the output, it will be ignored
* - ignoreTrailingWhitespaces (defaults to true): removes trailing whitespaces from values being read/written
* - ignoreLeadingWhitespaces (defaults to true): removes leading whitespaces from values being read/written
* - headers (defaults to null): the field names in the input/output, in the sequence they occur.
*
when reading, the given header names will be used to refer to each column irrespective of whether or not the input contains a header row
*
when writing, the given header names will be used to refer to each column and can be used for writing the header row
* - field selection (defaults to none): a selection of fields for reading and writing. Fields can be selected by their name or their position.
*
when reading, the selected fields only will be parsed and the remaining fields will be discarded.
*
when writing, the selected fields only will be written and the remaining fields will be discarded
*
*
* @param the format supported by this settings class.
*
* @author Univocity Software Pty Ltd - [email protected]
* @see com.univocity.parsers.common.CommonParserSettings
* @see com.univocity.parsers.common.CommonWriterSettings
* @see com.univocity.parsers.csv.CsvParserSettings
* @see com.univocity.parsers.csv.CsvWriterSettings
* @see com.univocity.parsers.fixed.FixedWidthParserSettings
* @see com.univocity.parsers.fixed.FixedWidthWriterSettings
*/
public abstract class CommonSettings implements Cloneable {
private F format;
private String nullValue = null;
private int maxCharsPerColumn = 4096;
private int maxColumns = 512;
private boolean skipEmptyLines = true;
private boolean ignoreTrailingWhitespaces = true;
private boolean ignoreLeadingWhitespaces = true;
private FieldSelector fieldSelector = null;
private boolean autoConfigurationEnabled = true;
private ProcessorErrorHandler extends Context> errorHandler;
private int errorContentLength = -1;
private boolean skipBitsAsWhitespace = true;
private String[] headers;
Class> headerSourceClass;
/**
* Creates a new instance of this settings object using the default format specified by the concrete class that inherits from {@code CommonSettings}
*/
public CommonSettings() {
setFormat(createDefaultFormat());
}
/**
* Returns the String representation of a null value (defaults to null)
* When reading, if the parser does not read any character from the input, the nullValue is used instead of an empty string
*
When writing, if the writer has a null object to write to the output, the nullValue is used instead of an empty string
*
* @return the String representation of a null value
*/
public String getNullValue() {
return nullValue;
}
/**
* Sets the String representation of a null value (defaults to null)
*
When reading, if the parser does not read any character from the input, the nullValue is used instead of an empty string
*
When writing, if the writer has a null object to write to the output, the nullValue is used instead of an empty string
*
* @param emptyValue the String representation of a null value
*/
public void setNullValue(String emptyValue) {
this.nullValue = emptyValue;
}
/**
* The maximum number of characters allowed for any given value being written/read. Used to avoid OutOfMemoryErrors (defaults to 4096).
*
*
If set to {@code -1}, then the internal internal array will expand automatically, up to the limit allowed by the JVM
*
* @return The maximum number of characters allowed for any given value being written/read
*/
public int getMaxCharsPerColumn() {
return maxCharsPerColumn;
}
/**
* Defines the maximum number of characters allowed for any given value being written/read. Used to avoid OutOfMemoryErrors (defaults to 4096).
*
* To enable auto-expansion of the internal array, set this property to -1
*
* @param maxCharsPerColumn The maximum number of characters allowed for any given value being written/read
*/
public void setMaxCharsPerColumn(int maxCharsPerColumn) {
this.maxCharsPerColumn = maxCharsPerColumn;
}
/**
* Returns whether or not empty lines should be ignored (defaults to true)
* when reading, if the parser reads a line that is empty, it will be skipped.
*
when writing, if the writer receives an empty or null row to write to the output, it will be ignored
*
* @return true if empty lines are configured to be ignored, false otherwise
*/
public boolean getSkipEmptyLines() {
return skipEmptyLines;
}
/**
* Defines whether or not empty lines should be ignored (defaults to true)
*
when reading, if the parser reads a line that is empty, it will be skipped.
*
when writing, if the writer receives an empty or null row to write to the output, it will be ignored
*
* @param skipEmptyLines true if empty lines should be ignored, false otherwise
*/
public void setSkipEmptyLines(boolean skipEmptyLines) {
this.skipEmptyLines = skipEmptyLines;
}
/**
* Returns whether or not trailing whitespaces from values being read/written should be skipped (defaults to true)
*
* @return true if trailing whitespaces from values being read/written should be skipped, false otherwise
*/
public boolean getIgnoreTrailingWhitespaces() {
return ignoreTrailingWhitespaces;
}
/**
* Defines whether or not trailing whitespaces from values being read/written should be skipped (defaults to true)
*
* @param ignoreTrailingWhitespaces true if trailing whitespaces from values being read/written should be skipped, false otherwise
*/
public void setIgnoreTrailingWhitespaces(boolean ignoreTrailingWhitespaces) {
this.ignoreTrailingWhitespaces = ignoreTrailingWhitespaces;
}
/**
* Returns whether or not leading whitespaces from values being read/written should be skipped (defaults to true)
*
* @return true if leading whitespaces from values being read/written should be skipped, false otherwise
*/
public boolean getIgnoreLeadingWhitespaces() {
return ignoreLeadingWhitespaces;
}
/**
* Defines whether or not leading whitespaces from values being read/written should be skipped (defaults to true)
*
* @param ignoreLeadingWhitespaces true if leading whitespaces from values being read/written should be skipped, false otherwise
*/
public void setIgnoreLeadingWhitespaces(boolean ignoreLeadingWhitespaces) {
this.ignoreLeadingWhitespaces = ignoreLeadingWhitespaces;
}
/**
* Defines the field names in the input/output, in the sequence they occur (defaults to null).
*
when reading, the given header names will be used to refer to each column irrespective of whether or not the input contains a header row
*
when writing, the given header names will be used to refer to each column and can be used for writing the header row
*
* @param headers the field name sequence associated with each column in the input/output.
*/
public void setHeaders(String... headers) {
if (headers == null || headers.length == 0) {
this.headers = null;
} else {
this.headers = headers;
}
}
/**
* Defines the field names in the input/output derived from a given class with {@link Parsed} annotated attributes/methods.
*
when reading, the given header names will be used to refer to each column irrespective of whether or not the input contains a header row
*
when writing, the given header names will be used to refer to each column and can be used for writing the header row
*
* @param headerSourceClass the class from which the headers have been derived.
* @param headers the field name sequence associated with each column in the input/output.
*/
void setHeadersDerivedFromClass(Class> headerSourceClass, String... headers) {
this.headerSourceClass = headerSourceClass;
setHeaders(headers);
}
/**
* Indicates whether headers should be derived from a given class.
*
* @param beanClass the class to derive headers from
*
* @return {@code true} if the headers used for parsing/writing should be derived from the given class; otherwise {@code false}
*/
boolean deriveHeadersFrom(Class> beanClass) {
if (headerSourceClass != null) {
if (headerSourceClass != beanClass) {
setHeaders(null);
} else {
return false;
}
}
return true;
}
/**
* Returns the field names in the input/output, in the sequence they occur (defaults to null).
*
when reading, the given header names will be used to refer to each column irrespective of whether or not the input contains a header row
*
when writing, the given header names will be used to refer to each column and can be used for writing the header row
*
* @return the field name sequence associated with each column in the input/output.
*/
public String[] getHeaders() {
return this.headers;
}
/**
* Returns the hard limit of how many columns a record can have (defaults to 512).
* You need this to avoid OutOfMemory errors in case of inputs that might be inconsistent with the format you are dealing with .
*
* @return The maximum number of columns a record can have.
*/
public int getMaxColumns() {
return maxColumns;
}
/**
* Defines a hard limit of how many columns a record can have (defaults to 512).
* You need this to avoid OutOfMemory errors in case of inputs that might be inconsistent with the format you are dealing with.
*
* @param maxColumns The maximum number of columns a record can have.
*/
public void setMaxColumns(int maxColumns) {
this.maxColumns = maxColumns;
}
/**
* The format of the file to be parsed/written (returns the format's defaults).
*
* @return The format of the file to be parsed/written
*/
public F getFormat() {
return format;
}
/**
* Defines the format of the file to be parsed/written (returns the format's defaults).
*
* @param format The format of the file to be parsed/written
*/
public void setFormat(F format) {
if (format == null) {
throw new IllegalArgumentException("Format cannot be null");
}
this.format = format;
}
/**
* Selects a sequence of fields for reading/writing by their names.
*
*
When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence provided represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting fields "H3" and "H1" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param fieldNames The field names to read/write
*
* @return the (modifiable) set of selected fields
*/
public FieldSet selectFields(String... fieldNames) {
return setFieldSet(new FieldNameSelector(), fieldNames);
}
/**
* Selects fields which will not be read/written, by their names
*
* When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence of non-excluded fields represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting fields "H3" and "H1" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param fieldNames The field names to exclude from the parsing/writing process
*
* @return the (modifiable) set of ignored fields
*/
public FieldSet excludeFields(String... fieldNames) {
return setFieldSet(new ExcludeFieldNameSelector(), fieldNames);
}
/**
* Selects a sequence of fields for reading/writing by their positions.
*
* When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence provided represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting indexes "2" and "0" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param fieldIndexes The indexes to read/write
*
* @return the (modifiable) set of selected fields
*/
public FieldSet selectIndexes(Integer... fieldIndexes) {
return setFieldSet(new FieldIndexSelector(), fieldIndexes);
}
/**
* Selects columns which will not be read/written, by their positions
*
* When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence of non-excluded fields represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting fields by index, such as "2" and "0" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param fieldIndexes indexes of columns to exclude from the parsing/writing process
*
* @return the (modifiable) set of ignored fields
*/
public FieldSet excludeIndexes(Integer... fieldIndexes) {
return setFieldSet(new ExcludeFieldIndexSelector(), fieldIndexes);
}
/**
* Selects a sequence of fields for reading/writing by their names
*
*
* When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence provided represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting fields "H3" and "H1" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param columns The columns to read/write
*
* @return the (modifiable) set of selected fields
*/
@SuppressWarnings("rawtypes")
public FieldSet selectFields(Enum... columns) {
return setFieldSet(new FieldEnumSelector(), columns);
}
/**
* Selects columns which will not be read/written, by their names
*
* When reading, only the values of the selected columns will be parsed, and the content of the other columns ignored.
* The resulting rows will be returned with the selected columns only, in the order specified. If you want to
* obtain the original row format, with all columns included and nulls in the fields that have not been selected,
* set {@link CommonParserSettings#setColumnReorderingEnabled(boolean)} with {@code false}.
*
* When writing, the sequence of non-excluded fields represents the expected format of the input rows. For example,
* headers can be "H1,H2,H3", but the input data is coming with values for two columns and in a different order,
* such as "V_H3, V_H1". Selecting fields "H3" and "H1" will allow the writer to write values in the expected
* locations. Using the given example, the output row will be generated as: "V_H1,null,V_H3"
*
* @param columns The columns to exclude from the parsing/writing process
*
* @return the (modifiable) set of ignored fields
*/
@SuppressWarnings("rawtypes")
public FieldSet excludeFields(Enum... columns) {
return setFieldSet(new ExcludeFieldEnumSelector(), columns);
}
/**
* Replaces the current field selection
*
* @param fieldSet the new set of selected fields
* @param values the values to include to the selection
*
* @return the set of selected fields given in as a parameter.
*/
private FieldSet setFieldSet(FieldSet fieldSet, T... values) {
this.fieldSelector = (FieldSelector) fieldSet;
fieldSet.add(values);
return fieldSet;
}
/**
* Returns the set of selected fields, if any
*
* @return the set of selected fields. Null if no field was selected/excluded
*/
FieldSet> getFieldSet() {
return (FieldSet>) fieldSelector;
}
/**
* Returns the FieldSelector object, which handles selected fields.
*
* @return the FieldSelector object, which handles selected fields. Null if no field was selected/excluded
*/
FieldSelector getFieldSelector() {
return this.fieldSelector;
}
/**
* Indicates whether this settings object can automatically derive configuration options. This is used, for example, to define the headers when the user
* provides a {@link BeanWriterProcessor} where the bean class contains a {@link Headers} annotation, or to enable header extraction when the bean class of a
* {@link BeanProcessor} has attributes mapping to header names.
*
* Defaults to {@code true}
*
* @return {@code true} if the automatic configuration feature is enabled, false otherwise
*/
public final boolean isAutoConfigurationEnabled() {
return autoConfigurationEnabled;
}
/**
* Indicates whether this settings object can automatically derive configuration options. This is used, for example, to define the headers when the user
* provides a {@link BeanWriterProcessor} where the bean class contains a {@link Headers} annotation, or to enable header extraction when the bean class of a
* {@link BeanProcessor} has attributes mapping to header names.
*
* @param autoConfigurationEnabled a flag to turn the automatic configuration feature on/off.
*/
public final void setAutoConfigurationEnabled(boolean autoConfigurationEnabled) {
this.autoConfigurationEnabled = autoConfigurationEnabled;
}
/**
* Returns the custom error handler to be used to capture and handle errors that might happen while processing records with a {@link RowProcessor}
* or a {@link RowWriterProcessor} (i.e. non-fatal {@link DataProcessingException}s).
*
* The parsing/writing process won't stop (unless the error handler rethrows the {@link DataProcessingException} or manually stops the process).
*
* @return the callback error handler with custom code to manage occurrences of {@link DataProcessingException}.
*
* @deprecated Use the {@link #getProcessorErrorHandler()} method as it allows format-specific error handlers to be built to work with different implementations of {@link Context}.
* Implementations based on {@link RowProcessorErrorHandler} allow only parsers who provide a {@link ParsingContext} to be used.
*/
@Deprecated
public RowProcessorErrorHandler getRowProcessorErrorHandler() {
return errorHandler == null ? NoopRowProcessorErrorHandler.instance : (RowProcessorErrorHandler) errorHandler;
}
/**
* Defines a custom error handler to capture and handle errors that might happen while processing records with a {@link RowProcessor}
* or a {@link RowWriterProcessor} (i.e. non-fatal {@link DataProcessingException}s).
*
* The parsing parsing/writing won't stop (unless the error handler rethrows the {@link DataProcessingException} or manually stops the process).
*
* @param rowProcessorErrorHandler the callback error handler with custom code to manage occurrences of {@link DataProcessingException}.
*
* @deprecated Use the {@link #setProcessorErrorHandler(ProcessorErrorHandler)} method as it allows format-specific error handlers to be built to work with different implementations of {@link Context}.
* Implementations based on {@link RowProcessorErrorHandler} allow only parsers who provide a {@link ParsingContext} to be used.
*/
@Deprecated
public void setRowProcessorErrorHandler(RowProcessorErrorHandler rowProcessorErrorHandler) {
this.errorHandler = rowProcessorErrorHandler;
}
/**
* Returns the custom error handler to be used to capture and handle errors that might happen while processing records with a {@link com.univocity.parsers.common.processor.core.Processor}
* or a {@link RowWriterProcessor} (i.e. non-fatal {@link DataProcessingException}s).
*
* The parsing/writing process won't stop (unless the error handler rethrows the {@link DataProcessingException} or manually stops the process).
*
* @param the {@code Context} type provided by the parser implementation.
*
* @return the callback error handler with custom code to manage occurrences of {@link DataProcessingException}.
*/
public ProcessorErrorHandler getProcessorErrorHandler() {
return errorHandler == null ? NoopProcessorErrorHandler.instance : (ProcessorErrorHandler) errorHandler;
}
/**
* Defines a custom error handler to capture and handle errors that might happen while processing records with a {@link com.univocity.parsers.common.processor.core.Processor}
* or a {@link RowWriterProcessor} (i.e. non-fatal {@link DataProcessingException}s).
*
* The parsing parsing/writing won't stop (unless the error handler rethrows the {@link DataProcessingException} or manually stops the process).
*
* @param processorErrorHandler the callback error handler with custom code to manage occurrences of {@link DataProcessingException}.
*/
public void setProcessorErrorHandler(ProcessorErrorHandler extends Context> processorErrorHandler) {
this.errorHandler = processorErrorHandler;
}
/**
* Returns a flag indicating whether or not a {@link ProcessorErrorHandler} has been defined through the use of method {@link #setProcessorErrorHandler(ProcessorErrorHandler)}
*
* @return {@code true} if the parser/writer is configured to use a {@link ProcessorErrorHandler}
*/
public boolean isProcessorErrorHandlerDefined() {
return errorHandler != null;
}
/**
* Extending classes must implement this method to return the default format settings for their parser/writer
*
* @return Default format configuration for the given parser/writer settings.
*/
protected abstract F createDefaultFormat();
final void autoConfigure() {
if (!this.autoConfigurationEnabled) {
return;
}
runAutomaticConfiguration();
}
/**
* Configures the parser/writer to trim or keep leading and trailing whitespaces around values
* This has the same effect as invoking both {@link #setIgnoreLeadingWhitespaces(boolean)} and {@link #setIgnoreTrailingWhitespaces(boolean)}
* with the same value.
*
* @param trim a flag indicating whether the whitespaces should remove whitespaces around values parsed/written.
*/
public final void trimValues(boolean trim) {
this.setIgnoreLeadingWhitespaces(trim);
this.setIgnoreTrailingWhitespaces(trim);
}
/**
* Configures the parser/writer to limit the length of displayed contents being parsed/written in the exception message when an error occurs
*
* If set to {@code 0}, then no exceptions will include the content being manipulated in their attributes,
* and the {@code ""} string will appear in error messages as the parsed/written content.
*
* defaults to {@code -1} (no limit)
.
*
* @return the maximum length of contents displayed in exception messages in case of errors while parsing/writing.
*/
public int getErrorContentLength() {
return errorContentLength;
}
/**
* Configures the parser/writer to limit the length of displayed contents being parsed/written in the exception message when an error occurs.
*
* If set to {@code 0}, then no exceptions will include the content being manipulated in their attributes,
* and the {@code ""} string will appear in error messages as the parsed/written content.
*
* defaults to {@code -1} (no limit)
.
*
* @param errorContentLength maximum length of contents displayed in exception messages in case of errors while parsing/writing.
*/
public void setErrorContentLength(int errorContentLength) {
this.errorContentLength = errorContentLength;
}
void runAutomaticConfiguration() {
}
/**
* Returns a flag indicating whether the parser/writer should skip bit values as whitespace.
*
* By default the parser/writer
* removes control characters and considers a whitespace any character where {@code character <= ' '} evaluates to
* {@code true}. This includes bit values, i.e. {@code 0} (the \0 character) and {@code 1} which might
* be produced by database dumps. Disabling this flag will prevent the parser/writer from discarding these characters
* when {@link #getIgnoreLeadingWhitespaces()} or {@link #getIgnoreTrailingWhitespaces()} evaluate to {@code true}.
*
* defaults to {@code true}
*
* @return a flag indicating whether bit values (0 or 1) should be considered whitespace.
*/
public final boolean getSkipBitsAsWhitespace() {
return skipBitsAsWhitespace;
}
/**
* Configures the parser to skip bit values as whitespace.
*
* By default the parser/writer removes control characters and considers a whitespace any character where {@code character <= ' '} evaluates to
* {@code true}. This includes bit values, i.e. {@code 0} (the \0 character) and {@code 1} which might
* be produced by database dumps. Disabling this flag will prevent the parser/writer from discarding these characters
* when {@link #getIgnoreLeadingWhitespaces()} or {@link #getIgnoreTrailingWhitespaces()} evaluate to {@code true}.
*
* defaults to {@code true}
*
* @param skipBitsAsWhitespace a flag indicating whether bit values (0 or 1) should be considered whitespace.
*/
public final void setSkipBitsAsWhitespace(boolean skipBitsAsWhitespace) {
this.skipBitsAsWhitespace = skipBitsAsWhitespace;
}
/**
* Returns the starting decimal range for {@code characters <= ' '} that should be skipped as whitespace, as
* determined by {@link #getSkipBitsAsWhitespace()}
*
* @return the starting range after which characters will be considered whitespace
*/
protected final int getWhitespaceRangeStart() {
return skipBitsAsWhitespace ? -1 : 1;
}
@Override
public final String toString() {
StringBuilder out = new StringBuilder();
out.append(getClass().getSimpleName()).append(':');
TreeMap config = new TreeMap();
addConfiguration(config);
for (Entry e : config.entrySet()) {
out.append("\n\t");
out.append(e.getKey()).append('=').append(e.getValue());
}
out.append("Format configuration:\n\t").append(getFormat().toString());
return out.toString();
}
protected void addConfiguration(Map out) {
out.put("Null value", nullValue);
out.put("Maximum number of characters per column", maxCharsPerColumn);
out.put("Maximum number of columns", maxColumns);
out.put("Skip empty lines", skipEmptyLines);
out.put("Ignore trailing whitespaces", ignoreTrailingWhitespaces);
out.put("Ignore leading whitespaces", ignoreLeadingWhitespaces);
out.put("Selected fields", fieldSelector == null ? "none" : fieldSelector.describe());
out.put("Headers", Arrays.toString(headers));
out.put("Auto configuration enabled", autoConfigurationEnabled);
out.put("RowProcessor error handler", errorHandler);
out.put("Length of content displayed on error", errorContentLength);
out.put("Restricting data in exceptions", errorContentLength == 0);
out.put("Skip bits as whitespace", skipBitsAsWhitespace);
}
/**
* Clones this configuration object to reuse user-provided settings.
*
* Properties that are specific to a given input (such as header names and selection of fields) can be reset to their defaults
* if the {@code clearInputSpecificSettings} flag is set to {@code true}
*
* @param clearInputSpecificSettings flag indicating whether to clear settings that are likely to be associated with a given input.
*
* @return a copy of the configurations applied to the current instance.
*/
protected CommonSettings clone(boolean clearInputSpecificSettings) {
try {
CommonSettings out = (CommonSettings) super.clone();
if (out.format != null) {
out.format = out.format.clone();
}
if (clearInputSpecificSettings) {
out.clearInputSpecificSettings();
}
return out;
} catch (CloneNotSupportedException e) {
throw new IllegalStateException(e);
}
}
/**
* Clones this configuration object. Use alternative {@link #clone(boolean)} method to reset properties that are
* specific to a given input, such as header names and selection of fields.
*
* @return a copy of all configurations applied to the current instance.
*/
@Override
protected CommonSettings clone() {
return clone(false);
}
/**
* Clears settings that are likely to be specific to a given input.
*/
protected void clearInputSpecificSettings() {
fieldSelector = null;
headers = null;
}
}