2 * (C) Copyright 2016 Pantheon Technologies, s.r.o. and others.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.opendaylight.yangtools.triemap;
18 import java.util.AbstractMap.SimpleImmutableEntry;
19 import java.util.Iterator;
20 import java.util.Map.Entry;
21 import java.util.NoSuchElementException;
22 import java.util.Optional;
25 * Mimic immutable ListMap in Scala
27 * @author Roman Levenstein <romixlev@gmail.com>
31 final class ListMap<K, V> {
35 // Modified during remove0 only
36 private ListMap<K, V> next;
38 private ListMap(final K k, final V v) {
42 private ListMap(final K k, final V v, final ListMap<K, V> next) {
48 static <K,V> ListMap<K, V> map(final K k1, final V v1, final K k2, final V v2) {
49 return new ListMap<>(k1, v1, new ListMap<>(k2, v2));
52 Optional<Entry<K, V>> maybeSingleton() {
53 return next != null ? Optional.empty() : Optional.of(new SimpleImmutableEntry<>(k, v));
58 for (ListMap<?, ?> wlk = next; wlk != null; wlk = wlk.next) {
64 Optional<V> get(final Equivalence<? super K> equiv, final K key) {
65 // We do not perform recursion on purpose here, so we do not run out of stack if the key hashing fails.
66 ListMap<K, V> head = this;
68 if (equiv.equivalent(head.k, key)) {
69 return Optional.of(head.v);
73 } while (head != null);
75 return Optional.empty();
78 ListMap<K,V> add(final Equivalence<? super K> equiv, final K key, final V value) {
79 return new ListMap<>(key, value, remove(equiv, key));
82 ListMap<K, V> remove(final Equivalence<? super K> equiv, final K key) {
83 if (!contains(equiv, key)) {
90 private boolean contains(final Equivalence<? super K> equiv, final K key) {
91 // We do not perform recursion on purpose here, so we do not run out of stack if the key hashing fails.
92 ListMap<K, V> head = this;
94 if (equiv.equivalent(head.k, key)) {
98 } while (head != null);
103 private ListMap<K, V> remove0(final K key) {
104 ListMap<K, V> n = this;
105 ListMap<K, V> ret = null;
106 ListMap<K, V> lastN = null;
108 if (key.equals(n.k)) {
114 lastN.next = new ListMap<>(n.k, n.v);
117 ret = new ListMap<>(n.k, n.v);
125 Iterator<Entry<K, V>> iterator() {
126 return new NodeIterator<>(this);
129 static final class NodeIterator<K,V> implements Iterator<Entry<K, V>> {
130 private ListMap<K, V> n;
132 NodeIterator(final ListMap<K, V> n) {
137 public boolean hasNext() {
142 public Entry<K, V> next() {
144 throw new NoSuchElementException();
147 final Entry<K, V> res = new SimpleImmutableEntry<>(n.k, n.v);