Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement #510: refactoring of CSV read/write Features #511

Merged
merged 1 commit into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import tools.jackson.core.SerializableString;
import tools.jackson.core.io.CharTypes;
import tools.jackson.core.io.CharacterEscapes;
import tools.jackson.dataformat.csv.CsvGenerator.Feature;

/**
* Character escapes for CSV. There are multiple types of escapes.
Expand Down Expand Up @@ -81,8 +80,8 @@ public static CsvCharacterEscapes controlQuoteEscapesInstance()
public static CsvCharacterEscapes fromCsvFeatures(int csvFeatures)
{
int idx = 0;
idx |= CsvGenerator.Feature.ESCAPE_QUOTE_CHAR_WITH_ESCAPE_CHAR.enabledIn(csvFeatures) ? 1 : 0;
idx |= Feature.ESCAPE_CONTROL_CHARS_WITH_ESCAPE_CHAR.enabledIn(csvFeatures) ? 2 : 0;
idx |= CsvWriteFeature.ESCAPE_QUOTE_CHAR_WITH_ESCAPE_CHAR.enabledIn(csvFeatures) ? 1 : 0;
idx |= CsvWriteFeature.ESCAPE_CONTROL_CHARS_WITH_ESCAPE_CHAR.enabledIn(csvFeatures) ? 2 : 0;

return sEscapes[idx];
}
Expand Down
16 changes: 8 additions & 8 deletions csv/src/main/java/tools/jackson/dataformat/csv/CsvFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public class CsvFactory
* Bitfield (set of flags) of all parser features that are enabled
* by default.
*/
protected final static int DEFAULT_CSV_PARSER_FEATURE_FLAGS = CsvParser.Feature.collectDefaults();
protected final static int DEFAULT_CSV_PARSER_FEATURE_FLAGS = CsvReadFeature.collectDefaults();

/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
protected final static int DEFAULT_CSV_GENERATOR_FEATURE_FLAGS = CsvGenerator.Feature.collectDefaults();
protected final static int DEFAULT_CSV_GENERATOR_FEATURE_FLAGS = CsvWriteFeature.collectDefaults();

// could make it use Platform default too but...
protected final static char[] DEFAULT_LF = { '\n' };
Expand Down Expand Up @@ -172,13 +172,13 @@ public boolean canUseSchema(FormatSchema schema) {
}

@Override
public Class<CsvParser.Feature> getFormatReadFeatureType() {
return CsvParser.Feature.class;
public Class<CsvReadFeature> getFormatReadFeatureType() {
return CsvReadFeature.class;
}

@Override
public Class<CsvGenerator.Feature> getFormatWriteFeatureType() {
return CsvGenerator.Feature.class;
public Class<CsvWriteFeature> getFormatWriteFeatureType() {
return CsvWriteFeature.class;
}

@Override
Expand All @@ -190,14 +190,14 @@ public Class<CsvGenerator.Feature> getFormatWriteFeatureType() {
/**
* Checked whether specified parser feature is enabled.
*/
public final boolean isEnabled(CsvParser.Feature f) {
public final boolean isEnabled(CsvReadFeature f) {
return (_formatReadFeatures & f.getMask()) != 0;
}

/**
* Check whether specified generator feature is enabled.
*/
public boolean isEnabled(CsvGenerator.Feature f) {
public boolean isEnabled(CsvWriteFeature f) {
return (_formatWriteFeatures & f.getMask()) != 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,65 +48,65 @@ public CsvFactory build() {

// // // Parser features

public CsvFactoryBuilder enable(CsvParser.Feature f) {
public CsvFactoryBuilder enable(CsvReadFeature f) {
_formatReadFeatures |= f.getMask();
return _this();
}

public CsvFactoryBuilder enable(CsvParser.Feature first, CsvParser.Feature... other) {
public CsvFactoryBuilder enable(CsvReadFeature first, CsvReadFeature... other) {
_formatReadFeatures |= first.getMask();
for (CsvParser.Feature f : other) {
for (CsvReadFeature f : other) {
_formatReadFeatures |= f.getMask();
}
return _this();
}

public CsvFactoryBuilder disable(CsvParser.Feature f) {
public CsvFactoryBuilder disable(CsvReadFeature f) {
_formatReadFeatures &= ~f.getMask();
return _this();
}

public CsvFactoryBuilder disable(CsvParser.Feature first, CsvParser.Feature... other) {
public CsvFactoryBuilder disable(CsvReadFeature first, CsvReadFeature... other) {
_formatReadFeatures &= ~first.getMask();
for (CsvParser.Feature f : other) {
for (CsvReadFeature f : other) {
_formatReadFeatures &= ~f.getMask();
}
return _this();
}

public CsvFactoryBuilder configure(CsvParser.Feature f, boolean state) {
public CsvFactoryBuilder configure(CsvReadFeature f, boolean state) {
return state ? enable(f) : disable(f);
}

// // // Generator features

public CsvFactoryBuilder enable(CsvGenerator.Feature f) {
public CsvFactoryBuilder enable(CsvWriteFeature f) {
_formatWriteFeatures |= f.getMask();
return _this();
}

public CsvFactoryBuilder enable(CsvGenerator.Feature first, CsvGenerator.Feature... other) {
public CsvFactoryBuilder enable(CsvWriteFeature first, CsvWriteFeature... other) {
_formatWriteFeatures |= first.getMask();
for (CsvGenerator.Feature f : other) {
for (CsvWriteFeature f : other) {
_formatWriteFeatures |= f.getMask();
}
return _this();
}

public CsvFactoryBuilder disable(CsvGenerator.Feature f) {
public CsvFactoryBuilder disable(CsvWriteFeature f) {
_formatWriteFeatures &= ~f.getMask();
return _this();
}

public CsvFactoryBuilder disable(CsvGenerator.Feature first, CsvGenerator.Feature... other) {
public CsvFactoryBuilder disable(CsvWriteFeature first, CsvWriteFeature... other) {
_formatWriteFeatures &= ~first.getMask();
for (CsvGenerator.Feature f : other) {
for (CsvWriteFeature f : other) {
_formatWriteFeatures &= ~f.getMask();
}
return _this();
}

public CsvFactoryBuilder configure(CsvGenerator.Feature f, boolean state) {
public CsvFactoryBuilder configure(CsvWriteFeature f, boolean state) {
return state ? enable(f) : disable(f);
}

Expand Down
138 changes: 2 additions & 136 deletions csv/src/main/java/tools/jackson/dataformat/csv/CsvGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,140 +17,6 @@

public class CsvGenerator extends GeneratorBase
{
/**
* Enumeration that defines all togglable features for CSV writers
* (if any: currently none)
*/
public enum Feature
implements FormatFeature
{
/**
* Feature that determines how much work is done before determining that
* a column value requires quoting: when set as <code>true</code>, full
* check is made to only use quoting when it is strictly necessary;
* but when <code>false</code>, a faster but more conservative check
* is made, and possibly quoting is used for values that might not need it.
* Trade-offs is basically between optimal/minimal quoting (true), and
* faster handling (false).
* Faster check involves only checking first N characters of value, as well
* as possible looser checks.
*<p>
* Note, however, that regardless setting, all values that need to be quoted
* will be: it is just that when set to <code>false</code>, other values may
* also be quoted (to avoid having to do more expensive checks).
*<p>
* Default value is <code>false</code> for "loose" (approximate, conservative)
* checking.
*/
STRICT_CHECK_FOR_QUOTING(false),

/**
* Feature that determines whether columns without matching value may be omitted,
* when they are the last values of the row.
* If <code>true</code>, values and separators between values may be omitted, to slightly reduce
* length of the row; if <code>false</code>, separators need to stay in place and values
* are indicated by empty Strings.
*/
OMIT_MISSING_TAIL_COLUMNS(false),

/**
* Feature that determines whether values written as Strings (from <code>java.lang.String</code>
* valued POJO properties) should be forced to be quoted, regardless of whether they
* actually need this.
* Note that this feature has precedence over {@link #STRICT_CHECK_FOR_QUOTING}, when
* both would be applicable.
<<<<<<< HEAD:csv/src/main/java/tools/jackson/dataformat/csv/CsvGenerator.java
=======
* Note that this setting does NOT affect quoting of typed values like {@code Number}s
* or {@code Boolean}s.
*
* @since 2.5
>>>>>>> 2.16:csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvGenerator.java
*/
ALWAYS_QUOTE_STRINGS(false),

/**
* Feature that determines whether values written as empty Strings (from <code>java.lang.String</code>
* valued POJO properties) should be forced to be quoted.
*/
ALWAYS_QUOTE_EMPTY_STRINGS(false),

/**
* Feature that determines whether values written as Nymbers (from {@code java.lang.Number}
* valued POJO properties) should be forced to be quoted, regardless of whether they
* actually need this.
*
* @since 2.16
*/
ALWAYS_QUOTE_NUMBERS(false),

/**
* Feature that determines whether quote characters within quoted String values are escaped
* using configured escape character, instead of being "doubled up" (that is: a quote character
* is written twice in a row).
*<p>
* Default value is false so that quotes are doubled as necessary, not escaped.
*/
ESCAPE_QUOTE_CHAR_WITH_ESCAPE_CHAR(false),

/**
* Feature that determines whether control characters (non-printable) are escaped using the
* configured escape character. This feature allows LF and CR characters to be output as <pre>\n</pre>
* and <pre>\r</pre> instead of being echoed out. This is a compatibility feature for some
* parsers that can not read such output back in.
* <p>
* Default value is false so that control characters are echoed out (backwards compatible).
*/
ESCAPE_CONTROL_CHARS_WITH_ESCAPE_CHAR(false),

/**
* Feature that determines whether a line-feed will be written at the end of content,
* after the last row of output.
*<p>
* NOTE! When disabling this feature it is important that
* {@link #flush()} is NOT called before {@link #close()} is called;
* the current implementation relies on ability to essentially remove the
* last linefeed that was appended in the output buffer.
*<p>
* Default value is {@code true} so all rows, including the last, are terminated by
* a line feed.
*
* @since 2.17
*/
WRITE_LINEFEED_AFTER_LAST_ROW(true)
;

protected final boolean _defaultState;
protected final int _mask;

/**
* Method that calculates bit set (flags) of all features that
* are enabled by default.
*/
public static int collectDefaults()
{
int flags = 0;
for (Feature f : values()) {
if (f.enabledByDefault()) {
flags |= f.getMask();
}
}
return flags;
}

private Feature(boolean defaultState) {
_defaultState = defaultState;
_mask = (1 << ordinal());
}

@Override
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
@Override
public boolean enabledByDefault() { return _defaultState; }
@Override
public int getMask() { return _mask; }
}

protected final static long MIN_INT_AS_LONG = Integer.MIN_VALUE;
protected final static long MAX_INT_AS_LONG = Integer.MAX_VALUE;

Expand All @@ -164,7 +30,7 @@ private Feature(boolean defaultState) {

/**
* Bit flag composed of bits that indicate which
* {@link CsvGenerator.Feature}s
* {@link CsvWriteFeature}s
* are enabled.
*/
protected int _formatFeatures;
Expand Down Expand Up @@ -431,7 +297,7 @@ private final void _writeFieldName(String name) throws JacksonException
/**********************************************************************
*/

public final boolean isEnabled(Feature f) {
public final boolean isEnabled(CsvWriteFeature f) {
return (_formatFeatures & f.getMask()) != 0;
}

Expand Down
20 changes: 10 additions & 10 deletions csv/src/main/java/tools/jackson/dataformat/csv/CsvMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,21 @@ protected MapperBuilderState _saveState() {
/******************************************************************
*/

public Builder enable(CsvParser.Feature... features) {
for (CsvParser.Feature f : features) {
public Builder enable(CsvReadFeature... features) {
for (CsvReadFeature f : features) {
_formatReadFeatures |= f.getMask();
}
return this;
}

public Builder disable(CsvParser.Feature... features) {
for (CsvParser.Feature f : features) {
public Builder disable(CsvReadFeature... features) {
for (CsvReadFeature f : features) {
_formatReadFeatures &= ~f.getMask();
}
return this;
}

public Builder configure(CsvParser.Feature feature, boolean state)
public Builder configure(CsvReadFeature feature, boolean state)
{
if (state) {
_formatReadFeatures |= feature.getMask();
Expand All @@ -79,21 +79,21 @@ public Builder configure(CsvParser.Feature feature, boolean state)
return this;
}

public Builder enable(CsvGenerator.Feature... features) {
for (CsvGenerator.Feature f : features) {
public Builder enable(CsvWriteFeature... features) {
for (CsvWriteFeature f : features) {
_formatWriteFeatures |= f.getMask();
}
return this;
}

public Builder disable(CsvGenerator.Feature... features) {
for (CsvGenerator.Feature f : features) {
public Builder disable(CsvWriteFeature... features) {
for (CsvWriteFeature f : features) {
_formatWriteFeatures &= ~f.getMask();
}
return this;
}

public Builder configure(CsvGenerator.Feature feature, boolean state)
public Builder configure(CsvWriteFeature feature, boolean state)
{
if (state) {
_formatWriteFeatures |= feature.getMask();
Expand Down
Loading