Cleanup use of Guava library
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / StatementMap.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.yang.parser.stmt.reactor;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.AbstractIterator;
15 import com.google.common.collect.ImmutableList;
16 import java.util.AbstractCollection;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.Iterator;
20 import java.util.function.Consumer;
21 import javax.annotation.Nonnull;
22 import javax.annotation.Nullable;
23
24 /**
25  * Simple integer-to-StatementContextBase map optimized for size and restricted in scope of operations. It does not
26  * implement {@link java.util.Map} for simplicity's sake.
27  *
28  * @author Robert Varga
29  */
30 abstract class StatementMap {
31     private static final class Empty extends StatementMap {
32         @Override
33         StatementContextBase<?, ?, ?> get(final int index) {
34             return null;
35         }
36
37         @Override
38         StatementMap put(final int index, final StatementContextBase<?, ?, ?> object) {
39             return index == 0 ? new Singleton(object) : new Regular(index, object);
40         }
41
42         @Override
43         Collection<StatementContextBase<?, ?, ?>> values() {
44             return ImmutableList.of();
45         }
46
47         @Override
48         int size() {
49             return 0;
50         }
51     }
52
53     private static final class Regular extends StatementMap {
54         private StatementContextBase<?, ?, ?>[] elements;
55
56         Regular(final int index, final StatementContextBase<?, ?, ?> object) {
57             elements = new StatementContextBase<?, ?, ?>[index + 1];
58             elements[index] = requireNonNull(object);
59         }
60
61         Regular(final StatementContextBase<?, ?, ?> object0, final int index,
62                 final StatementContextBase<?, ?, ?> object) {
63             elements = new StatementContextBase<?, ?, ?>[index + 1];
64             elements[0] = requireNonNull(object0);
65             elements[index] = requireNonNull(object);
66         }
67
68         @Override
69         StatementContextBase<?, ?, ?> get(final int index) {
70             if (index >= elements.length) {
71                 return null;
72             }
73
74             return elements[index];
75         }
76
77         @Override
78         StatementMap put(final int index, final StatementContextBase<?, ?, ?> object) {
79             if (index < elements.length) {
80                 checkArgument(elements[index] == null);
81             } else {
82                 elements = Arrays.copyOf(elements, index + 1);
83             }
84
85             elements[index] = requireNonNull(object);
86             return this;
87         }
88
89         @Override
90         Collection<StatementContextBase<?, ?, ?>> values() {
91             return new RegularAsCollection<>(elements);
92         }
93
94         @Override
95         int size() {
96             return countElements(elements);
97         }
98     }
99
100     static int countElements(final Object[] elements) {
101         // Optimized for non-sparse case
102         int nulls = 0;
103         for (Object e : elements) {
104             if (e == null) {
105                 nulls++;
106             }
107         }
108
109         return elements.length - nulls;
110     }
111
112     private static final class RegularAsCollection<T> extends AbstractCollection<T> {
113         private final T[] elements;
114
115         RegularAsCollection(final T[] elements) {
116             this.elements = Preconditions.checkNotNull(elements);
117         }
118
119         @Override
120         public void forEach(final Consumer<? super T> action) {
121             for (T e : elements) {
122                 if (e != null) {
123                     action.accept(e);
124                 }
125             }
126         }
127
128         @Override
129         public boolean isEmpty() {
130             // This has a single-use and when it is instantiated, we know to have at least two items
131             return false;
132         }
133
134         @Override
135         public Iterator<T> iterator() {
136             return new AbstractIterator<T>() {
137                 private int nextOffset = 0;
138
139                 @Override
140                 protected T computeNext() {
141                     while (nextOffset < elements.length) {
142                         final T ret = elements[nextOffset++];
143                         if (ret != null) {
144                             return ret;
145                         }
146                     }
147
148                     return endOfData();
149                 }
150             };
151         }
152
153         @Override
154         public int size() {
155             return countElements(elements);
156         }
157     }
158
159     private static final class Singleton extends StatementMap {
160         private final StatementContextBase<?, ?, ?> object;
161
162         Singleton(final StatementContextBase<?, ?, ?> object) {
163             this.object = requireNonNull(object);
164         }
165
166         @Override
167         StatementContextBase<?, ?, ?> get(final int index) {
168             return index == 0 ? object : null;
169         }
170
171         @Override
172         StatementMap put(final int index, final StatementContextBase<?, ?, ?> object) {
173             checkArgument(index != 0);
174             return new Regular(this.object, index, object);
175         }
176
177         @Override
178         Collection<StatementContextBase<?, ?, ?>> values() {
179             return ImmutableList.of(object);
180         }
181
182         @Override
183         int size() {
184             return 1;
185         }
186     }
187
188     private static final StatementMap EMPTY = new Empty();
189
190     static StatementMap empty() {
191         return EMPTY;
192     }
193
194     /**
195      * Return the statement context at specified index.
196      *
197      * @param index Element index, must be non-negative
198      * @return Requested element or null if there is no element at that index
199      */
200     abstract @Nullable StatementContextBase<?, ?, ?> get(int index);
201
202     /**
203      * Add a statement at specified index.
204      *
205      * @param index Element index, must be non-negative
206      * @param object Object to store
207      * @return New statement map
208      * @throws IllegalArgumentException if the index is already occupied
209      */
210     abstract @Nonnull StatementMap put(int index, @Nonnull StatementContextBase<?, ?, ?> object);
211
212     /**
213      * Return a read-only view of the elements in this map. Unlike other maps, this view does not detect concurrent
214      * modification. Iteration is performed in order of increasing offset. In face of concurrent modification, number
215      * of elements returned through iteration may not match the size reported via {@link Collection#size()}.
216      *
217      * @return Read-only view of available statements.
218      */
219     abstract @Nonnull Collection<StatementContextBase<?, ?, ?>> values();
220
221     abstract int size();
222 }