/* * (C) Copyright 2016 Pantheon Technologies, s.r.o. and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.opendaylight.yangtools.triemap; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Iterator; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Optional; /** * Similar to Scala's ListMap. Stores a linked set of entries, guaranteed to contain unique entry keys. * * @author Robert Varga * * @param the type of keys * @param the type of values */ final class LNodeEntries extends LNodeEntry { // Modified during remove0 only private LNodeEntries next; private LNodeEntries(final K k, final V v) { this(k, v, null); } private LNodeEntries(final K k, final V v, final LNodeEntries next) { super(k, v); this.next = next; } static LNodeEntries map(final K k1, final V v1, final K k2, final V v2) { return new LNodeEntries<>(k1, v1, new LNodeEntries<>(k2, v2)); } Optional> maybeSingleton() { return next != null ? Optional.empty() : Optional.of(new SimpleImmutableEntry<>(key(), value())); } int size() { int sz = 1; for (LNodeEntries wlk = next; wlk != null; wlk = wlk.next) { sz++; } return sz; } LNodeEntry findEntry(final Equivalence equiv, final K key) { // We do not perform recursion on purpose here, so we do not run out of stack if the key hashing fails. LNodeEntries head = this; do { if (equiv.equivalent(head.key(), key)) { return head; } head = head.next; } while (head != null); return null; } LNodeEntries insert(final K key, final V value) { return new LNodeEntries<>(key, value, this); } LNodeEntries replace(final LNodeEntry entry, final V v) { return new LNodeEntries<>(entry.key(), v, remove(entry)); } LNodeEntries remove(final LNodeEntry entry) { if (entry == this) { return next; } final LNodeEntries ret = new LNodeEntries<>(key(), value()); LNodeEntries last = ret; LNodeEntries cur = next; while (cur != null) { if (entry.equals(cur)) { last.next = cur.next; return ret; } last.next = new LNodeEntries<>(cur.key(), cur.value()); last = last.next; cur = cur.next; } throw new IllegalStateException("Entry " + entry + " not found in entries " + this); } Iterator> iterator() { return new NodeIterator<>(this); } static final class NodeIterator implements Iterator> { private LNodeEntries n; NodeIterator(final LNodeEntries n) { this.n = n; } @Override public boolean hasNext() { return n != null; } @Override public Entry next() { if (n == null) { throw new NoSuchElementException(); } final Entry res = new SimpleImmutableEntry<>(n.key(), n.value()); n = n.next; return res; } } }