embulk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +33 -0
- data/README.md +117 -0
- data/Rakefile +58 -0
- data/bin/embulk +63 -0
- data/build.gradle +149 -0
- data/embulk-cli/build.gradle +6 -0
- data/embulk-cli/pom.xml +94 -0
- data/embulk-cli/src/main/java/org/embulk/cli/Main.java +15 -0
- data/embulk-core/build.gradle +6 -0
- data/embulk-core/pom.xml +143 -0
- data/embulk-core/src/main/java/org/embulk/EmbulkService.java +39 -0
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +199 -0
- data/embulk-core/src/main/java/org/embulk/command/TablePrinter.java +119 -0
- data/embulk-core/src/main/java/org/embulk/config/CommitReport.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Config.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigDefault.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigException.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +83 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSource.java +35 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +208 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceSerDe.java +80 -0
- data/embulk-core/src/main/java/org/embulk/config/GenericTypeReference.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ModelManager.java +125 -0
- data/embulk-core/src/main/java/org/embulk/config/NextConfig.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Task.java +10 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskInvocationHandler.java +180 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSerDe.java +343 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidationException.java +37 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidator.java +24 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +45 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java +19 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExtensionServiceLoaderModule.java +43 -0
- data/embulk-core/src/main/java/org/embulk/exec/ForSystemConfig.java +16 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +307 -0
- data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +274 -0
- data/embulk-core/src/main/java/org/embulk/exec/LoggerProvider.java +30 -0
- data/embulk-core/src/main/java/org/embulk/exec/NoSampleException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +58 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +138 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewResult.java +27 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewedNoticeError.java +17 -0
- data/embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java +116 -0
- data/embulk-core/src/main/java/org/embulk/exec/SystemConfigModule.java +24 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java +69 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.java +100 -0
- data/embulk-core/src/main/java/org/embulk/plugin/BuiltinPluginSourceModule.java +17 -0
- data/embulk-core/src/main/java/org/embulk/plugin/InjectedPluginSource.java +92 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +34 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSource.java +6 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSourceNotMatchException.java +19 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginType.java +47 -0
- data/embulk-core/src/main/java/org/embulk/plugin/SetThreadContextClassLoader.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/Buffer.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/BufferAllocator.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/Column.java +92 -0
- data/embulk-core/src/main/java/org/embulk/spi/ColumnConfig.java +79 -0
- data/embulk-core/src/main/java/org/embulk/spi/DecoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/EncoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/Exec.java +76 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecAction.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +105 -0
- data/embulk-core/src/main/java/org/embulk/spi/Extension.java +42 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutput.java +13 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +167 -0
- data/embulk-core/src/main/java/org/embulk/spi/FormatterPlugin.java +18 -0
- data/embulk-core/src/main/java/org/embulk/spi/GuessPlugin.java +9 -0
- data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/Page.java +45 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageBuilder.java +327 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageFormat.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageOutput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageReader.java +227 -0
- data/embulk-core/src/main/java/org/embulk/spi/ParserPlugin.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/Schema.java +101 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaConfig.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaVisitor.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/Transactional.java +10 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileInput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileOutput.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalPageOutput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/DateTimeZoneSerDe.java +57 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelper.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelperFactory.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/Timestamp.java +159 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java +98 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParseException.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParser.java +60 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampSerDe.java +50 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/AbstractType.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/BooleanType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/DoubleType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/LongType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/StringType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TimestampType.java +39 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Type.java +15 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TypeDeserializer.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Types.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/CharsetSerDe.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Decoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Encoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileInputInputStream.java +110 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileOutputOutputStream.java +94 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/InputStreamFileInput.java +111 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Inputs.java +74 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineDecoder.java +118 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineEncoder.java +109 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/ListFileInput.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Newline.java +38 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/PagePrinter.java +102 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Pages.java +139 -0
- data/embulk-core/src/test/java/org/embulk/EmbulkTestRuntime.java +110 -0
- data/embulk-core/src/test/java/org/embulk/GuiceBinder.java +72 -0
- data/embulk-core/src/test/java/org/embulk/RandomManager.java +53 -0
- data/embulk-core/src/test/java/org/embulk/TestPluginSourceModule.java +23 -0
- data/embulk-core/src/test/java/org/embulk/TestUtilityModule.java +17 -0
- data/embulk-core/src/test/java/org/embulk/config/TestConfigSource.java +114 -0
- data/embulk-core/src/test/java/org/embulk/config/TestTaskSource.java +70 -0
- data/embulk-core/src/test/java/org/embulk/plugin/MockPluginSource.java +57 -0
- data/embulk-core/src/test/java/org/embulk/plugin/TestPluginType.java +18 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFileOutput.java +63 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFormatterPlugin.java +101 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockParserPlugin.java +73 -0
- data/embulk-core/src/test/java/org/embulk/spi/PageTestUtils.java +78 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputInputStream.java +67 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +180 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +192 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestInputStreamFileInput.java +188 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestPageBuilderReader.java +301 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestamp.java +116 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestampFormatterParser.java +52 -0
- data/embulk-core/src/test/java/org/embulk/spi/type/TestTypeSerDe.java +45 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineDecoder.java +132 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineEncoder.java +123 -0
- data/embulk-standards/build.gradle +6 -0
- data/embulk-standards/pom.xml +68 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvFormatterPlugin.java +158 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +233 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvTokenizer.java +355 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileDecoderPlugin.java +55 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileEncoderPlugin.java +39 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +138 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +128 -0
- data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +46 -0
- data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +238 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginExtension.java +16 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginModule.java +44 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +71 -0
- data/embulk-standards/src/main/resources/META-INF/services/org.embulk.spi.Extension +1 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvParserPlugin.java +69 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvTokenizer.java +291 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestS3FileInputPlugin.java +43 -0
- data/embulk.gemspec +27 -0
- data/examples/config.yml +34 -0
- data/examples/csv/sample.csv.gz +0 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +164 -0
- data/gradlew.bat +90 -0
- data/lib/embulk.rb +16 -0
- data/lib/embulk/buffer.rb +17 -0
- data/lib/embulk/column.rb +47 -0
- data/lib/embulk/command/embulk.rb +39 -0
- data/lib/embulk/command/embulk_example.rb +32 -0
- data/lib/embulk/command/embulk_generate_bin.rb +62 -0
- data/lib/embulk/command/embulk_run.rb +243 -0
- data/lib/embulk/data/bundle/.bundle/config +3 -0
- data/lib/embulk/data/bundle/Gemfile +31 -0
- data/lib/embulk/data/bundle/Gemfile.lock +8 -0
- data/lib/embulk/data/bundle/embulk/input_example.rb +40 -0
- data/lib/embulk/data/bundle/embulk/output_example.rb +51 -0
- data/lib/embulk/data_source.rb +66 -0
- data/lib/embulk/error.rb +5 -0
- data/lib/embulk/guess_charset.rb +26 -0
- data/lib/embulk/guess_csv.rb +195 -0
- data/lib/embulk/guess_gzip.rb +18 -0
- data/lib/embulk/guess_newline.rb +20 -0
- data/lib/embulk/guess_plugin.rb +113 -0
- data/lib/embulk/input_plugin.rb +53 -0
- data/lib/embulk/java/bootstrap.rb +12 -0
- data/lib/embulk/java/imports.rb +26 -0
- data/lib/embulk/java/time_helper.rb +77 -0
- data/lib/embulk/output_plugin.rb +104 -0
- data/lib/embulk/page.rb +28 -0
- data/lib/embulk/page_builder.rb +22 -0
- data/lib/embulk/plugin.rb +152 -0
- data/lib/embulk/plugin_registry.rb +70 -0
- data/lib/embulk/schema.rb +85 -0
- data/lib/embulk/time_format_guess.rb +331 -0
- data/lib/embulk/version.rb +3 -0
- data/pom.xml +533 -0
- data/settings.gradle +5 -0
- metadata +370 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package org.embulk.command;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
import java.util.ArrayList;
|
|
5
|
+
import java.util.Locale;
|
|
6
|
+
import java.io.PrintStream;
|
|
7
|
+
import java.io.Flushable;
|
|
8
|
+
import java.io.IOException;
|
|
9
|
+
|
|
10
|
+
class TablePrinter
|
|
11
|
+
{
|
|
12
|
+
private static final int SAMPLES = 10;
|
|
13
|
+
|
|
14
|
+
private PrintStream out;
|
|
15
|
+
|
|
16
|
+
private String[] header;
|
|
17
|
+
|
|
18
|
+
private List<Object[]> samples;
|
|
19
|
+
private String format;
|
|
20
|
+
private String border;
|
|
21
|
+
|
|
22
|
+
public TablePrinter(PrintStream out, String... header)
|
|
23
|
+
{
|
|
24
|
+
this.out = out;
|
|
25
|
+
this.header = header;
|
|
26
|
+
this.samples = new ArrayList<Object[]>(SAMPLES);
|
|
27
|
+
samples.add(header);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public void add(Object... values) throws IOException
|
|
31
|
+
{
|
|
32
|
+
int min = header.length < values.length ? header.length : values.length;
|
|
33
|
+
Object[] cols = new Object[header.length];
|
|
34
|
+
for(int i=0; i < min; i++) {
|
|
35
|
+
if(values[i] == null) {
|
|
36
|
+
cols[i] = "";
|
|
37
|
+
} else {
|
|
38
|
+
cols[i] = valueToString(values[i]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for(int i=min; i < header.length; i++) {
|
|
42
|
+
cols[i] = "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if(samples == null) {
|
|
46
|
+
out.format(format, cols);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
samples.add(cols);
|
|
51
|
+
if(samples.size() < SAMPLES) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected String valueToString(Object obj)
|
|
57
|
+
{
|
|
58
|
+
return obj.toString();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private void flushSamples()
|
|
62
|
+
{
|
|
63
|
+
StringBuilder borderBuilder = new StringBuilder();
|
|
64
|
+
|
|
65
|
+
StringBuilder sb = new StringBuilder();
|
|
66
|
+
sb.append("| ");
|
|
67
|
+
borderBuilder.append("+-");
|
|
68
|
+
for(int i=0; i < header.length; i++) {
|
|
69
|
+
if(i != 0) {
|
|
70
|
+
sb.append(" | ");
|
|
71
|
+
borderBuilder.append("-+-");
|
|
72
|
+
}
|
|
73
|
+
int colLen = maxLengthInColumn(i);
|
|
74
|
+
sb.append("%"+colLen+"s");
|
|
75
|
+
for(int b=0; b < colLen; b++) {
|
|
76
|
+
borderBuilder.append("-");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
sb.append(" |");
|
|
80
|
+
borderBuilder.append("-+");
|
|
81
|
+
sb.append("\n");
|
|
82
|
+
|
|
83
|
+
this.format = sb.toString();
|
|
84
|
+
this.border = borderBuilder.toString();
|
|
85
|
+
|
|
86
|
+
out.println(border);
|
|
87
|
+
|
|
88
|
+
for(int i=0; i < samples.size(); i++) {
|
|
89
|
+
out.format(format, samples.get(i));
|
|
90
|
+
if(i == 0) {
|
|
91
|
+
out.println(border);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.samples = null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private int maxLengthInColumn(int i)
|
|
99
|
+
{
|
|
100
|
+
int max = 0;
|
|
101
|
+
for(Object[] cols : samples) {
|
|
102
|
+
String s = (String) cols[i];
|
|
103
|
+
int len = (s == null) ? 0 : s.length();
|
|
104
|
+
if(max < len) {
|
|
105
|
+
max = len;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return max;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public void finish() throws IOException
|
|
112
|
+
{
|
|
113
|
+
if(!samples.isEmpty()) {
|
|
114
|
+
flushSamples();
|
|
115
|
+
}
|
|
116
|
+
out.println(border);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
public interface CommitReport
|
|
4
|
+
extends DataSource
|
|
5
|
+
{
|
|
6
|
+
@Override
|
|
7
|
+
public CommitReport getNested(String attrName);
|
|
8
|
+
|
|
9
|
+
@Override
|
|
10
|
+
public CommitReport getNestedOrSetEmpty(String attrName);
|
|
11
|
+
|
|
12
|
+
@Override
|
|
13
|
+
public CommitReport set(String attrName, Object v);
|
|
14
|
+
|
|
15
|
+
@Override
|
|
16
|
+
public CommitReport setNested(String attrName, DataSource v);
|
|
17
|
+
|
|
18
|
+
@Override
|
|
19
|
+
public CommitReport setAll(DataSource other);
|
|
20
|
+
|
|
21
|
+
@Override
|
|
22
|
+
public CommitReport deepCopy();
|
|
23
|
+
|
|
24
|
+
@Override
|
|
25
|
+
public CommitReport merge(DataSource other);
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.lang.annotation.Documented;
|
|
4
|
+
import java.lang.annotation.ElementType;
|
|
5
|
+
import java.lang.annotation.Retention;
|
|
6
|
+
import java.lang.annotation.RetentionPolicy;
|
|
7
|
+
import java.lang.annotation.Target;
|
|
8
|
+
|
|
9
|
+
@Documented
|
|
10
|
+
@Retention(RetentionPolicy.RUNTIME)
|
|
11
|
+
@Target(ElementType.METHOD)
|
|
12
|
+
public @interface Config
|
|
13
|
+
{
|
|
14
|
+
String value();
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.lang.annotation.Documented;
|
|
4
|
+
import java.lang.annotation.ElementType;
|
|
5
|
+
import java.lang.annotation.Retention;
|
|
6
|
+
import java.lang.annotation.RetentionPolicy;
|
|
7
|
+
import java.lang.annotation.Target;
|
|
8
|
+
|
|
9
|
+
@Documented
|
|
10
|
+
@Retention(RetentionPolicy.RUNTIME)
|
|
11
|
+
@Target(ElementType.METHOD)
|
|
12
|
+
public @interface ConfigDefault
|
|
13
|
+
{
|
|
14
|
+
String value();
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
public class ConfigException
|
|
4
|
+
extends RuntimeException
|
|
5
|
+
{
|
|
6
|
+
public ConfigException(String message)
|
|
7
|
+
{
|
|
8
|
+
super(message);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public ConfigException(Throwable cause)
|
|
12
|
+
{
|
|
13
|
+
super(cause);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public ConfigException(String message, Throwable cause)
|
|
17
|
+
{
|
|
18
|
+
super(message, cause);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.io.File;
|
|
4
|
+
import java.io.FileInputStream;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.util.Properties;
|
|
7
|
+
import com.google.inject.Inject;
|
|
8
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
9
|
+
import com.fasterxml.jackson.core.JsonParser;
|
|
10
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
11
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
12
|
+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
|
13
|
+
import org.yaml.snakeyaml.Yaml;
|
|
14
|
+
|
|
15
|
+
public class ConfigLoader
|
|
16
|
+
{
|
|
17
|
+
private final ModelManager model;
|
|
18
|
+
|
|
19
|
+
@Inject
|
|
20
|
+
public ConfigLoader(ModelManager model)
|
|
21
|
+
{
|
|
22
|
+
this.model = model;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public ConfigSource fromJson(JsonParser parser) throws IOException
|
|
26
|
+
{
|
|
27
|
+
// TODO check parsed.isObject()
|
|
28
|
+
ObjectNode source = (ObjectNode) new ObjectMapper().readTree(parser);
|
|
29
|
+
return new DataSourceImpl(model, source);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public ConfigSource fromYamlFile(File path) throws IOException
|
|
33
|
+
{
|
|
34
|
+
Yaml yaml = new Yaml();
|
|
35
|
+
Object parsedYaml;
|
|
36
|
+
try (FileInputStream is = new FileInputStream(path)) {
|
|
37
|
+
parsedYaml = yaml.load(is);
|
|
38
|
+
}
|
|
39
|
+
ObjectNode source = objectToJsonObject(parsedYaml);
|
|
40
|
+
return new DataSourceImpl(model, source);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public ConfigSource fromPropertiesYamlLiteral(Properties props, String keyPrefix)
|
|
44
|
+
{
|
|
45
|
+
// TODO exception handling
|
|
46
|
+
ObjectNode source = new ObjectNode(JsonNodeFactory.instance);
|
|
47
|
+
Yaml yaml = new Yaml();
|
|
48
|
+
for (String key : props.stringPropertyNames()) {
|
|
49
|
+
// TODO handle "." and "[...]" as map and array acccessor for example:
|
|
50
|
+
// in.parser.type=csv => {"in": {"parser": {"type": "csv"}}}
|
|
51
|
+
if (!key.startsWith(keyPrefix)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
String yamlValue = props.getProperty(key);
|
|
55
|
+
String keyName = key.substring(keyPrefix.length());
|
|
56
|
+
Object parsedValue = yaml.load(yamlValue);
|
|
57
|
+
JsonNode typedValue = objectToJson(parsedValue);
|
|
58
|
+
source.set(keyName, typedValue);
|
|
59
|
+
}
|
|
60
|
+
return new DataSourceImpl(model, source);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private JsonNode objectToJson(Object object)
|
|
64
|
+
{
|
|
65
|
+
// TODO exception
|
|
66
|
+
ObjectMapper objectMapper = new ObjectMapper();
|
|
67
|
+
try {
|
|
68
|
+
return objectMapper.readTree(objectMapper.writeValueAsString(object));
|
|
69
|
+
} catch (IOException ex) {
|
|
70
|
+
throw new RuntimeException(ex);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private ObjectNode objectToJsonObject(Object object)
|
|
75
|
+
{
|
|
76
|
+
// TODO exception
|
|
77
|
+
JsonNode json = objectToJson(object);
|
|
78
|
+
if (!json.isObject()) {
|
|
79
|
+
throw new RuntimeException("Expected object to deserialize ConfigSource but got "+json);
|
|
80
|
+
}
|
|
81
|
+
return (ObjectNode) json;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
public interface ConfigSource
|
|
4
|
+
extends DataSource
|
|
5
|
+
{
|
|
6
|
+
public <T extends Task> T loadConfig(Class<T> taskType);
|
|
7
|
+
|
|
8
|
+
@Override
|
|
9
|
+
public ConfigSource getNested(String attrName);
|
|
10
|
+
|
|
11
|
+
@Override
|
|
12
|
+
public ConfigSource getNestedOrSetEmpty(String attrName);
|
|
13
|
+
|
|
14
|
+
@Override
|
|
15
|
+
public ConfigSource set(String attrName, Object v);
|
|
16
|
+
|
|
17
|
+
@Override
|
|
18
|
+
public ConfigSource setNested(String attrName, DataSource v);
|
|
19
|
+
|
|
20
|
+
@Override
|
|
21
|
+
public ConfigSource setAll(DataSource other);
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public ConfigSource deepCopy();
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public ConfigSource merge(DataSource other);
|
|
28
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
import java.util.Map;
|
|
5
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
6
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
7
|
+
|
|
8
|
+
public interface DataSource
|
|
9
|
+
{
|
|
10
|
+
public List<String> getAttributeNames();
|
|
11
|
+
|
|
12
|
+
public Iterable<Map.Entry<String, JsonNode>> getAttributes();
|
|
13
|
+
|
|
14
|
+
public boolean isEmpty();
|
|
15
|
+
|
|
16
|
+
public <E> E get(Class<E> type, String attrName);
|
|
17
|
+
|
|
18
|
+
public <E> E get(Class<E> type, String attrName, E defaultValue);
|
|
19
|
+
|
|
20
|
+
public DataSource getNested(String attrName);
|
|
21
|
+
|
|
22
|
+
public DataSource getNestedOrSetEmpty(String attrName);
|
|
23
|
+
|
|
24
|
+
public DataSource set(String attrName, Object v);
|
|
25
|
+
|
|
26
|
+
public DataSource setNested(String attrName, DataSource v);
|
|
27
|
+
|
|
28
|
+
public DataSource setAll(DataSource other);
|
|
29
|
+
|
|
30
|
+
public DataSource deepCopy();
|
|
31
|
+
|
|
32
|
+
public DataSource merge(DataSource other);
|
|
33
|
+
|
|
34
|
+
public ObjectNode getObjectNode();
|
|
35
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
import java.util.Map;
|
|
5
|
+
import java.util.Iterator;
|
|
6
|
+
import com.google.common.collect.ImmutableList;
|
|
7
|
+
import com.fasterxml.jackson.core.JsonParser;
|
|
8
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
9
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
10
|
+
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
11
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
12
|
+
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
13
|
+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
|
14
|
+
|
|
15
|
+
public class DataSourceImpl
|
|
16
|
+
implements ConfigSource, TaskSource, CommitReport, NextConfig
|
|
17
|
+
{
|
|
18
|
+
protected final ObjectNode data;
|
|
19
|
+
protected final ModelManager model;
|
|
20
|
+
|
|
21
|
+
public DataSourceImpl(ModelManager model)
|
|
22
|
+
{
|
|
23
|
+
this(model, new ObjectNode(JsonNodeFactory.instance));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// visible for DataSourceSerDe, ConfigSourceLoader and TaskInvocationHandler.dump
|
|
27
|
+
public DataSourceImpl(ModelManager model, ObjectNode data)
|
|
28
|
+
{
|
|
29
|
+
this.data = data;
|
|
30
|
+
this.model = model;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected DataSourceImpl newInstance(ModelManager model, ObjectNode data)
|
|
34
|
+
{
|
|
35
|
+
return new DataSourceImpl(model, (ObjectNode) data);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// visible for DataSourceSerDe.DataSourceSerializer
|
|
39
|
+
@Override
|
|
40
|
+
public ObjectNode getObjectNode()
|
|
41
|
+
{
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Override
|
|
46
|
+
public List<String> getAttributeNames()
|
|
47
|
+
{
|
|
48
|
+
return ImmutableList.copyOf(data.fieldNames());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Override
|
|
52
|
+
public Iterable<Map.Entry<String, JsonNode>> getAttributes()
|
|
53
|
+
{
|
|
54
|
+
return new Iterable() {
|
|
55
|
+
public Iterator<Map.Entry<String, JsonNode>> iterator()
|
|
56
|
+
{
|
|
57
|
+
return data.fields();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Override
|
|
63
|
+
public boolean isEmpty()
|
|
64
|
+
{
|
|
65
|
+
return !data.fieldNames().hasNext();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Override
|
|
69
|
+
public <E> E get(Class<E> type, String attrName)
|
|
70
|
+
{
|
|
71
|
+
JsonNode json = data.get(attrName);
|
|
72
|
+
if (json == null) {
|
|
73
|
+
throw new ConfigException("Attribute "+attrName+" is required but not set");
|
|
74
|
+
}
|
|
75
|
+
return model.readObject(type, json.traverse());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@Override
|
|
79
|
+
public <E> E get(Class<E> type, String attrName, E defaultValue)
|
|
80
|
+
{
|
|
81
|
+
JsonNode json = data.get(attrName);
|
|
82
|
+
if (json == null) {
|
|
83
|
+
return defaultValue;
|
|
84
|
+
}
|
|
85
|
+
return model.readObject(type, json.traverse());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@Override
|
|
89
|
+
public DataSourceImpl getNested(String attrName)
|
|
90
|
+
{
|
|
91
|
+
JsonNode json = data.get(attrName);
|
|
92
|
+
if (json == null) {
|
|
93
|
+
throw new ConfigException("Attribute "+attrName+" is required but not set");
|
|
94
|
+
}
|
|
95
|
+
if (!json.isObject()) {
|
|
96
|
+
throw new ConfigException("Attribute "+attrName+" must be an object");
|
|
97
|
+
}
|
|
98
|
+
return newInstance(model, (ObjectNode) json);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Override
|
|
102
|
+
public DataSourceImpl getNestedOrSetEmpty(String attrName)
|
|
103
|
+
{
|
|
104
|
+
JsonNode json = data.get(attrName);
|
|
105
|
+
if (json == null) {
|
|
106
|
+
json = data.objectNode();
|
|
107
|
+
data.set(attrName, json);
|
|
108
|
+
} else if (!json.isObject()) {
|
|
109
|
+
throw new ConfigException("Attribute "+attrName+" must be an object");
|
|
110
|
+
}
|
|
111
|
+
return newInstance(model, (ObjectNode) json);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Override
|
|
115
|
+
public DataSourceImpl set(String attrName, Object v)
|
|
116
|
+
{
|
|
117
|
+
if (v == null) {
|
|
118
|
+
data.remove(attrName);
|
|
119
|
+
} else {
|
|
120
|
+
data.put(attrName, model.writeObjectAsJsonNode(v));
|
|
121
|
+
}
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Override
|
|
126
|
+
public DataSourceImpl setNested(String attrName, DataSource v)
|
|
127
|
+
{
|
|
128
|
+
data.put(attrName, v.getObjectNode());
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@Override
|
|
133
|
+
public DataSourceImpl setAll(DataSource other)
|
|
134
|
+
{
|
|
135
|
+
for (Map.Entry<String, JsonNode> field : other.getAttributes()) {
|
|
136
|
+
data.put(field.getKey(), field.getValue());
|
|
137
|
+
}
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@Override
|
|
142
|
+
public DataSourceImpl deepCopy()
|
|
143
|
+
{
|
|
144
|
+
return newInstance(model, data.deepCopy());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@Override
|
|
148
|
+
public DataSourceImpl merge(DataSource other)
|
|
149
|
+
{
|
|
150
|
+
mergeJsonObject(data, other.deepCopy().getObjectNode());
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private static void mergeJsonObject(ObjectNode src, ObjectNode other)
|
|
155
|
+
{
|
|
156
|
+
Iterator<Map.Entry<String, JsonNode>> ite = other.fields();
|
|
157
|
+
while (ite.hasNext()) {
|
|
158
|
+
Map.Entry<String, JsonNode> pair = ite.next();
|
|
159
|
+
JsonNode s = src.get(pair.getKey());
|
|
160
|
+
JsonNode v = pair.getValue();
|
|
161
|
+
if (v.isObject() && s != null && s.isObject()) {
|
|
162
|
+
mergeJsonObject((ObjectNode) s, (ObjectNode) v);
|
|
163
|
+
} else if (v.isArray() && s != null && s.isArray()) {
|
|
164
|
+
mergeJsonArray((ArrayNode) s, (ArrayNode) v);
|
|
165
|
+
} else {
|
|
166
|
+
src.replace(pair.getKey(), v);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private static void mergeJsonArray(ArrayNode src, ArrayNode other)
|
|
172
|
+
{
|
|
173
|
+
src.addAll(other);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Override
|
|
177
|
+
public <T extends Task> T loadTask(Class<T> taskType)
|
|
178
|
+
{
|
|
179
|
+
return model.readObject(taskType, data.traverse());
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@Override
|
|
183
|
+
public <T extends Task> T loadConfig(Class<T> taskType)
|
|
184
|
+
{
|
|
185
|
+
return model.readObjectWithConfigSerDe(taskType, data.traverse());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@Override
|
|
189
|
+
public String toString()
|
|
190
|
+
{
|
|
191
|
+
return data.toString();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@Override
|
|
195
|
+
public boolean equals(Object other)
|
|
196
|
+
{
|
|
197
|
+
if (!(other instanceof DataSource)) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
return data.equals(((DataSource) other).getObjectNode());
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@Override
|
|
204
|
+
public int hashCode()
|
|
205
|
+
{
|
|
206
|
+
return data.hashCode();
|
|
207
|
+
}
|
|
208
|
+
}
|