Add filter that combines several filters into one.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 5 Jun 2013 05:05:54 +0000 (07:05 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 6 Jun 2013 20:28:12 +0000 (22:28 +0200)
src/main/java/net/pterodactylus/sonitus/data/filter/PipelineFilter.java [new file with mode: 0644]

diff --git a/src/main/java/net/pterodactylus/sonitus/data/filter/PipelineFilter.java b/src/main/java/net/pterodactylus/sonitus/data/filter/PipelineFilter.java
new file mode 100644 (file)
index 0000000..59e34be
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Sonitus - PipelineFilter.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sonitus.data.filter;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import net.pterodactylus.sonitus.data.AbstractFilter;
+import net.pterodactylus.sonitus.data.DataPacket;
+import net.pterodactylus.sonitus.data.Filter;
+import net.pterodactylus.sonitus.data.Metadata;
+import net.pterodactylus.sonitus.data.Pipeline.Connection;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+/**
+ * {@link Filter} that combines several filters into one.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PipelineFilter extends AbstractFilter implements Filter {
+
+       /** The first filter. */
+       private final Filter source;
+
+       /** All following filters. */
+       private final List<Filter> filters = Lists.newArrayList();
+
+       /** The last filter (for convenience). */
+       private final Filter lastFilter;
+
+       /**
+        * Creates a new pipeline filter.
+        *
+        * @param name
+        *              The name of the filter
+        * @param source
+        *              The first source of the filter
+        * @param filters
+        *              All other filters in correct order
+        */
+       private PipelineFilter(String name, Filter source, Collection<Filter> filters) {
+               super(name);
+               this.source = source;
+               this.filters.addAll(filters);
+               this.lastFilter = this.filters.get(filters.size() - 1);
+       }
+
+       //
+       // FILTER METHODS
+       //
+
+       @Override
+       public Metadata metadata() {
+               return lastFilter.metadata();
+       }
+
+       @Override
+       public void open(Metadata metadata) throws IOException {
+               /* open the source and all filters in the correct order. */
+               source.open(metadata);
+               Metadata currentMetadata = source.metadata();
+               Filter currentSource = source;
+               for (Filter filter : filters) {
+                       filter.open(currentMetadata);
+                       currentMetadata = filter.metadata();
+                       Connection connection = new Connection(currentSource, Arrays.asList(filter));
+                       String threadName = String.format("%s → %s.", connection.source().name(), FluentIterable.from(connection.sinks()).transform(new Function<Filter, String>() {
+
+                               @Override
+                               public String apply(Filter sink) {
+                                       return sink.name();
+                               }
+                       }));
+                       new Thread(connection, threadName).start();
+                       currentSource = filter;
+               }
+       }
+
+       @Override
+       public DataPacket get(int bufferSize) throws IOException {
+               return lastFilter.get(bufferSize);
+       }
+
+       @Override
+       public void process(DataPacket dataPacket) throws IOException {
+               source.process(dataPacket);
+       }
+
+       //
+       // STATIC METHODS
+       //
+
+       /**
+        * Returns a builder that can create pipeline filters.
+        *
+        * @param source
+        *              The source filter of the pipeline
+        * @return The pipeline filter builder
+        */
+       public static Builder builder(Filter source) {
+               return new Builder(source);
+       }
+
+       /**
+        * Builder for a {@link PipelineFilter}.
+        *
+        * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+        */
+       public static class Builder {
+
+               /** The source of the pipeline. */
+               private final Filter source;
+
+               /** All other filters of the pipeline. */
+               private final List<Filter> filters = Lists.newArrayList();
+
+               /**
+                * Creates a new builder with the given source.
+                *
+                * @param source
+                *              The source of the pipeline filter
+                */
+               private Builder(Filter source) {
+                       this.source = source;
+               }
+
+               /**
+                * Connects the given filter at the end of the pipeline being build.
+                *
+                * @param filter
+                *              The filter to add
+                * @return This builder
+                */
+               public Builder to(Filter filter) {
+                       filters.add(filter);
+                       return this;
+               }
+
+               /**
+                * Builds a filter using the given name. If no filters other than the source
+                * have been added, only the source filter is being returned.
+                *
+                * @param name
+                *              The name of the pipeline filter to build
+                * @return The created filter, or the source filter
+                */
+               public Filter build(String name) {
+                       if (filters.isEmpty()) {
+                               return source;
+                       }
+                       return new PipelineFilter(name, source, filters);
+               }
+
+       }
+
+}