Improve SingletonSet.spliterator()
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / SingletonSpliterators.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import java.util.Spliterator;
14 import java.util.function.Consumer;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.yangtools.concepts.Mutable;
18
19 /**
20  * Utility methods for instantiating {@link Spliterator}s containing a single element.
21  *
22  * @author Robert Varga
23  */
24 @Beta
25 @NonNullByDefault
26 public final class SingletonSpliterators {
27     private SingletonSpliterators() {
28
29     }
30
31     /**
32      * Create a new {@link Spliterator} reporting specified element. It has the following characteristics:
33      * <ul>
34      *   <li>{@link Spliterator#DISTINCT}</li>
35      *   <li>{@link Spliterator#IMMUTABLE}</li>
36      *   <li>{@link Spliterator#NONNULL}</li>
37      *   <li>{@link Spliterator#ORDERED}</li>
38      *   <li>{@link Spliterator#SIZED}</li>
39      *   <li>{@link Spliterator#SUBSIZED}</li>
40      * </ul>
41      *
42      * @param element Single element to report
43      * @param <T> the type of elements returned by this Spliterator
44      * @return A new spliterator
45      * @throws NullPointerException if element is null
46      */
47     public static <T> Spliterator<T> immutableOf(final T element) {
48         return new ImmutableNonNull<>(element);
49     }
50
51     /**
52      * Create a new {@link Spliterator} reporting a {@code null} element. It has the following characteristics:
53      * <ul>
54      *   <li>{@link Spliterator#DISTINCT}</li>
55      *   <li>{@link Spliterator#IMMUTABLE}</li>
56      *   <li>{@link Spliterator#ORDERED}</li>
57      *   <li>{@link Spliterator#SIZED}</li>
58      *   <li>{@link Spliterator#SUBSIZED}</li>
59      * </ul>
60      *
61      * @return A new spliterator
62      */
63     public static <@Nullable T> Spliterator<T> immutableOfNull() {
64         return new ImmutableNull<>();
65     }
66
67     private static final class ImmutableNonNull<T> implements Mutable, Spliterator<T> {
68         private final T element;
69
70         private boolean consumed;
71
72         private ImmutableNonNull(final T element) {
73             this.element = requireNonNull(element);
74         }
75
76         @Override
77         public boolean tryAdvance(final @Nullable Consumer<? super T> action) {
78             requireNonNull(action);
79             if (consumed) {
80                 return false;
81             }
82
83             action.accept(element);
84             consumed = true;
85             return true;
86         }
87
88         @Override
89         public @Nullable Spliterator<T> trySplit() {
90             return null;
91         }
92
93         @Override
94         public long estimateSize() {
95             return consumed ? 0 : 1;
96         }
97
98         @Override
99         public int characteristics() {
100             return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE
101                     | Spliterator.DISTINCT | Spliterator.ORDERED;
102         }
103     }
104
105     private static final class ImmutableNull<@Nullable E> implements Mutable, Spliterator<E> {
106         private boolean consumed;
107
108         @Override
109         public boolean tryAdvance(final @Nullable Consumer<? super E> action) {
110             requireNonNull(action);
111             if (consumed) {
112                 return false;
113             }
114
115             action.accept(null);
116             consumed = true;
117             return true;
118         }
119
120         @Override
121         public @Nullable Spliterator<E> trySplit() {
122             return null;
123         }
124
125         @Override
126         public long estimateSize() {
127             return consumed ? 0 : 1;
128         }
129
130         @Override
131         public int characteristics() {
132             return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | Spliterator.DISTINCT
133                     | Spliterator.ORDERED;
134         }
135     }
136 }