package org.embulk.spi.util; import java.util.List; import com.google.common.collect.ImmutableList; import org.embulk.config.TaskSource; import org.embulk.config.ConfigSource; import org.embulk.config.ConfigDiff; import org.embulk.plugin.PluginType; import org.embulk.spi.ExecSession; import org.embulk.spi.Schema; import org.embulk.spi.PageOutput; import org.embulk.spi.FilterPlugin; public abstract class Filters { private Filters() { } public static List<PluginType> getPluginTypes(List<ConfigSource> configs) { ImmutableList.Builder<PluginType> builder = ImmutableList.builder(); for (ConfigSource config : configs) { builder.add(config.get(PluginType.class, "type")); } return builder.build(); } public static List<FilterPlugin> newFilterPluginsFromConfigSources(ExecSession exec, List<ConfigSource> configs) { return newFilterPlugins(exec, getPluginTypes(configs)); } public static List<FilterPlugin> newFilterPlugins(ExecSession exec, List<PluginType> pluginTypes) { ImmutableList.Builder<FilterPlugin> builder = ImmutableList.builder(); for (PluginType pluginType : pluginTypes) { builder.add(exec.newPlugin(FilterPlugin.class, pluginType)); } return builder.build(); } public interface Control { public void run(List<TaskSource> taskSources, List<Schema> filterSchemas); } public static void transaction(List<FilterPlugin> plugins, List<ConfigSource> configs, Schema inputSchema, Filters.Control control) { new RecursiveControl(plugins, configs, control).transaction(inputSchema); } public static PageOutput open(List<FilterPlugin> plugins, List<TaskSource> taskSources, List<Schema> filterSchemas, PageOutput output) { PageOutput out = output; int pos = plugins.size() - 1; while (pos >= 0) { out = plugins.get(pos).open(taskSources.get(pos), filterSchemas.get(pos), filterSchemas.get(pos + 1), out); pos--; } return out; } private static class RecursiveControl { private final List<FilterPlugin> plugins; private final List<ConfigSource> configs; private final Filters.Control finalControl; private final ImmutableList.Builder<TaskSource> taskSources; private final ImmutableList.Builder<Schema> filterSchemas; private int pos; RecursiveControl(List<FilterPlugin> plugins, List<ConfigSource> configs, Filters.Control finalControl) { this.plugins = plugins; this.configs = configs; this.finalControl = finalControl; this.taskSources = ImmutableList.builder(); this.filterSchemas = ImmutableList.builder(); } public void transaction(Schema inputSchema) { filterSchemas.add(inputSchema); if (pos < plugins.size()) { plugins.get(pos).transaction(configs.get(pos), inputSchema, new FilterPlugin.Control() { public void run(TaskSource taskSource, Schema outputSchema) { taskSources.add(taskSource); pos++; transaction(outputSchema); } }); } else { finalControl.run(taskSources.build(), filterSchemas.build()); } } } }