[jOOQ/jOOQ#9233] Use new Source API throughout the jOOQ API

- LoaderSourceStep.loadCSV
- LoaderSourceStep.loadJSON
- LoaderSourceStep.loadXML
This commit is contained in:
Lukas Eder 2019-09-17 18:07:18 +02:00
parent 44e82bdb63
commit 2c4a05b1d5
3 changed files with 183 additions and 126 deletions

View File

@ -197,6 +197,12 @@ public interface LoaderSourceStep<R extends Record> {
@Support
LoaderCSVStep<R> loadCSV(Reader reader);
/**
* Load CSV data.
*/
@Support
LoaderCSVStep<R> loadCSV(Source source);
/**
* Load XML data.
*/
@ -263,6 +269,12 @@ public interface LoaderSourceStep<R extends Record> {
@Support
LoaderXMLStep<R> loadXML(InputSource source);
/**
* Load XML data.
*/
@Support
LoaderXMLStep<R> loadXML(Source source);
/**
* Load JSON data.
*/
@ -323,4 +335,10 @@ public interface LoaderSourceStep<R extends Record> {
@Support
LoaderJSONStep<R> loadJSON(Reader reader);
/**
* Load JSON data.
*/
@Support
LoaderJSONStep<R> loadJSON(Source source);
}

View File

@ -38,98 +38,183 @@
package org.jooq;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import org.jooq.exception.IOException;
/**
* A source of text data.
*/
public final class Source {
private final String string;
private final byte[] bytes;
private final Charset charset;
private final Reader reader;
private final InputStream inputStream;
private final String string;
private final byte[] bytes;
private final String charsetName;
private final Charset charset;
private final CharsetDecoder charsetDecoder;
private final Reader reader;
private final InputStream inputStream;
private final File file;
private Source(
String string,
byte[] bytes,
String charsetName,
Charset charset,
CharsetDecoder charsetDecoder,
Reader reader,
InputStream inputStream
InputStream inputStream,
File file
) {
this.string = string;
this.bytes = bytes;
this.charsetName = charsetName;
this.charset = charset;
this.charsetDecoder = charsetDecoder;
this.reader = reader;
this.inputStream = inputStream;
this.file = file;
}
/**
* Create a source from a string.
*/
public static final Source of(String string) {
return new Source(string, null, null, null, null);
return new Source(string, null, null, null, null, null, null, null);
}
/**
* Create a source from binary data.
*/
public static final Source of(byte[] bytes) {
return new Source(null, bytes, null, null, null);
return of(bytes, (Charset) null);
}
/**
* Create a source from binary data using a specific character set.
*/
public static final Source of(byte[] bytes, String charsetName) {
return new Source(null, bytes, charsetName, null, null, null, null, null);
}
/**
* Create a source from binary data using a specific character set.
*/
public static final Source of(byte[] bytes, Charset charset) {
return new Source(null, bytes, charset, null, null);
return new Source(null, bytes, null, charset, null, null, null, null);
}
/**
* Create a source from binary data using a specific character set.
*/
public static final Source of(byte[] bytes, CharsetDecoder charsetDecoder) {
return new Source(null, bytes, null, null, charsetDecoder, null, null, null);
}
/**
* Create a source from a file.
*/
public static final Source of(File file) {
return new Source(null, null, null, null, null, null, null, file);
}
/**
* Create a source from a file using a specific character set.
*/
public static final Source of(File file, String charsetName) {
return new Source(null, null, charsetName, null, null, null, null, file);
}
/**
* Create a source from a file using a specific character set.
*/
public static final Source of(File file, Charset charset) {
return new Source(null, null, null, charset, null, null, null, file);
}
/**
* Create a source from a file using a specific character set.
*/
public static final Source of(File file, CharsetDecoder charsetDecoder) {
return new Source(null, null, null, null, charsetDecoder, null, null, file);
}
/**
* Create a source from a reader.
*/
public static final Source of(Reader reader) {
return new Source(null, null, null, reader, null);
return new Source(null, null, null, null, null, reader, null, null);
}
/**
* Create a source from an input stream.
*/
public static final Source of(InputStream inputStream) {
return new Source(null, null, null, null, inputStream);
return new Source(null, null, null, null, null, null, inputStream, null);
}
/**
* Create a source from an input stream using a specific character set.
*/
public static final Source of(InputStream inputStream, String charsetName) {
return new Source(null, null, charsetName, null, null, null, inputStream, null);
}
/**
* Create a source from an input stream using a specific character set.
*/
public static final Source of(InputStream inputStream, Charset charset) {
return new Source(null, null, charset, null, inputStream);
return new Source(null, null, null, charset, null, null, inputStream, null);
}
/**
* Create a source from an input stream using a specific character set.
*/
public static final Source of(InputStream inputStream, CharsetDecoder charsetDecoder) {
return new Source(null, null, null, null, charsetDecoder, null, inputStream, null);
}
/**
* Produce a reader from this source.
*
* @throws IOException When something goes wrong creating a reader from this
* source.
*/
public final Reader reader() {
if (string != null)
return new StringReader(string);
else if (bytes != null)
return inputStreamReader(new ByteArrayInputStream(bytes));
else if (reader != null)
return reader;
else if (inputStream != null)
return inputStreamReader(inputStream);
else
throw new IllegalStateException("Could not produce a reader from this source");
public final Reader reader() throws IOException {
try {
if (string != null)
return new StringReader(string);
else if (bytes != null)
return inputStreamReader(new ByteArrayInputStream(bytes));
else if (reader != null)
return reader;
else if (inputStream != null)
return inputStreamReader(inputStream);
else if (file != null)
return inputStreamReader(new FileInputStream(file));
else
throw new IllegalStateException("Could not produce a reader from this source");
}
catch (java.io.IOException e) {
throw new IOException(e.getMessage(), e);
}
}
private final Reader inputStreamReader(InputStream is) {
if (charset != null)
private final Reader inputStreamReader(InputStream is) throws UnsupportedEncodingException {
if (charsetName != null)
return new InputStreamReader(is, charsetName);
else if (charset != null)
return new InputStreamReader(is, charset);
else if (charsetDecoder != null)
return new InputStreamReader(is, charsetDecoder);
else
return new InputStreamReader(is);
}

View File

@ -41,13 +41,9 @@ import static org.jooq.impl.Tools.EMPTY_FIELD;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.sql.Connection;
@ -84,6 +80,7 @@ import org.jooq.LoaderXMLStep;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SelectQuery;
import org.jooq.Source;
import org.jooq.Table;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.LoaderConfigurationException;
@ -149,7 +146,7 @@ final class LoaderImpl<R extends Record> implements
private int bulk = BULK_NONE;
private int bulkAfter = 1;
private int content = CONTENT_CSV;
private final InputDelay data = new InputDelay();
private Source input;
private Iterator<? extends Object[]> arrays;
// CSV configuration data
@ -344,115 +341,109 @@ final class LoaderImpl<R extends Record> implements
@Override
public final LoaderImpl<R> loadCSV(File file) {
content = CONTENT_CSV;
data.file = file;
return this;
return loadCSV(Source.of(file));
}
@Override
public final LoaderImpl<R> loadCSV(File file, String charsetName) {
data.charsetName = charsetName;
return loadCSV(file);
return loadCSV(Source.of(file, charsetName));
}
@Override
public final LoaderImpl<R> loadCSV(File file, Charset cs) {
data.cs = cs;
return loadCSV(file);
return loadCSV(Source.of(file, cs));
}
@Override
public final LoaderImpl<R> loadCSV(File file, CharsetDecoder dec) {
data.dec = dec;
return loadCSV(file);
return loadCSV(Source.of(file, dec));
}
@Override
public final LoaderImpl<R> loadCSV(String csv) {
return loadCSV(new StringReader(csv));
return loadCSV(Source.of(csv));
}
@Override
public final LoaderImpl<R> loadCSV(InputStream stream) {
return loadCSV(new InputStreamReader(stream));
return loadCSV(Source.of(stream));
}
@Override
public final LoaderImpl<R> loadCSV(InputStream stream, String charsetName) throws UnsupportedEncodingException {
return loadCSV(new InputStreamReader(stream, charsetName));
public final LoaderImpl<R> loadCSV(InputStream stream, String charsetName) {
return loadCSV(Source.of(stream, charsetName));
}
@Override
public final LoaderImpl<R> loadCSV(InputStream stream, Charset cs) {
return loadCSV(new InputStreamReader(stream, cs));
return loadCSV(Source.of(stream, cs));
}
@Override
public final LoaderImpl<R> loadCSV(InputStream stream, CharsetDecoder dec) {
return loadCSV(new InputStreamReader(stream, dec));
return loadCSV(Source.of(stream, dec));
}
@Override
public final LoaderImpl<R> loadCSV(Reader reader) {
return loadCSV(Source.of(reader));
}
@Override
public final LoaderImpl<R> loadCSV(Source s) {
content = CONTENT_CSV;
data.reader = new BufferedReader(reader);
input = s;
return this;
}
@Override
public final LoaderImpl<R> loadXML(File file) {
content = CONTENT_XML;
data.file = file;
return this;
return loadXML(Source.of(file));
}
@Override
public final LoaderImpl<R> loadXML(File file, String charsetName) {
data.charsetName = charsetName;
return loadXML(file);
return loadXML(Source.of(file, charsetName));
}
@Override
public final LoaderImpl<R> loadXML(File file, Charset cs) {
data.cs = cs;
return loadXML(file);
return loadXML(Source.of(file, cs));
}
@Override
public final LoaderImpl<R> loadXML(File file, CharsetDecoder dec) {
data.dec = dec;
return loadXML(file);
return loadXML(Source.of(file, dec));
}
@Override
public final LoaderImpl<R> loadXML(String xml) {
return loadXML(new StringReader(xml));
return loadXML(Source.of(xml));
}
@Override
public final LoaderImpl<R> loadXML(InputStream stream) {
return loadXML(new InputStreamReader(stream));
return loadXML(Source.of(stream));
}
@Override
public final LoaderImpl<R> loadXML(InputStream stream, String charsetName) throws UnsupportedEncodingException {
return loadXML(new InputStreamReader(stream, charsetName));
public final LoaderImpl<R> loadXML(InputStream stream, String charsetName) {
return loadXML(Source.of(stream, charsetName));
}
@Override
public final LoaderImpl<R> loadXML(InputStream stream, Charset cs) {
return loadXML(new InputStreamReader(stream, cs));
return loadXML(Source.of(stream, cs));
}
@Override
public final LoaderImpl<R> loadXML(InputStream stream, CharsetDecoder dec) {
return loadXML(new InputStreamReader(stream, dec));
return loadXML(Source.of(stream, dec));
}
@Override
public final LoaderImpl<R> loadXML(Reader reader) {
content = CONTENT_XML;
throw new UnsupportedOperationException("This is not yet implemented");
return loadXML(Source.of(reader));
}
@Override
@ -461,60 +452,67 @@ final class LoaderImpl<R extends Record> implements
throw new UnsupportedOperationException("This is not yet implemented");
}
@Override
public final LoaderImpl<R> loadXML(Source s) {
content = CONTENT_XML;
input = s;
throw new UnsupportedOperationException("This is not yet implemented");
}
@Override
public final LoaderImpl<R> loadJSON(File file) {
content = CONTENT_JSON;
data.file = file;
return this;
return loadJSON(Source.of(file));
}
@Override
public final LoaderImpl<R> loadJSON(File file, String charsetName) {
data.charsetName = charsetName;
return loadJSON(file);
return loadJSON(Source.of(file, charsetName));
}
@Override
public final LoaderImpl<R> loadJSON(File file, Charset cs) {
data.cs = cs;
return loadJSON(file);
return loadJSON(Source.of(file, cs));
}
@Override
public final LoaderImpl<R> loadJSON(File file, CharsetDecoder dec) {
data.dec = dec;
return loadJSON(file);
return loadJSON(Source.of(file, dec));
}
@Override
public final LoaderImpl<R> loadJSON(String json) {
return loadJSON(new StringReader(json));
return loadJSON(Source.of(json));
}
@Override
public final LoaderImpl<R> loadJSON(InputStream stream) {
return loadJSON(new InputStreamReader(stream));
return loadJSON(Source.of(stream));
}
@Override
public final LoaderImpl<R> loadJSON(InputStream stream, String charsetName) throws UnsupportedEncodingException {
return loadJSON(new InputStreamReader(stream, charsetName));
public final LoaderImpl<R> loadJSON(InputStream stream, String charsetName) {
return loadJSON(Source.of(stream, charsetName));
}
@Override
public final LoaderImpl<R> loadJSON(InputStream stream, Charset cs) {
return loadJSON(new InputStreamReader(stream, cs));
return loadJSON(Source.of(stream, cs));
}
@Override
public final LoaderImpl<R> loadJSON(InputStream stream, CharsetDecoder dec) {
return loadJSON(new InputStreamReader(stream, dec));
return loadJSON(Source.of(stream, dec));
}
@Override
public final LoaderImpl<R> loadJSON(Reader reader) {
return loadJSON(Source.of(reader));
}
@Override
public final LoaderImpl<R> loadJSON(Source s) {
content = CONTENT_JSON;
data.reader = new BufferedReader(reader);
input = s;
return this;
}
@ -652,7 +650,7 @@ final class LoaderImpl<R extends Record> implements
BufferedReader reader = null;
try {
reader = data.reader();
reader = new BufferedReader(input.reader());
Result<Record> r = new JSONReader(create).read(reader);
source = r.fields();
@ -678,11 +676,11 @@ final class LoaderImpl<R extends Record> implements
try {
if (ignoreRows == 1) {
reader = new CSVReader(data.reader(), separator, quote, 0);
reader = new CSVReader(input.reader(), separator, quote, 0);
source = Tools.fieldsByName(reader.next());
}
else {
reader = new CSVReader(data.reader(), separator, quote, ignoreRows);
reader = new CSVReader(input.reader(), separator, quote, ignoreRows);
}
executeSQL(reader);
@ -995,48 +993,4 @@ final class LoaderImpl<R extends Record> implements
return stored;
}
}
/**
* An "input delay" type.
* <p>
* [#4593] To make sure we do not spill file handles due to improper
* resource shutdown (e.g. when a loader is created but never executed),
* this type helps delaying creating resources from input until the input is
* really needed.
*/
private class InputDelay {
// Either, we already have an external Reader resource, in case of which
// client code is responsible for resource management...
BufferedReader reader;
// ... or we create the resource explicitly as late as possible
File file;
String charsetName;
Charset cs;
CharsetDecoder dec;
BufferedReader reader() throws IOException {
if (reader != null)
return reader;
if (file != null) {
try {
if (charsetName != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName));
else if (cs != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), cs));
else if (dec != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), dec));
else
return new BufferedReader(new InputStreamReader(new FileInputStream(file)));
}
catch (Exception e) {
throw new IOException(e);
}
}
return null;
}
}
}