2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Verify.verify;
12 import static java.util.Objects.requireNonNull;
14 import com.google.common.collect.AbstractIterator;
15 import com.google.common.collect.Iterators;
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 org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.Nullable;
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.
29 * Unlike other collections, this view does not detect concurrent modification. Iteration is performed in order of
30 * increasing offset. In face of concurrent modification, number of elements returned through iteration may not match
31 * the size reported via {@link Collection#size()}.
33 * @author Robert Varga
35 abstract class StatementMap extends AbstractCollection<OriginalStmtCtx<?, ?, ?>> {
36 private static final class Empty extends StatementMap {
37 private static final Iterator<OriginalStmtCtx<?, ?, ?>> EMPTY_ITERATOR;
40 // This may look weird, but we really want to return two Iterator implementations from StatementMap, so that
41 // users have to deal with bimorphic invocation. Note that we want to invoke hasNext() here, as we want to
42 // initialize state to AbstractIterator.endOfData().
43 final Iterator<OriginalStmtCtx<?, ?, ?>> it = new Regular(0).iterator();
44 verify(!it.hasNext());
49 AbstractResumedStatement<?, ?, ?> get(final int index) {
54 StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
55 return index == 0 ? new Singleton(obj) : new Regular(index, obj);
64 StatementMap ensureCapacity(final int expectedLimit) {
65 return expectedLimit < 2 ? this : new Regular(expectedLimit);
69 public void forEach(final Consumer<? super OriginalStmtCtx<?, ?, ?>> action) {
74 public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
75 return EMPTY_ITERATOR;
79 private static final class Regular extends StatementMap {
80 private OriginalStmtCtx<?, ?, ?>[] elements;
83 Regular(final int expectedLimit) {
84 elements = new OriginalStmtCtx<?, ?, ?>[expectedLimit];
87 Regular(final int index, final OriginalStmtCtx<?, ?, ?> object) {
88 this(index + 1, index, object);
91 Regular(final OriginalStmtCtx<?, ?, ?> object0, final int index, final OriginalStmtCtx<?, ?, ?> object) {
92 this(index + 1, 0, object0);
93 elements[index] = requireNonNull(object);
97 Regular(final int expectedLimit, final int index, final OriginalStmtCtx<?, ?, ?> object) {
99 elements[index] = requireNonNull(object);
104 OriginalStmtCtx<?, ?, ?> get(final int index) {
105 return index >= elements.length ? null : elements[index];
109 StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
110 if (index < elements.length) {
111 checkArgument(elements[index] == null);
113 // FIXME: detect linear growth
114 elements = Arrays.copyOf(elements, index + 1);
117 elements[index] = requireNonNull(obj);
128 StatementMap ensureCapacity(final int expectedLimit) {
129 if (elements.length < expectedLimit) {
130 elements = Arrays.copyOf(elements, expectedLimit);
136 public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
137 return new Iter(this);
140 private static final class Iter extends AbstractIterator<OriginalStmtCtx<?, ?, ?>> {
141 private int nextOffset = 0;
144 Iter(final Regular map) {
145 this.map = requireNonNull(map);
149 protected OriginalStmtCtx<?, ?, ?> computeNext() {
150 while (nextOffset < map.elements.length) {
151 final OriginalStmtCtx<?, ?, ?> ret = map.elements[nextOffset++];
163 private static final class Singleton extends StatementMap {
164 private final OriginalStmtCtx<?, ?, ?> object;
166 Singleton(final OriginalStmtCtx<?, ?, ?> object) {
167 this.object = requireNonNull(object);
171 OriginalStmtCtx<?, ?, ?> get(final int index) {
172 return index == 0 ? object : null;
176 StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
177 checkArgument(index != 0);
178 return new Regular(object, index, obj);
187 StatementMap ensureCapacity(final int expectedLimit) {
188 return expectedLimit < 2 ? this : new Regular(expectedLimit, 0, object);
192 public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
193 return Iterators.singletonIterator(object);
197 private static final @NonNull StatementMap EMPTY = new Empty();
200 * Return an empty map.
202 * @return An empty map.
204 static @NonNull StatementMap empty() {
209 * Return the statement context at specified index.
211 * @param index Element index, must be non-negative
212 * @return Requested element or null if there is no element at that index
214 abstract @Nullable OriginalStmtCtx<?, ?, ?> get(int index);
217 * Add a statement at specified index.
219 * @param index Element index, must be non-negative
220 * @param obj Object to store
221 * @return New statement map
222 * @throws IllegalArgumentException if the index is already occupied
224 abstract @NonNull StatementMap put(int index, @NonNull OriginalStmtCtx<?, ?, ?> obj);
227 * Ensure storage space for at least {@code explectedLimit} substatements.
229 * @param expectedLimit Expected number of substatements
230 * @return New statement map
232 abstract @NonNull StatementMap ensureCapacity(int expectedLimit);