[jOOQ/jOOQ#12304] Add Configuration::formattingProvider to offer various formatting related SPIs

This includes:

- [jOOQ/jOOQ#12305] Add missing @NotNull annotations to TXTFormat, CSVFormat, JSONFormat, XMLFormat, ChartFormat
This commit is contained in:
Lukas Eder 2021-08-13 10:49:14 +02:00
parent 192a655396
commit ccad787ebc
21 changed files with 583 additions and 162 deletions

View File

@ -39,6 +39,8 @@ package org.jooq;
import static org.jooq.CSVFormat.Quote.SPECIAL_CHARACTERS;
import org.jetbrains.annotations.NotNull;
/**
* A CSV formatting type, which can be used to configure CSV imports / exports.
* <p>
@ -49,13 +51,15 @@ import static org.jooq.CSVFormat.Quote.SPECIAL_CHARACTERS;
*/
public final class CSVFormat {
final String delimiter;
final String nullString;
final String emptyString;
final String newline;
final String quoteString;
final Quote quote;
final boolean header;
public static final CSVFormat DEFAULT = new CSVFormat();
final String delimiter;
final String nullString;
final String emptyString;
final String newline;
final String quoteString;
final Quote quote;
final boolean header;
public CSVFormat() {
this(
@ -102,6 +106,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public CSVFormat delimiter(String newDelimiter) {
return new CSVFormat(
newDelimiter,
@ -129,6 +134,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public CSVFormat delimiter(char newDelimiter) {
return delimiter("" + newDelimiter);
}
@ -148,6 +154,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public String delimiter() {
return delimiter;
}
@ -171,6 +178,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public CSVFormat nullString(String newNullString) {
return new CSVFormat(
delimiter,
@ -202,6 +210,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public String nullString() {
return nullString;
}
@ -221,6 +230,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public CSVFormat emptyString(String newEmptyString) {
return new CSVFormat(
delimiter,
@ -248,6 +258,7 @@ public final class CSVFormat {
* </tr>
* </table>
*/
@NotNull
public String emptyString() {
return emptyString;
}
@ -255,6 +266,7 @@ public final class CSVFormat {
/**
* The string to be used to separate rows, defaulting to <code>\n</code>.
*/
@NotNull
public CSVFormat newline(String newNewline) {
return new CSVFormat(
delimiter,
@ -270,6 +282,7 @@ public final class CSVFormat {
/**
* The string to be used to separate rows, defaulting to <code>\n</code>.
*/
@NotNull
public String newline() {
return newline;
}
@ -278,6 +291,7 @@ public final class CSVFormat {
* The string used to quote values according to the rules specified in
* {@link #quote()}.
*/
@NotNull
public CSVFormat quoteString(String newQuoteString) {
return new CSVFormat(
delimiter,
@ -294,6 +308,7 @@ public final class CSVFormat {
* The string used to quote values according to the rules specified in
* {@link #quote()}.
*/
@NotNull
public String quoteString() {
return quoteString;
}
@ -301,6 +316,7 @@ public final class CSVFormat {
/**
* When to quote CSV content.
*/
@NotNull
public CSVFormat quote(Quote newQuote) {
return new CSVFormat(
delimiter,
@ -316,6 +332,7 @@ public final class CSVFormat {
/**
* When to quote CSV content.
*/
@NotNull
public Quote quote() {
return quote;
}
@ -324,6 +341,7 @@ public final class CSVFormat {
* Whether to emit a header row with column names, defaulting to
* <code>true</code>.
*/
@NotNull
public CSVFormat header(boolean newHeader) {
return new CSVFormat(
delimiter,

View File

@ -39,6 +39,8 @@ package org.jooq;
import java.text.DecimalFormat;
import org.jetbrains.annotations.NotNull;
/**
* A CSV formatting type, which can be used to configure chart exports.
* <p>
@ -116,6 +118,7 @@ public final class ChartFormat {
/**
* The new output format, defaulting to {@link Output#ASCII}.
*/
@NotNull
public ChartFormat output(Output newOutput) {
return new ChartFormat(
newOutput,
@ -137,6 +140,7 @@ public final class ChartFormat {
/**
* The output format.
*/
@NotNull
public Output output() {
return output;
}
@ -144,6 +148,7 @@ public final class ChartFormat {
/**
* The new chart type, defaulting to {@link Type#AREA}.
*/
@NotNull
public ChartFormat type(Type newType) {
return new ChartFormat(
output,
@ -162,6 +167,7 @@ public final class ChartFormat {
);
}
@NotNull
public Type type() {
return type;
}
@ -169,6 +175,7 @@ public final class ChartFormat {
/**
* The new display format, defaulting to {@link Display#STACKED}.
*/
@NotNull
public ChartFormat display(Display newDisplay) {
return new ChartFormat(
output,
@ -190,6 +197,7 @@ public final class ChartFormat {
/**
* The display format.
*/
@NotNull
public Display display() {
return display;
}
@ -197,6 +205,7 @@ public final class ChartFormat {
/**
* The new chart dimensions, defaulting to <code>80 x 25</code>.
*/
@NotNull
public ChartFormat dimensions(int newWidth, int newHeight) {
return new ChartFormat(
output,
@ -218,6 +227,7 @@ public final class ChartFormat {
/**
* The new chart width, defaulting to <code>80</code>.
*/
@NotNull
public ChartFormat width(int newWidth) {
return dimensions(newWidth, height);
}
@ -232,6 +242,7 @@ public final class ChartFormat {
/**
* The new chart height, defaulting to <code>25</code>.
*/
@NotNull
public ChartFormat height(int newHeight) {
return dimensions(width, newHeight);
}
@ -246,6 +257,7 @@ public final class ChartFormat {
/**
* The new category source column number, defaulting to <code>0</code>.
*/
@NotNull
public ChartFormat category(int newCategory) {
return new ChartFormat(
output,
@ -274,6 +286,7 @@ public final class ChartFormat {
/**
* The new category as text value, defaulting to <code>true</code>.
*/
@NotNull
public ChartFormat categoryAsText(boolean newCategoryAsText) {
return new ChartFormat(
output,
@ -302,6 +315,7 @@ public final class ChartFormat {
/**
* The new value source column numbers, defaulting to <code>{ 1 }</code>.
*/
@NotNull
public ChartFormat values(int... newValues) {
return new ChartFormat(
output,
@ -323,6 +337,7 @@ public final class ChartFormat {
/**
* The value source column numbers.
*/
@NotNull
public int[] values() {
return values;
}
@ -330,6 +345,7 @@ public final class ChartFormat {
/**
* The new column shades, defaulting to <code>{ 'X' }</code>.
*/
@NotNull
public ChartFormat shades(char... newShades) {
return new ChartFormat(
output,
@ -351,6 +367,7 @@ public final class ChartFormat {
/**
* The value column shades.
*/
@NotNull
public char[] shades() {
return shades;
}
@ -358,6 +375,7 @@ public final class ChartFormat {
/**
* Whether to show legends, defaulting to <code>true</code>.
*/
@NotNull
public ChartFormat showLegends(boolean newShowHorizontalLegend, boolean newShowVerticalLegend) {
return new ChartFormat(
output,
@ -379,6 +397,7 @@ public final class ChartFormat {
/**
* Whether to show the horizontal legend, defaulting to <code>true</code>.
*/
@NotNull
public ChartFormat showHorizontalLegend(boolean newShowHorizontalLegend) {
return showLegends(newShowHorizontalLegend, showVerticalLegend);
}
@ -393,6 +412,7 @@ public final class ChartFormat {
/**
* Whether to show the vertical legend, defaulting to <code>true</code>.
*/
@NotNull
public ChartFormat showVerticalLegend(boolean newShowVerticalLegend) {
return showLegends(showHorizontalLegend, newShowVerticalLegend);
}
@ -407,6 +427,7 @@ public final class ChartFormat {
/**
* The new newline character, defaulting to <code>\n</code>.
*/
@NotNull
public ChartFormat newline(String newNewline) {
return new ChartFormat(
output,
@ -428,6 +449,7 @@ public final class ChartFormat {
/**
* The newline character.
*/
@NotNull
public String newline() {
return newline;
}
@ -435,6 +457,7 @@ public final class ChartFormat {
/**
* The new numeric format, defaulting to <code>###,###.00</code>.
*/
@NotNull
public ChartFormat numericFormat(DecimalFormat newNumericFormat) {
return new ChartFormat(
output,
@ -456,6 +479,7 @@ public final class ChartFormat {
/**
* The numeric format.
*/
@NotNull
public DecimalFormat numericFormat() {
return numericFormat;
}

View File

@ -543,6 +543,13 @@ public interface Configuration extends Serializable {
@NotNull
ConverterProvider converterProvider();
/**
* Get the configured <code>FormattingProvider</code> from this
* configuration.
*/
@NotNull
FormattingProvider formattingProvider();
@ -1195,6 +1202,19 @@ public interface Configuration extends Serializable {
@NotNull
Configuration set(ConverterProvider newConverterProvider);
/**
* Change this configuration to hold a new formatting provider.
* <p>
* This method is not thread-safe and should not be used in globally
* available <code>Configuration</code> objects.
*
* @param newFormattingProvider The new formatting provider to be contained
* in the changed configuration.
* @return The changed configuration.
*/
@NotNull
Configuration set(FormattingProvider newFormattingProvider);
@ -1801,6 +1821,17 @@ public interface Configuration extends Serializable {
@NotNull
Configuration derive(ConverterProvider newConverterProvider);
/**
* Create a derived configuration from this one, with new formatting
* provider.
*
* @param newFormattingProvider The new formatting provider to be contained
* in the derived configuration.
* @return The derived configuration.
*/
@NotNull
Configuration derive(FormattingProvider newFormattingProvider);

View File

@ -0,0 +1,116 @@
/*
* 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.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import org.jooq.impl.DefaultExecuteListener;
import org.jooq.impl.DefaultFormattingProvider;
import org.jetbrains.annotations.NotNull;
/**
* An SPI that allows for overriding certain formatting defaults.
* <p>
* For convenience, consider extending {@link DefaultFormattingProvider} instead
* of implementing this interface. This will prevent compilation errors in
* future versions of jOOQ, when this interface might get new methods.
*
* @author Lukas Eder
*/
public interface FormattingProvider {
/**
* The {@link TXTFormat} to use when calling {@link Formattable#format()}
* and related methods, defaulting to {@link TXTFormat#DEFAULT}.
*/
@NotNull
TXTFormat txtFormat();
/**
* The {@link CSVFormat} to use when calling {@link Formattable#formatCSV()}
* and related methods, defaulting to {@link CSVFormat#DEFAULT}.
*/
@NotNull
CSVFormat csvFormat();
/**
* The {@link JSONFormat} to use when calling
* {@link Formattable#formatJSON()} and related methods on results,
* defaulting to {@link JSONFormat#DEFAULT_FOR_RESULTS}.
*/
@NotNull
JSONFormat jsonFormatForResults();
/**
* The {@link JSONFormat} to use when calling
* {@link Formattable#formatJSON()} and related methods on records,
* defaulting to {@link JSONFormat#DEFAULT_FOR_RECORDS}.
*/
@NotNull
JSONFormat jsonFormatForRecords();
/**
* The {@link XMLFormat} to use when calling {@link Formattable#formatXML()}
* and related methods on results, defaulting to
* {@link XMLFormat#DEFAULT_FOR_RESULTS}.
*/
@NotNull
XMLFormat xmlFormatForResults();
/**
* The {@link XMLFormat} to use when calling {@link Formattable#formatXML()}
* and related methods on records, defaulting to
* {@link XMLFormat#DEFAULT_FOR_RECORDS}.
*/
@NotNull
XMLFormat xmlFormatForRecords();
/**
* The {@link ChartFormat} to use when calling
* {@link Formattable#formatChart()} and related methods, defaulting to
* {@link ChartFormat#DEFAULT}.
*/
@NotNull
ChartFormat chartFormat();
/**
* The formatting display width in a monospaced font, which may diverge from
* {@link String#length()} e.g. if the string contains a
* {@link Character#isIdeographic(int)} character.
*/
int width(String string);
}

View File

@ -39,6 +39,8 @@ package org.jooq;
import static org.jooq.tools.StringUtils.rightPad;
import org.jetbrains.annotations.NotNull;
/**
* A JSON formatting type, which can be used to configure JSON imports /
* exports.
@ -125,6 +127,7 @@ public final class JSONFormat {
/**
* The new value for the formatting flag, defaulting to <code>false</code>.
*/
@NotNull
public final JSONFormat format(boolean newFormat) {
return new JSONFormat(
newFormat,
@ -149,6 +152,7 @@ public final class JSONFormat {
/**
* The new newline character, defaulting to <code>\n</code>.
*/
@NotNull
public final JSONFormat newline(String newNewline) {
return new JSONFormat(
format,
@ -166,6 +170,7 @@ public final class JSONFormat {
/**
* The formatting flag.
*/
@NotNull
public final String newline() {
return format ? newline : "";
}
@ -173,6 +178,7 @@ public final class JSONFormat {
/**
* The new global indentation size applied on all levels, defaulting to <code>0</code>.
*/
@NotNull
public final JSONFormat globalIndent(int newGlobalIndent) {
return new JSONFormat(
format,
@ -197,6 +203,7 @@ public final class JSONFormat {
/**
* The new indentation size per level value, defaulting to <code>2</code>.
*/
@NotNull
public final JSONFormat indent(int newIndent) {
return new JSONFormat(
format,
@ -221,6 +228,7 @@ public final class JSONFormat {
/**
* Convenience method to get an indentation string at a given level.
*/
@NotNull
public final String indentString(int level) {
int i = level + globalIndent / indent;
@ -236,6 +244,7 @@ public final class JSONFormat {
* Whether to emit a header row with column names, defaulting to
* <code>true</code>.
*/
@NotNull
public final JSONFormat header(boolean newHeader) {
return new JSONFormat(
format,
@ -262,6 +271,7 @@ public final class JSONFormat {
* The record format to be applied, defaulting to
* {@link RecordFormat#ARRAY}.
*/
@NotNull
public final JSONFormat recordFormat(RecordFormat newRecordFormat) {
return new JSONFormat(
format,
@ -280,6 +290,7 @@ public final class JSONFormat {
* The record format to be applied, defaulting to
* {@link RecordFormat#ARRAY}.
*/
@NotNull
public final RecordFormat recordFormat() {
return recordFormat;
}
@ -287,6 +298,7 @@ public final class JSONFormat {
/**
* Whether to wrap single column records in the {@link #recordFormat()}.
*/
@NotNull
public final JSONFormat wrapSingleColumnRecords(boolean newWrapSingleColumnRecords) {
return new JSONFormat(
format,
@ -312,6 +324,7 @@ public final class JSONFormat {
* Whether nested {@link JSON} or {@link JSONB} content should be quoted
* like a string, or nested into JSON formatted output.
*/
@NotNull
public final JSONFormat quoteNested(boolean newQuoteNested) {
return new JSONFormat(
format,

View File

@ -37,6 +37,7 @@
*/
package org.jooq;
import org.jetbrains.annotations.NotNull;
/**
* A text formatting type, which can be used to configure text imports /
@ -100,6 +101,7 @@ public final class TXTFormat {
/**
* The maximum number of rows to be included in the format, defaulting to all rows.
*/
@NotNull
public TXTFormat maxRows(int newMaxRows) {
return new TXTFormat(
newMaxRows,
@ -124,6 +126,7 @@ public final class TXTFormat {
/**
* The minimum column width, defaulting to 4
*/
@NotNull
public TXTFormat minColWidth(int newMinColWidth) {
return new TXTFormat(
maxRows,
@ -145,10 +148,10 @@ public final class TXTFormat {
return minColWidth;
}
/**
* The minimum column width, defaulting to no limit.
*/
@NotNull
public TXTFormat maxColWidth(int newMaxColWidth) {
return new TXTFormat(
maxRows,
@ -174,6 +177,7 @@ public final class TXTFormat {
* Whether the horizontal table border (top and bottom line) should be
* displayed.
*/
@NotNull
public TXTFormat horizontalTableBorder(boolean newHorizontalTableBorder) {
return new TXTFormat(
maxRows,
@ -200,6 +204,7 @@ public final class TXTFormat {
* Whether the horizontal header border (line between header and data cells)
* should be displayed.
*/
@NotNull
public TXTFormat horizontalHeaderBorder(boolean newHorizontalHeaderBorder) {
return new TXTFormat(
maxRows,
@ -226,6 +231,7 @@ public final class TXTFormat {
* Whether the horizontal cell border (line between data cells) should be
* displayed.
*/
@NotNull
public TXTFormat horizontalCellBorder(boolean newHorizontalCellBorder) {
return new TXTFormat(
maxRows,
@ -252,6 +258,7 @@ public final class TXTFormat {
* Whether the vertical table border (left and right most lines) should be
* displayed.
*/
@NotNull
public TXTFormat verticalTableBorder(boolean newVerticalTableBorder) {
return new TXTFormat(
maxRows,
@ -278,6 +285,7 @@ public final class TXTFormat {
* Whether the vertical cell borders (lines between data cells) should be
* displayed.
*/
@NotNull
public TXTFormat verticalCellBorder(boolean newVerticalCellBorder) {
return new TXTFormat(
maxRows,
@ -304,6 +312,7 @@ public final class TXTFormat {
* Whether horizontal and vertical lines should be intersected with a
* <code>'+'</code> symbol.
*/
@NotNull
public TXTFormat intersectLines(boolean newIntersectLines) {
return new TXTFormat(
maxRows,

View File

@ -39,6 +39,8 @@ package org.jooq;
import static org.jooq.tools.StringUtils.rightPad;
import org.jetbrains.annotations.NotNull;
/**
* An XML formatting type, which can be used to configure XML imports / exports.
* <p>
@ -106,6 +108,7 @@ public final class XMLFormat {
/**
* The new value for the xmlns flag, defaulting to <code>true</code>.
*/
@NotNull
public final XMLFormat xmlns(boolean newXmlns) {
return new XMLFormat(
newXmlns,
@ -130,6 +133,7 @@ public final class XMLFormat {
/**
* The new value for the formatting flag, defaulting to <code>false</code>.
*/
@NotNull
public final XMLFormat format(boolean newFormat) {
return new XMLFormat(
xmlns,
@ -154,6 +158,7 @@ public final class XMLFormat {
/**
* The new newline character, defaulting to <code>\n</code>.
*/
@NotNull
public final XMLFormat newline(String newNewline) {
return new XMLFormat(
xmlns,
@ -171,6 +176,7 @@ public final class XMLFormat {
/**
* The formatting flag.
*/
@NotNull
public final String newline() {
return format ? newline : "";
}
@ -178,6 +184,7 @@ public final class XMLFormat {
/**
* The new global indentation size applied on all levels, defaulting to <code>0</code>.
*/
@NotNull
public final XMLFormat globalIndent(int newGlobalIndent) {
return new XMLFormat(
xmlns,
@ -202,6 +209,7 @@ public final class XMLFormat {
/**
* The new indentation size per level value, defaulting to <code>2</code>.
*/
@NotNull
public final XMLFormat indent(int newIndent) {
return new XMLFormat(
xmlns,
@ -226,6 +234,7 @@ public final class XMLFormat {
/**
* Convenience method to get an indentation string at a given level.
*/
@NotNull
public final String indentString(int level) {
int i = level + globalIndent / indent;
@ -246,6 +255,7 @@ public final class XMLFormat {
* This flag is ignored on {@link Record#formatXML(XMLFormat)} and similar
* methods.
*/
@NotNull
public final XMLFormat header(boolean newHeader) {
return new XMLFormat(
xmlns,
@ -271,6 +281,7 @@ public final class XMLFormat {
* The record format to be applied, defaulting to
* {@link RecordFormat#VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE}.
*/
@NotNull
public final XMLFormat recordFormat(RecordFormat newRecordFormat) {
return new XMLFormat(
xmlns,
@ -289,6 +300,7 @@ public final class XMLFormat {
* The record format to be applied, defaulting to
* {@link RecordFormat#VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE}.
*/
@NotNull
public final RecordFormat recordFormat() {
return recordFormat;
}
@ -297,6 +309,7 @@ public final class XMLFormat {
* Whether nested {@link XML} content should be quoted like a string, or
* nested into XML formatted output.
*/
@NotNull
public final XMLFormat quoteNested(boolean newQuoteNested) {
return new XMLFormat(
xmlns,

View File

@ -39,12 +39,14 @@ package org.jooq.impl;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.List;
import org.jooq.Attachable;
import org.jooq.CSVFormat;
import org.jooq.ChartFormat;
import org.jooq.Configuration;
import org.jooq.Field;
import org.jooq.Formattable;
import org.jooq.JSONFormat;
@ -62,16 +64,51 @@ import org.xml.sax.SAXException;
*
* @author Lukas Eder
*/
abstract class AbstractFormattable implements Formattable, Serializable {
abstract class AbstractFormattable implements Formattable, Attachable {
Configuration configuration;
AbstractFormattable(Configuration configuration) {
this.configuration = configuration;
}
// -------------------------------------------------------------------------
// The Attachable API
// -------------------------------------------------------------------------
abstract List<? extends Attachable> getAttachables();
@Override
public final void attach(Configuration c) {
configuration = c;
for (Attachable attachable : getAttachables())
if (attachable != null)
attachable.attach(c);
}
@Override
public final void detach() {
attach(null);
}
@Override
public final Configuration configuration() {
return configuration;
}
// -------------------------------------------------------------------------
// The Formattable API
// -------------------------------------------------------------------------
@Override
public final String format() {
return format(TXTFormat.DEFAULT);
return format(Tools.configuration(this).formattingProvider().txtFormat());
}
@Override
public final String format(int maxRecords) {
return format(TXTFormat.DEFAULT.maxRows(maxRecords));
return format(Tools.configuration(this).formattingProvider().txtFormat().maxRows(maxRecords));
}
@Override
@ -98,88 +135,42 @@ abstract class AbstractFormattable implements Formattable, Serializable {
@Override
public final void format(Writer writer) {
format(writer, TXTFormat.DEFAULT);
format(writer, Tools.configuration(this).formattingProvider().txtFormat());
}
@Override
public final void format(Writer writer, int maxRecords) {
format(writer, TXTFormat.DEFAULT.maxRows(maxRecords));
format(writer, Tools.configuration(this).formattingProvider().txtFormat().maxRows(maxRecords));
}
@Override
public final String formatCSV() {
return formatCSV(true);
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat());
}
@Override
public final String formatCSV(boolean header) {
StringWriter writer = new StringWriter();
formatCSV(writer, header);
return writer.toString();
}
@Override
public final void formatCSV(OutputStream stream) {
formatCSV(stream, true);
}
@Override
public final void formatCSV(OutputStream stream, boolean header) {
formatCSV(new OutputStreamWriter(stream), header);
}
@Override
public final void formatCSV(Writer writer) {
formatCSV(writer, true);
}
@Override
public final void formatCSV(Writer writer, boolean header) {
formatCSV(writer, header, ',', "\"\"");
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat().header(header));
}
@Override
public final String formatCSV(char delimiter) {
return formatCSV(true, delimiter);
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat().delimiter(delimiter));
}
@Override
public final String formatCSV(boolean header, char delimiter) {
StringWriter writer = new StringWriter();
formatCSV(writer, header, delimiter);
return writer.toString();
}
@Override
public final void formatCSV(OutputStream stream, char delimiter) {
formatCSV(stream, true, delimiter);
}
@Override
public final void formatCSV(OutputStream stream, boolean header, char delimiter) {
formatCSV(new OutputStreamWriter(stream), header, delimiter);
}
@Override
public final void formatCSV(Writer writer, char delimiter) {
formatCSV(writer, true, delimiter);
}
@Override
public final void formatCSV(Writer writer, boolean header, char delimiter) {
formatCSV(writer, header, delimiter, "\"\"");
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat().header(header).delimiter(delimiter));
}
@Override
public final String formatCSV(char delimiter, String nullString) {
return formatCSV(true, delimiter, nullString);
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat().delimiter(delimiter).nullString(nullString));
}
@Override
public final String formatCSV(boolean header, char delimiter, String nullString) {
StringWriter writer = new StringWriter();
formatCSV(writer, header, delimiter, nullString);
return writer.toString();
return formatCSV(Tools.configuration(this).formattingProvider().csvFormat().header(header).delimiter(delimiter).nullString(nullString));
}
@Override
@ -189,9 +180,29 @@ abstract class AbstractFormattable implements Formattable, Serializable {
return writer.toString();
}
@Override
public final void formatCSV(OutputStream stream) {
formatCSV(new OutputStreamWriter(stream));
}
@Override
public final void formatCSV(OutputStream stream, boolean header) {
formatCSV(new OutputStreamWriter(stream), header);
}
@Override
public final void formatCSV(OutputStream stream, char delimiter) {
formatCSV(stream, Tools.configuration(this).formattingProvider().csvFormat().delimiter(delimiter));
}
@Override
public final void formatCSV(OutputStream stream, boolean header, char delimiter) {
formatCSV(new OutputStreamWriter(stream), header, delimiter);
}
@Override
public final void formatCSV(OutputStream stream, char delimiter, String nullString) {
formatCSV(stream, true, delimiter, nullString);
formatCSV(new OutputStreamWriter(stream), delimiter, nullString);
}
@Override
@ -204,14 +215,34 @@ abstract class AbstractFormattable implements Formattable, Serializable {
formatCSV(new OutputStreamWriter(stream), format);
}
@Override
public final void formatCSV(Writer writer) {
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat());
}
@Override
public final void formatCSV(Writer writer, boolean header) {
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat().header(header));
}
@Override
public final void formatCSV(Writer writer, char delimiter) {
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat().delimiter(delimiter));
}
@Override
public final void formatCSV(Writer writer, boolean header, char delimiter) {
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat().header(header).delimiter(delimiter));
}
@Override
public final void formatCSV(Writer writer, char delimiter, String nullString) {
formatCSV(writer, true, delimiter, nullString);
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat().delimiter(delimiter).nullString(nullString));
}
@Override
public final void formatCSV(Writer writer, boolean header, char delimiter, String nullString) {
formatCSV(writer, new CSVFormat().header(header).delimiter(delimiter).nullString(nullString));
formatCSV(writer, Tools.configuration(this).formattingProvider().csvFormat().header(header).delimiter(delimiter).nullString(nullString));
}
abstract JSONFormat defaultJSONFormat();
@ -300,7 +331,7 @@ abstract class AbstractFormattable implements Formattable, Serializable {
@Override
public final void formatChart(Writer writer) {
formatChart(writer, ChartFormat.DEFAULT);
formatChart(writer, Tools.configuration(this).formattingProvider().chartFormat());
}
@Override

View File

@ -1036,11 +1036,6 @@ abstract class AbstractRecord extends AbstractStore implements Record {
asResult().formatCSV(writer, format);
}
@Override
final JSONFormat defaultJSONFormat() {
return JSONFormat.DEFAULT_FOR_RECORDS;
}
@Override
public final void formatJSON(Writer writer, JSONFormat format) {
if (format.header())
@ -1063,11 +1058,6 @@ abstract class AbstractRecord extends AbstractStore implements Record {
}
}
@Override
final XMLFormat defaultXMLFormat() {
return XMLFormat.DEFAULT_FOR_RECORDS;
}
@Override
public final void formatXML(Writer writer, XMLFormat format) {
if (format.header())

View File

@ -62,7 +62,6 @@ import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Stream;
import javax.xml.bind.DatatypeConverter;
import javax.xml.parsers.DocumentBuilder;
@ -76,15 +75,12 @@ import org.jooq.Configuration;
import org.jooq.Constants;
import org.jooq.Cursor;
import org.jooq.DSLContext;
import org.jooq.DataType;
import org.jooq.EnumType;
import org.jooq.Field;
import org.jooq.Fields;
import org.jooq.Formattable;
import org.jooq.JSON;
import org.jooq.JSONB;
import org.jooq.JSONFormat;
import org.jooq.Name;
import org.jooq.Param;
import org.jooq.Record;
import org.jooq.Result;
@ -116,11 +112,11 @@ import org.xml.sax.helpers.DefaultHandler;
*/
abstract class AbstractResult<R extends Record> extends AbstractFormattable implements FieldsTrait, Iterable<R> {
final AbstractRow<R> fields;
Configuration configuration;
final AbstractRow<R> fields;
AbstractResult(Configuration configuration, AbstractRow<R> row) {
this.configuration = configuration;
super(configuration);
this.fields = row;
}
@ -459,7 +455,7 @@ abstract class AbstractResult<R extends Record> extends AbstractFormattable impl
@Override
final JSONFormat defaultJSONFormat() {
return JSONFormat.DEFAULT_FOR_RESULTS;
return Tools.configuration(this).formattingProvider().jsonFormatForResults();
}
@Override
@ -743,7 +739,7 @@ abstract class AbstractResult<R extends Record> extends AbstractFormattable impl
@Override
final XMLFormat defaultXMLFormat() {
return XMLFormat.DEFAULT_FOR_RESULTS;
return Tools.configuration(this).formattingProvider().xmlFormatForResults();
}
@Override

View File

@ -1303,6 +1303,9 @@ public abstract class AbstractRoutine<T> extends AbstractNamed implements Routin

View File

@ -38,13 +38,14 @@
package org.jooq.impl;
import java.util.Arrays;
import java.util.List;
// ...
import org.jooq.Attachable;
import org.jooq.Configuration;
import org.jooq.DSLContext;
import org.jooq.JSONFormat;
import org.jooq.Record;
import org.jooq.XMLFormat;
/**
* A common base class for {@link Record} and {@link ArrayRecord}
@ -54,43 +55,20 @@ import org.jooq.Record;
*
* @author Lukas Eder
*/
abstract class AbstractStore extends AbstractFormattable implements Attachable {
private Configuration configuration;
abstract class AbstractStore extends AbstractFormattable {
AbstractStore() {
this(null);
}
AbstractStore(Configuration configuration) {
this.configuration = configuration;
super(configuration);
}
// -------------------------------------------------------------------------
// The Attachable API
// -------------------------------------------------------------------------
abstract List<Attachable> getAttachables();
@Override
public final void attach(Configuration c) {
configuration = c;
for (Attachable attachable : getAttachables())
if (attachable != null)
attachable.attach(c);
}
@Override
public final void detach() {
attach(null);
}
@Override
public final Configuration configuration() {
return configuration;
}
/**
* This method is used in generated code!
*
@ -102,6 +80,20 @@ abstract class AbstractStore extends AbstractFormattable implements Attachable {
return DSL.using(configuration());
}
// -------------------------------------------------------------------------
// The Formattable API
// -------------------------------------------------------------------------
@Override
final JSONFormat defaultJSONFormat() {
return Tools.configuration(this).formattingProvider().jsonFormatForRecords();
}
@Override
final XMLFormat defaultXMLFormat() {
return Tools.configuration(this).formattingProvider().xmlFormatForRecords();
}
// -------------------------------------------------------------------------
// equals and hashCode
// -------------------------------------------------------------------------

View File

@ -403,16 +403,6 @@ package org.jooq.impl;

View File

@ -378,16 +378,6 @@ package org.jooq.impl;

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static java.util.Collections.emptyList;
// ...
import static org.jooq.impl.RowField.NO_NATIVE_SUPPORT;
import static org.jooq.impl.Tools.embeddedFields;
@ -67,10 +68,12 @@ import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.Supplier;
import org.jooq.Attachable;
import org.jooq.BindingGetResultSetContext;
import org.jooq.Converter;
import org.jooq.ExecuteContext;
@ -144,6 +147,19 @@ final class CursorImpl<R extends Record> extends AbstractCursor<R> {
this.intern = null;
}
// -------------------------------------------------------------------------
// XXX: Attachable API
// -------------------------------------------------------------------------
@Override
final List<? extends Attachable> getAttachables() {
return emptyList();
}
// -------------------------------------------------------------------------
// XXX: Cursor API
// -------------------------------------------------------------------------

View File

@ -66,6 +66,7 @@ import org.jooq.DiagnosticsListenerProvider;
import org.jooq.ExecuteListener;
import org.jooq.ExecuteListenerProvider;
import org.jooq.ExecutorProvider;
import org.jooq.FormattingProvider;
import org.jooq.MetaProvider;
import org.jooq.MigrationListenerProvider;
// ...
@ -131,6 +132,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
private transient UnwrapperProvider unwrapperProvider;
private transient CharsetProvider charsetProvider;
private transient ConverterProvider converterProvider;
private transient FormattingProvider formattingProvider;
@ -191,6 +193,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
null,
null,
null,
null,
@ -231,6 +234,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
configuration.unwrapperProvider,
configuration.charsetProvider,
configuration.converterProvider,
configuration.formattingProvider,
@ -270,6 +274,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
UnwrapperProvider unwrapperProvider,
CharsetProvider charsetProvider,
ConverterProvider converterProvider,
FormattingProvider formattingProvider,
@ -298,6 +303,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
set(unwrapperProvider);
set(charsetProvider);
set(converterProvider);
set(formattingProvider);
@ -361,6 +367,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -394,6 +401,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -427,6 +435,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -460,6 +469,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -498,6 +508,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -531,6 +542,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -564,6 +576,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -602,6 +615,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -640,6 +654,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -673,6 +688,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -706,6 +722,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -739,6 +756,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -772,6 +790,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -805,6 +824,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -838,6 +858,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -876,6 +897,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
newUnwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -909,6 +931,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
newCharsetProvider,
converterProvider,
formattingProvider,
@ -942,6 +965,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
newConverterProvider,
formattingProvider,
@ -952,6 +976,41 @@ public class DefaultConfiguration extends AbstractConfiguration {
);
}
@Override
public final Configuration derive(FormattingProvider newFormattingProvider) {
return new DefaultConfiguration(
connectionProvider,
interpreterConnectionProvider,
systemConnectionProvider,
connectionFactory,
metaProvider,
commitProvider,
executorProvider,
cacheProvider,
transactionProvider,
recordMapperProvider,
recordUnmapperProvider,
recordListenerProviders,
executeListenerProviders,
migrationListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
unwrapperProvider,
charsetProvider,
converterProvider,
newFormattingProvider,
clock,
dialect,
settings,
data
);
}
@ -1011,6 +1070,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -1044,6 +1104,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -1077,6 +1138,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider,
charsetProvider,
converterProvider,
formattingProvider,
@ -1275,6 +1337,12 @@ public class DefaultConfiguration extends AbstractConfiguration {
return this;
}
@Override
public final Configuration set(FormattingProvider newFormattingProvider) {
this.formattingProvider = newFormattingProvider;
return this;
}
@ -1712,6 +1780,13 @@ public class DefaultConfiguration extends AbstractConfiguration {
: new DefaultConverterProvider();
}
@Override
public final FormattingProvider formattingProvider() {
return formattingProvider != null
? formattingProvider
: new DefaultFormattingProvider();
}
@ -1827,6 +1902,10 @@ public class DefaultConfiguration extends AbstractConfiguration {
? converterProvider
: null);
oos.writeObject(formattingProvider instanceof Serializable
? formattingProvider
: null);
// [#7062] Exclude reflection cache from serialisation
for (Entry<Object, Object> entry : data.entrySet()) {
if (entry.getKey() instanceof CacheType)
@ -1874,6 +1953,7 @@ public class DefaultConfiguration extends AbstractConfiguration {
unwrapperProvider = (UnwrapperProvider) ois.readObject();
charsetProvider = (CharsetProvider) ois.readObject();
converterProvider = (ConverterProvider) ois.readObject();
formattingProvider = (FormattingProvider) ois.readObject();
data = new ConcurrentHashMap<>();
Object key;

View File

@ -0,0 +1,93 @@
/*
* 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.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import org.jooq.CSVFormat;
import org.jooq.ChartFormat;
import org.jooq.FormattingProvider;
import org.jooq.JSONFormat;
import org.jooq.TXTFormat;
import org.jooq.XMLFormat;
/**
* A default implementation for the {@link FormattingProvider}.
*
* @author Lukas Eder
*/
public class DefaultFormattingProvider implements FormattingProvider {
@Override
public TXTFormat txtFormat() {
return TXTFormat.DEFAULT;
}
@Override
public CSVFormat csvFormat() {
return CSVFormat.DEFAULT;
}
@Override
public JSONFormat jsonFormatForResults() {
return JSONFormat.DEFAULT_FOR_RESULTS;
}
@Override
public JSONFormat jsonFormatForRecords() {
return JSONFormat.DEFAULT_FOR_RECORDS;
}
@Override
public XMLFormat xmlFormatForResults() {
return XMLFormat.DEFAULT_FOR_RESULTS;
}
@Override
public XMLFormat xmlFormatForRecords() {
return XMLFormat.DEFAULT_FOR_RECORDS;
}
@Override
public ChartFormat chartFormat() {
return ChartFormat.DEFAULT;
}
@Override
public int width(String string) {
return string.length();
}
}

View File

@ -39,7 +39,9 @@ package org.jooq.impl;
import java.sql.ResultSet;
import java.util.Iterator;
import java.util.List;
import org.jooq.Attachable;
import org.jooq.Record;
import org.jooq.Result;
@ -47,8 +49,9 @@ import org.jooq.Result;
* @author Lukas Eder
*/
final class ResultAsCursor<R extends Record> extends AbstractCursor<R> {
private final Result<R> result;
private int index;
private final Result<R> result;
private int index;
@SuppressWarnings("unchecked")
ResultAsCursor(Result<R> result) {
@ -57,6 +60,19 @@ final class ResultAsCursor<R extends Record> extends AbstractCursor<R> {
this.result = result;
}
// -------------------------------------------------------------------------
// XXX: Attachable API
// -------------------------------------------------------------------------
@Override
final List<? extends Attachable> getAttachables() {
return result;
}
// -------------------------------------------------------------------------
// XXX: Cursor API
// -------------------------------------------------------------------------
@Override
public final Iterator<R> iterator() {
return result.iterator();

View File

@ -56,6 +56,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import org.jooq.Attachable;
import org.jooq.Configuration;
import org.jooq.Converter;
import org.jooq.Field;
@ -123,22 +124,8 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
// -------------------------------------------------------------------------
@Override
public final void attach(Configuration c) {
this.configuration = c;
for (R record : records)
if (record != null)
record.attach(c);
}
@Override
public final void detach() {
attach(null);
}
@Override
public final Configuration configuration() {
return configuration;
final List<? extends Attachable> getAttachables() {
return records;
}
// -------------------------------------------------------------------------
@ -1139,7 +1126,7 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public String toString() {
return format(TXTFormat.DEFAULT.maxRows(50).maxColWidth(50));
return format(Tools.configuration(this).formattingProvider().txtFormat().maxRows(50).maxColWidth(50));
}
@Override

View File

@ -60,15 +60,11 @@ import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.Routine;
import org.jooq.TXTFormat;
import org.jooq.VisitContext;
import org.jooq.impl.DSL;
import org.jooq.impl.DefaultExecuteListener;
import org.jooq.impl.DefaultVisitListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A default {@link ExecuteListener} that just logs events to java.util.logging,
* log4j, or slf4j using the {@link JooqLogger}
@ -161,7 +157,7 @@ public class LoggerListener extends DefaultExecuteListener {
@Override
public void resultEnd(ExecuteContext ctx) {
if (ctx.result() != null && log.isDebugEnabled()) {
log(ctx.result());
log(ctx.configuration(), ctx.result());
log.debug("Fetched row(s)", ctx.result().size());
}
}
@ -172,13 +168,13 @@ public class LoggerListener extends DefaultExecuteListener {
Result<Record> buffer = (Result<Record>) ctx.data(BUFFER);
if (buffer != null && !buffer.isEmpty()) {
log(buffer);
log(ctx.configuration(), buffer);
log.debug("Fetched row(s)", buffer.size() + (buffer.size() < maxRows() ? "" : " (or more)"));
}
}
private void log(Result<?> result) {
logMultiline("Fetched result", result.format(TXTFormat.DEFAULT.maxRows(maxRows()).maxColWidth(maxColWidth())), Level.FINE);
private void log(Configuration configuration, Result<?> result) {
logMultiline("Fetched result", result.format(configuration.formattingProvider().txtFormat().maxRows(maxRows()).maxColWidth(maxColWidth())), Level.FINE);
}
private int maxRows() {

View File

@ -55,6 +55,7 @@ import org.jooq.DSLContext;
import org.jooq.DiagnosticsListenerProvider;
import org.jooq.ExecuteListenerProvider;
import org.jooq.ExecutorProvider;
import org.jooq.FormattingProvider;
import org.jooq.MetaProvider;
import org.jooq.MigrationListenerProvider;
// ...
@ -230,6 +231,11 @@ public class MockConfiguration extends AbstractConfiguration {
return delegate.converterProvider();
}
@Override
public FormattingProvider formattingProvider() {
return delegate.formattingProvider();
}
@Override
public org.jooq.SchemaMapping schemaMapping() {
return delegate.schemaMapping();
@ -411,6 +417,12 @@ public class MockConfiguration extends AbstractConfiguration {
return this;
}
@Override
public Configuration set(FormattingProvider newFormattingProvider) {
delegate.set(newFormattingProvider);
return this;
}
@Override
public Configuration set(SQLDialect newDialect) {
delegate.set(newDialect);
@ -563,6 +575,11 @@ public class MockConfiguration extends AbstractConfiguration {
return new MockConfiguration(delegate.derive(newConverterProvider), provider);
}
@Override
public Configuration derive(FormattingProvider newFormattingProvider) {
return new MockConfiguration(delegate.derive(newFormattingProvider), provider);
}
@Override
public Configuration derive(SQLDialect newDialect) {
return new MockConfiguration(delegate.derive(newDialect), provider);