embulk 0.2.1 → 0.3.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 +8 -8
- data/ChangeLog +12 -0
- data/README.md +38 -13
- data/build.gradle +6 -1
- data/embulk-cli/pom.xml +1 -1
- data/embulk-core/pom.xml +1 -1
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +87 -8
- data/embulk-core/src/main/java/org/embulk/config/ConfigSource.java +1 -1
- data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +16 -3
- data/embulk-core/src/main/java/org/embulk/config/TaskSource.java +1 -1
- data/embulk-core/src/main/java/org/embulk/exec/ExecutionInterruptedException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecutionResult.java +26 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +37 -1
- data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +461 -110
- data/embulk-core/src/main/java/org/embulk/exec/PartialExecutionException.java +18 -0
- data/embulk-core/src/main/java/org/embulk/exec/ResumeState.java +82 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java +3 -3
- data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +35 -4
- data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +14 -3
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +55 -24
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +57 -24
- data/embulk-core/src/main/java/org/embulk/spi/FilterPlugin.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +14 -3
- data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Filters.java +87 -0
- data/embulk-core/src/test/java/org/embulk/EmbulkTestRuntime.java +4 -2
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +16 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +15 -0
- data/embulk-standards/pom.xml +1 -1
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +16 -2
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +14 -1
- data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +14 -1
- data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +15 -3
- data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +15 -1
- data/lib/embulk/command/embulk_run.rb +16 -1
- data/lib/embulk/data/bundle/embulk/filter_example.rb +42 -0
- data/lib/embulk/data/bundle/embulk/input_example.rb +43 -33
- data/lib/embulk/data/bundle/embulk/output_example.rb +43 -36
- data/lib/embulk/filter_plugin.rb +86 -0
- data/lib/embulk/input_plugin.rb +37 -2
- data/lib/embulk/java/imports.rb +1 -0
- data/lib/embulk/output_plugin.rb +30 -0
- data/lib/embulk/plugin.rb +32 -19
- data/lib/embulk/schema.rb +16 -9
- data/lib/embulk/version.rb +1 -1
- data/pom.xml +1 -1
- metadata +13 -7
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java +0 -10
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java +0 -19
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
N2ZlNTcxZjM0ZjA4MDE5YmM0NmU2ZTQ3ZmZkM2ZkZDM5OWFkNjRiNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzU2NjYzOTQzM2ExYzdiNzc0YzUzYWZiNzcwZTU2ZmFkZmUxYjMzOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWM5ZjJiNjhkNDQwZDgyZGU4MzhiMmNmYjI5OGZhMjk2OTAyM2FlOWM4YzYy
|
10
|
+
ZTczZTgzMDBkYjY3ZmZmODM0NGU0NmM2MTBjYmRiNDY1ZDliY2QzZmM2OTZi
|
11
|
+
ZmIzZjZmYzc4MTJkOWE2ODM5ODAxYTZhMzgzNzE0NzM5YzgyODU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTg3MjdiZWNjNGYzN2MzZTM0YzY0OTRmNGJlYmI5ODY3ZmY5ZWFiY2RkN2Yy
|
14
|
+
NjI0ZmIzOWJjNDU0NzM4ZDhlYTJjZTBkODc3MmRjYjI5Mzc5OWUyZDQwYzA5
|
15
|
+
MTRiMGE1NmU4YmI1MWU1Yjk1ZmJlZTU3Y2Y0NDY5YTFjN2EzOTQ=
|
data/ChangeLog
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
|
2
|
+
2015-02-03 version 0.3.0:
|
3
|
+
|
4
|
+
* Added resume functionality. InputPlugin and OutputPlugin needs to implement
|
5
|
+
resume and cleanup methods.
|
6
|
+
* cli: embulk-run supports -r, --resume-state PATH option.
|
7
|
+
* Added FilterInputPlugin Java API.
|
8
|
+
* Added FilterInputPlugin JRuby API.
|
9
|
+
* Configuration file accepts filters: array entry.
|
10
|
+
* Added gradle-versions-plugin to build.gradle (@seratch++)
|
11
|
+
* Fixed broken dependencies at build.gradle (@thagikura++)
|
12
|
+
|
13
|
+
|
2
14
|
2015-01-29 version 0.2.1:
|
3
15
|
|
4
16
|
* Fixed LineEncoder#finish to flush all remaining buffer (reported by @aibou)
|
data/README.md
CHANGED
@@ -1,27 +1,30 @@
|
|
1
|
-
# Embulk
|
2
|
-
|
3
|
-
A plugin-based parallel bulk data loader that makes painful data integration works relaxed.
|
4
|
-
|
5
|
-
## What's Embulk?
|
1
|
+
# What's Embulk?
|
6
2
|
|
7
3
|
Embulk is a plugin-based parallel bulk data loader that helps **data transfer** between various **storages**, **databases**, **NoSQL** and **cloud services**.
|
8
4
|
|
9
|
-
You can
|
10
|
-
|
11
|
-
You also can release plugins to share your efforts of data cleaning, error handling, transaction control, and retrying.
|
12
|
-
Packaging effrots into plugins **brings OSS-style development to the data scripts** which **was tend to be one-time adhoc scripts**.
|
5
|
+
You can release plugins to share your efforts of data cleaning, error handling, transaction control, and retrying. Packaging effrots into plugins **brings OSS-style development to the data scripts** which **was tend to be one-time adhoc scripts**.
|
13
6
|
|
14
|
-
[
|
7
|
+
[Embulk, an open-source plugin-based parallel bulk data loader](http://www.slideshare.net/frsyuki/embuk-making-data-integration-works-relaxed) at Slideshare
|
15
8
|
|
16
9
|
[](http://www.slideshare.net/frsyuki/embuk-making-data-integration-works-relaxed/12)
|
17
10
|
|
11
|
+
# Document
|
12
|
+
|
13
|
+
* [Quick Start](#quick-start)
|
14
|
+
* [Using plugins](#using-plugins)
|
15
|
+
* [Using plugin bundle](#using-plugin-bundle)
|
16
|
+
* [Releasing plugins to RubyGems](#releasing-plugins-to-rubygems)
|
17
|
+
* [Resuming a failed transaction](#resuming-a-failed-transaction)
|
18
|
+
* [Embulk Development](#embulk-development)
|
19
|
+
* [Build](#build)
|
20
|
+
* [Release](#release)
|
18
21
|
|
19
22
|
## Quick Start
|
20
23
|
|
21
24
|
The single-file package is the simplest way to try Embulk. You can download the latest embulk-VERSION.jar from [the releases page](https://bintray.com/embulk/maven/embulk/view#files) and run it with java:
|
22
25
|
|
23
26
|
```
|
24
|
-
wget https://bintray.com/artifact/download/embulk/maven/embulk-0.
|
27
|
+
wget https://bintray.com/artifact/download/embulk/maven/embulk-0.3.0.jar -O embulk.jar
|
25
28
|
java -jar embulk.jar --help
|
26
29
|
```
|
27
30
|
|
@@ -37,10 +40,10 @@ java -jar embulk.jar run config.yml
|
|
37
40
|
### Using plugins
|
38
41
|
|
39
42
|
You can use plugins to load data from/to various systems and file formats.
|
40
|
-
An example is [embulk-
|
43
|
+
An example is [embulk-plugin-postgres-json](https://github.com/frsyuki/embulk-plugin-postgres-json) plugin. It outputs data into PostgreSQL server using "json" column type.
|
41
44
|
|
42
45
|
```
|
43
|
-
java -jar embulk.jar gem install embulk-
|
46
|
+
java -jar embulk.jar gem install embulk-plugin-postgres-json
|
44
47
|
java -jar embulk.jar gem list
|
45
48
|
```
|
46
49
|
|
@@ -67,6 +70,28 @@ TODO: documents
|
|
67
70
|
embulk-plugin-xyz
|
68
71
|
```
|
69
72
|
|
73
|
+
### Resuming a failed transaction
|
74
|
+
|
75
|
+
Embulk supports resuming failed transactions.
|
76
|
+
To enable resuming, you need to start transaction with `-r PATH` option:
|
77
|
+
|
78
|
+
```
|
79
|
+
java -jar embulk.jar run config.yml -r resume-state.yml
|
80
|
+
```
|
81
|
+
|
82
|
+
If the transaction fails, embulk stores state some states to the yaml file. You can retry the transaction using exactly same command:
|
83
|
+
|
84
|
+
```
|
85
|
+
java -jar embulk.jar run config.yml -r resume-state.yml
|
86
|
+
```
|
87
|
+
|
88
|
+
If you giveup to resume the transaction, you can use `embulk cleanup` subcommand to delete intermediate data:
|
89
|
+
|
90
|
+
```
|
91
|
+
java -jar embulk.jar cleanup config.yml -r resume-state.yml
|
92
|
+
```
|
93
|
+
|
94
|
+
|
70
95
|
## Embulk Development
|
71
96
|
|
72
97
|
### Build
|
data/build.gradle
CHANGED
@@ -9,6 +9,7 @@ buildscript {
|
|
9
9
|
}
|
10
10
|
dependencies {
|
11
11
|
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
|
12
|
+
classpath 'com.github.ben-manes:gradle-versions-plugin:0.7'
|
12
13
|
}
|
13
14
|
}
|
14
15
|
|
@@ -22,8 +23,12 @@ allprojects {
|
|
22
23
|
apply plugin: 'maven-publish'
|
23
24
|
apply plugin: 'com.jfrog.bintray'
|
24
25
|
|
26
|
+
// determine which dependencies have updates
|
27
|
+
// $ gradle dependencyUpdates
|
28
|
+
apply plugin: 'com.github.ben-manes.versions'
|
29
|
+
|
25
30
|
group = 'org.embulk'
|
26
|
-
version = '0.
|
31
|
+
version = '0.3.0'
|
27
32
|
|
28
33
|
// to upload artifacts to Bintray by gradle-bintray-plugin
|
29
34
|
// $ gradle bintrayUpload
|
data/embulk-cli/pom.xml
CHANGED
data/embulk-core/pom.xml
CHANGED
@@ -21,10 +21,12 @@ import org.embulk.config.NextConfig;
|
|
21
21
|
import org.embulk.config.ModelManager;
|
22
22
|
import org.embulk.config.ConfigException;
|
23
23
|
import org.embulk.exec.LocalExecutor;
|
24
|
-
import org.embulk.exec.
|
24
|
+
import org.embulk.exec.ExecutionResult;
|
25
25
|
import org.embulk.exec.GuessExecutor;
|
26
26
|
import org.embulk.exec.PreviewExecutor;
|
27
27
|
import org.embulk.exec.PreviewResult;
|
28
|
+
import org.embulk.exec.ResumeState;
|
29
|
+
import org.embulk.exec.PartialExecutionException;
|
28
30
|
import org.embulk.spi.time.Timestamp;
|
29
31
|
import org.embulk.spi.ExecSession;
|
30
32
|
import org.embulk.spi.util.Pages;
|
@@ -36,6 +38,9 @@ public class Runner
|
|
36
38
|
{
|
37
39
|
private String nextConfigOutputPath;
|
38
40
|
public String getNextConfigOutputPath() { return nextConfigOutputPath; }
|
41
|
+
|
42
|
+
private String resumeStatePath;
|
43
|
+
public String getResumeStatePath() { return resumeStatePath; }
|
39
44
|
}
|
40
45
|
|
41
46
|
private final Options options;
|
@@ -58,6 +63,9 @@ public class Runner
|
|
58
63
|
case "run":
|
59
64
|
run(args[0]);
|
60
65
|
break;
|
66
|
+
case "cleanup":
|
67
|
+
cleanup(args[0]);
|
68
|
+
break;
|
61
69
|
case "guess":
|
62
70
|
guess(args[0]);
|
63
71
|
break;
|
@@ -72,21 +80,87 @@ public class Runner
|
|
72
80
|
public void run(String configPath)
|
73
81
|
{
|
74
82
|
ConfigSource config = loadYamlConfig(configPath);
|
75
|
-
|
83
|
+
checkFileWritable(options.getNextConfigOutputPath());
|
84
|
+
checkFileWritable(options.getResumeStatePath());
|
85
|
+
|
86
|
+
// load resume state file
|
87
|
+
ResumeState resume = null;
|
88
|
+
String resumePath = options.getResumeStatePath();
|
89
|
+
if (resumePath != null) {
|
90
|
+
ConfigSource resumeConfig = null;
|
91
|
+
try {
|
92
|
+
resumeConfig = loadYamlConfig(resumePath);
|
93
|
+
if (resumeConfig.isEmpty()) {
|
94
|
+
resumeConfig = null;
|
95
|
+
}
|
96
|
+
} catch (RuntimeException ex) {
|
97
|
+
// leave resumeConfig == null
|
98
|
+
}
|
99
|
+
if (resumeConfig != null) {
|
100
|
+
resume = resumeConfig.loadConfig(ResumeState.class);
|
101
|
+
}
|
102
|
+
}
|
76
103
|
|
77
104
|
ExecSession exec = newExecSession(config);
|
78
105
|
LocalExecutor local = injector.getInstance(LocalExecutor.class);
|
79
|
-
|
80
|
-
|
106
|
+
ExecutionResult result;
|
107
|
+
try {
|
108
|
+
if (resume != null) {
|
109
|
+
result = local.resume(config, resume);
|
110
|
+
} else {
|
111
|
+
result = local.run(exec, config);
|
112
|
+
}
|
113
|
+
} catch (PartialExecutionException partial) {
|
114
|
+
if (options.getResumeStatePath() == null) {
|
115
|
+
// resume state path is not set. cleanup the transaction
|
116
|
+
exec.getLogger(Runner.class).info("Transaction partially failed. Cleaning up the intermediate data. Use -r option to make it resumable.");
|
117
|
+
try {
|
118
|
+
local.cleanup(config, partial.getResumeState());
|
119
|
+
} catch (Throwable ex) {
|
120
|
+
partial.addSuppressed(ex);
|
121
|
+
}
|
122
|
+
throw partial;
|
123
|
+
}
|
124
|
+
// save the resume state
|
125
|
+
exec.getLogger(Runner.class).info("Writing resume state to '{}'", options.getResumeStatePath());
|
126
|
+
writeYaml(options.getResumeStatePath(), partial.getResumeState());
|
127
|
+
exec.getLogger(Runner.class).info("Resume state is written. Run the transaction again with -r option to resume or use \"cleanup\" subcommand to delete intermediate data.");
|
128
|
+
throw partial;
|
129
|
+
}
|
81
130
|
|
131
|
+
// delete resume file
|
132
|
+
if (options.getResumeStatePath() != null) {
|
133
|
+
new File(options.getResumeStatePath()).delete();
|
134
|
+
}
|
135
|
+
|
136
|
+
// write next config
|
137
|
+
NextConfig nextConfig = result.getNextConfig();
|
82
138
|
exec.getLogger(Runner.class).info("next config: {}", nextConfig.toString());
|
83
139
|
writeNextConfig(options.getNextConfigOutputPath(), config, nextConfig);
|
84
140
|
}
|
85
141
|
|
142
|
+
public void cleanup(String configPath)
|
143
|
+
{
|
144
|
+
String resumePath = options.getResumeStatePath();
|
145
|
+
if (resumePath == null) {
|
146
|
+
throw new IllegalArgumentException("Resume path is required for cleanup");
|
147
|
+
}
|
148
|
+
ConfigSource config = loadYamlConfig(configPath);
|
149
|
+
ConfigSource resumeConfig = loadYamlConfig(resumePath);
|
150
|
+
ResumeState resume = resumeConfig.loadConfig(ResumeState.class);
|
151
|
+
|
152
|
+
ExecSession exec = newExecSession(config);
|
153
|
+
LocalExecutor local = injector.getInstance(LocalExecutor.class);
|
154
|
+
local.cleanup(config, resume);
|
155
|
+
|
156
|
+
// delete resume file
|
157
|
+
new File(options.getResumeStatePath()).delete();
|
158
|
+
}
|
159
|
+
|
86
160
|
public void guess(String partialConfigPath)
|
87
161
|
{
|
88
162
|
ConfigSource config = loadYamlConfig(partialConfigPath);
|
89
|
-
|
163
|
+
checkFileWritable(options.getNextConfigOutputPath());
|
90
164
|
|
91
165
|
ExecSession exec = newExecSession(config);
|
92
166
|
GuessExecutor guess = injector.getInstance(GuessExecutor.class);
|
@@ -96,7 +170,7 @@ public class Runner
|
|
96
170
|
System.err.println(yml);
|
97
171
|
}
|
98
172
|
|
99
|
-
private void
|
173
|
+
private void checkFileWritable(String path)
|
100
174
|
{
|
101
175
|
if (path != null) {
|
102
176
|
try (FileOutputStream in = new FileOutputStream(path, true)) {
|
@@ -109,7 +183,12 @@ public class Runner
|
|
109
183
|
|
110
184
|
private String writeNextConfig(String path, ConfigSource originalConfig, NextConfig nextConfigDiff)
|
111
185
|
{
|
112
|
-
|
186
|
+
return writeYaml(path, originalConfig.merge(nextConfigDiff));
|
187
|
+
}
|
188
|
+
|
189
|
+
private String writeYaml(String path, Object obj)
|
190
|
+
{
|
191
|
+
String yml = dumpYaml(obj);
|
113
192
|
if (path != null) {
|
114
193
|
if (path.equals("-")) {
|
115
194
|
System.out.print(yml);
|
@@ -181,7 +260,7 @@ public class Runner
|
|
181
260
|
}
|
182
261
|
}
|
183
262
|
|
184
|
-
private String
|
263
|
+
private String dumpYaml(Object config)
|
185
264
|
{
|
186
265
|
ModelManager model = injector.getInstance(ModelManager.class);
|
187
266
|
Map<String, Object> map = model.readObject(MapType.class, model.writeObject(config));
|
@@ -170,17 +170,30 @@ public class DataSourceImpl
|
|
170
170
|
|
171
171
|
private static void mergeJsonArray(ArrayNode src, ArrayNode other)
|
172
172
|
{
|
173
|
-
|
173
|
+
for (int i=0; i < other.size(); i++) {
|
174
|
+
JsonNode s = src.get(i);
|
175
|
+
JsonNode v = other.get(i);
|
176
|
+
if (s == null) {
|
177
|
+
src.add(v);
|
178
|
+
} else if (v.isObject() && s.isObject()) {
|
179
|
+
mergeJsonObject((ObjectNode) s, (ObjectNode) v);
|
180
|
+
} else if (v.isArray() && s.isArray()) {
|
181
|
+
mergeJsonArray((ArrayNode) s, (ArrayNode) v);
|
182
|
+
} else {
|
183
|
+
src.remove(i);
|
184
|
+
src.insert(i, v);
|
185
|
+
}
|
186
|
+
}
|
174
187
|
}
|
175
188
|
|
176
189
|
@Override
|
177
|
-
public <T
|
190
|
+
public <T> T loadTask(Class<T> taskType)
|
178
191
|
{
|
179
192
|
return model.readObject(taskType, data.traverse());
|
180
193
|
}
|
181
194
|
|
182
195
|
@Override
|
183
|
-
public <T
|
196
|
+
public <T> T loadConfig(Class<T> taskType)
|
184
197
|
{
|
185
198
|
return model.readObjectWithConfigSerDe(taskType, data.traverse());
|
186
199
|
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
package org.embulk.exec;
|
2
|
+
|
3
|
+
import java.util.List;
|
4
|
+
import org.embulk.config.NextConfig;
|
5
|
+
|
6
|
+
public class ExecutionResult
|
7
|
+
{
|
8
|
+
private final NextConfig nextConfig;
|
9
|
+
private final List<Throwable> ignoredExceptions;
|
10
|
+
|
11
|
+
public ExecutionResult(NextConfig nextConfig, List<Throwable> ignoredExceptions)
|
12
|
+
{
|
13
|
+
this.nextConfig = nextConfig;
|
14
|
+
this.ignoredExceptions = ignoredExceptions;
|
15
|
+
}
|
16
|
+
|
17
|
+
public NextConfig getNextConfig()
|
18
|
+
{
|
19
|
+
return nextConfig;
|
20
|
+
}
|
21
|
+
|
22
|
+
public List<Throwable> getIgnoredExceptions()
|
23
|
+
{
|
24
|
+
return ignoredExceptions;
|
25
|
+
}
|
26
|
+
}
|
@@ -158,7 +158,7 @@ public class GuessExecutor
|
|
158
158
|
private static class BufferFileInputPlugin
|
159
159
|
implements FileInputPlugin
|
160
160
|
{
|
161
|
-
private
|
161
|
+
private Buffer buffer;
|
162
162
|
|
163
163
|
public BufferFileInputPlugin(Buffer buffer)
|
164
164
|
{
|
@@ -171,6 +171,23 @@ public class GuessExecutor
|
|
171
171
|
return Exec.newNextConfig();
|
172
172
|
}
|
173
173
|
|
174
|
+
public NextConfig resume(TaskSource taskSource,
|
175
|
+
int processorCount,
|
176
|
+
FileInputPlugin.Control control)
|
177
|
+
{
|
178
|
+
throw new UnsupportedOperationException();
|
179
|
+
}
|
180
|
+
|
181
|
+
public void cleanup(TaskSource taskSource,
|
182
|
+
int processorCount,
|
183
|
+
List<CommitReport> successCommitReports)
|
184
|
+
{
|
185
|
+
if (buffer != null) {
|
186
|
+
buffer.release();
|
187
|
+
buffer = null;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
174
191
|
public TransactionalFileInput open(TaskSource taskSource, int processorIndex)
|
175
192
|
{
|
176
193
|
return new BufferTransactionalFileInput(buffer);
|
@@ -257,6 +274,7 @@ public class GuessExecutor
|
|
257
274
|
NextConfig mergedGuessed = Exec.newNextConfig();
|
258
275
|
for (int i=0; i < guesses.size(); i++) {
|
259
276
|
NextConfig guessed = guesses.get(i).guess(originalConfig, sample);
|
277
|
+
guessed = addAssumedDecoderConfigs(originalConfig, guessed);
|
260
278
|
mergedGuessed.merge(guessed);
|
261
279
|
mergedConfig.merge(mergedGuessed);
|
262
280
|
if (!mergedConfig.equals(originalConfig)) {
|
@@ -287,6 +305,24 @@ public class GuessExecutor
|
|
287
305
|
}
|
288
306
|
throw new NoSampleException("No input buffer to guess");
|
289
307
|
}
|
308
|
+
|
309
|
+
private static class ConfigSourceList extends ArrayList<ConfigSource> { };
|
310
|
+
|
311
|
+
private static NextConfig addAssumedDecoderConfigs(ConfigSource originalConfig, NextConfig guessed)
|
312
|
+
{
|
313
|
+
List<ConfigSource> guessedDecoders = guessed.get(ConfigSourceList.class, "decoders", null);
|
314
|
+
if (guessedDecoders == null) {
|
315
|
+
return guessed;
|
316
|
+
} else {
|
317
|
+
List<ConfigSource> assumedDecoders = originalConfig.get(ConfigSourceList.class, "decoders", new ConfigSourceList());
|
318
|
+
ImmutableList.Builder<ConfigSource> added = ImmutableList.builder();
|
319
|
+
for (ConfigSource assuemed : assumedDecoders) {
|
320
|
+
added.add(Exec.newConfigSource());
|
321
|
+
}
|
322
|
+
added.addAll(guessedDecoders);
|
323
|
+
return guessed.set("decoders", added.build());
|
324
|
+
}
|
325
|
+
}
|
290
326
|
}
|
291
327
|
|
292
328
|
public static class GuessedNoticeError
|