jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java
changeset 31530 aa87d96a02b1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java	Tue Jul 07 13:17:53 2015 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Completer which contains multiple completers and aggregates them together.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class AggregateCompleter
+    implements Completer
+{
+    private final List<Completer> completers = new ArrayList<Completer>();
+
+    public AggregateCompleter() {
+        // empty
+    }
+
+    /**
+     * Construct an AggregateCompleter with the given collection of completers.
+     * The completers will be used in the iteration order of the collection.
+     *
+     * @param completers the collection of completers
+     */
+    public AggregateCompleter(final Collection<Completer> completers) {
+        checkNotNull(completers);
+        this.completers.addAll(completers);
+    }
+
+    /**
+     * Construct an AggregateCompleter with the given completers.
+     * The completers will be used in the order given.
+     *
+     * @param completers the completers
+     */
+    public AggregateCompleter(final Completer... completers) {
+        this(Arrays.asList(completers));
+    }
+
+    /**
+     * Retrieve the collection of completers currently being aggregated.
+     *
+     * @return the aggregated completers
+     */
+    public Collection<Completer> getCompleters() {
+        return completers;
+    }
+
+    /**
+     * Perform a completion operation across all aggregated completers.
+     *
+     * @see Completer#complete(String, int, java.util.List)
+     * @return the highest completion return value from all completers
+     */
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        // buffer could be null
+        checkNotNull(candidates);
+
+        List<Completion> completions = new ArrayList<Completion>(completers.size());
+
+        // Run each completer, saving its completion results
+        int max = -1;
+        for (Completer completer : completers) {
+            Completion completion = new Completion(candidates);
+            completion.complete(completer, buffer, cursor);
+
+            // Compute the max cursor position
+            max = Math.max(max, completion.cursor);
+
+            completions.add(completion);
+        }
+
+        // Append candidates from completions which have the same cursor position as max
+        for (Completion completion : completions) {
+            if (completion.cursor == max) {
+                candidates.addAll(completion.candidates);
+            }
+        }
+
+        return max;
+    }
+
+    /**
+     * @return a string representing the aggregated completers
+     */
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+            "completers=" + completers +
+            '}';
+    }
+
+    private class Completion
+    {
+        public final List<CharSequence> candidates;
+
+        public int cursor;
+
+        public Completion(final List<CharSequence> candidates) {
+            checkNotNull(candidates);
+            this.candidates = new LinkedList<CharSequence>(candidates);
+        }
+
+        public void complete(final Completer completer, final String buffer, final int cursor) {
+            checkNotNull(completer);
+            this.cursor = completer.complete(buffer, cursor, candidates);
+        }
+    }
+}