Improve SingletonSet.spliterator() 69/72469/4
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 30 May 2018 10:31:24 +0000 (12:31 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 30 May 2018 14:32:57 +0000 (16:32 +0200)
We can use a Iterator-less version of the spliterator, adding
further characteristics. Expose these spliterators via
SingletonSpliterators utility class.

Change-Id: I3d7e19cc303c2f0c9c9d79d173bb78d8d5b77eac
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
common/util/src/main/java/org/opendaylight/yangtools/util/SingletonSet.java
common/util/src/main/java/org/opendaylight/yangtools/util/SingletonSpliterators.java [new file with mode: 0644]

index 76359e2f7ccf85b4a10facef097a36ddee7adcc4..091ae4c1dba6b3e4ca67a3021a36c43b5043fbea 100644 (file)
@@ -15,6 +15,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Spliterator;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.concepts.Immutable;
 
@@ -46,6 +47,11 @@ public abstract class SingletonSet<E> implements Set<E>, Immutable, Serializable
             return null;
         }
 
+        @Override
+        public Spliterator<Object> spliterator() {
+            return SingletonSpliterators.immutableOfNull();
+        }
+
         @Override
         public String toString() {
             return "[null]";
@@ -81,6 +87,9 @@ public abstract class SingletonSet<E> implements Set<E>, Immutable, Serializable
         return Iterators.singletonIterator(getElement());
     }
 
+    @Override
+    public abstract Spliterator<E> spliterator();
+
     @Nonnull
     @Override
     public final Object[] toArray() {
@@ -201,5 +210,10 @@ public abstract class SingletonSet<E> implements Set<E>, Immutable, Serializable
         public String toString() {
             return "[" + element + ']';
         }
+
+        @Override
+        public Spliterator<E> spliterator() {
+            return SingletonSpliterators.immutableOf(element);
+        }
     }
 }
diff --git a/common/util/src/main/java/org/opendaylight/yangtools/util/SingletonSpliterators.java b/common/util/src/main/java/org/opendaylight/yangtools/util/SingletonSpliterators.java
new file mode 100644 (file)
index 0000000..d67626c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.util;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Mutable;
+
+/**
+ * Utility methods for instantiating {@link Spliterator}s containing a single element.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public final class SingletonSpliterators {
+    private SingletonSpliterators() {
+
+    }
+
+    /**
+     * Create a new {@link Spliterator} reporting specified element. It has the following characteristics:
+     * <ul>
+     *   <li>{@link Spliterator#DISTINCT}</li>
+     *   <li>{@link Spliterator#IMMUTABLE}</li>
+     *   <li>{@link Spliterator#NONNULL}</li>
+     *   <li>{@link Spliterator#ORDERED}</li>
+     *   <li>{@link Spliterator#SIZED}</li>
+     *   <li>{@link Spliterator#SUBSIZED}</li>
+     * </ul>
+     *
+     * @param element Single element to report
+     * @param <T> the type of elements returned by this Spliterator
+     * @return A new spliterator
+     * @throws NullPointerException if element is null
+     */
+    public static <T> Spliterator<T> immutableOf(final T element) {
+        return new ImmutableNonNull<>(element);
+    }
+
+    /**
+     * Create a new {@link Spliterator} reporting a {@code null} element. It has the following characteristics:
+     * <ul>
+     *   <li>{@link Spliterator#DISTINCT}</li>
+     *   <li>{@link Spliterator#IMMUTABLE}</li>
+     *   <li>{@link Spliterator#ORDERED}</li>
+     *   <li>{@link Spliterator#SIZED}</li>
+     *   <li>{@link Spliterator#SUBSIZED}</li>
+     * </ul>
+     *
+     * @return A new spliterator
+     */
+    public static <@Nullable T> Spliterator<T> immutableOfNull() {
+        return new ImmutableNull<>();
+    }
+
+    private static final class ImmutableNonNull<T> implements Mutable, Spliterator<T> {
+        private final T element;
+
+        private boolean consumed;
+
+        private ImmutableNonNull(final T element) {
+            this.element = requireNonNull(element);
+        }
+
+        @Override
+        public boolean tryAdvance(final @Nullable Consumer<? super T> action) {
+            requireNonNull(action);
+            if (consumed) {
+                return false;
+            }
+
+            action.accept(element);
+            consumed = true;
+            return true;
+        }
+
+        @Override
+        public @Nullable Spliterator<T> trySplit() {
+            return null;
+        }
+
+        @Override
+        public long estimateSize() {
+            return consumed ? 0 : 1;
+        }
+
+        @Override
+        public int characteristics() {
+            return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE
+                    | Spliterator.DISTINCT | Spliterator.ORDERED;
+        }
+    }
+
+    private static final class ImmutableNull<@Nullable E> implements Mutable, Spliterator<E> {
+        private boolean consumed;
+
+        @Override
+        public boolean tryAdvance(final @Nullable Consumer<? super E> action) {
+            requireNonNull(action);
+            if (consumed) {
+                return false;
+            }
+
+            action.accept(null);
+            consumed = true;
+            return true;
+        }
+
+        @Override
+        public @Nullable Spliterator<E> trySplit() {
+            return null;
+        }
+
+        @Override
+        public long estimateSize() {
+            return consumed ? 0 : 1;
+        }
+
+        @Override
+        public int characteristics() {
+            return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | Spliterator.DISTINCT
+                    | Spliterator.ORDERED;
+        }
+    }
+}