package org.opendaylight.yangtools.triemap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; /** * Mimic immutable ListMap in Scala * * @author Roman Levenstein * * @param */ abstract class ListMap { ListMap next; static ListMap map(K k, V v, ListMap tail){ return new Node (k, v, tail); } static ListMap map(K k, V v){ return new Node (k, v, null); } static ListMap map(K k1, V v1, K k2, V v2){ return new Node (k1, v1, new Node(k2,v2, null)); } public abstract int size (); public abstract boolean isEmpty() ; abstract public boolean contains(K k, V v); abstract public boolean contains(K key); abstract public Option get (K key); abstract public ListMap add (K key, V value); abstract public ListMap remove (K key); abstract public Iterator> iterator(); static class EmptyListMap extends ListMap { public ListMap add (K key, V value) { return ListMap.map(key, value, null); } public boolean contains(K k, V v) { return false; } public boolean contains(K k) { return false; } public ListMap remove(K key) { return this; } @Override public int size () { return 0; } @Override public boolean isEmpty () { return true; } @Override public Option get (K key) { return Option.makeOption (null); } @Override public Iterator> iterator () { return new EmptyListMapIterator (); } static class EmptyListMapIterator implements Iterator> { @Override public boolean hasNext () { return false; } @Override public Entry next () { return null; } @Override public void remove () { throw new RuntimeException("Operation not supported"); } } } static class Node extends ListMap { final K k; final V v; Node(K k, V v, ListMap next) { this.k = k; this.v = v; this.next = next; } public ListMap add (K key, V value) { return ListMap.map(key, value, remove (key)); } public boolean contains(K k, V v) { if(k.equals (this.k) && v.equals (this.v)) return true; else if(next != null) return next.contains (k, v); return false; } public boolean contains(K k) { if(k.equals (this.k)) return true; else if(next != null) return next.contains (k); return false; } public ListMap remove(K key) { if(!contains(key)) return this; else return remove0(key); } private ListMap remove0 (K key) { ListMap n = this; ListMap newN = null; ListMap lastN = null; while (n != null) { if(n instanceof EmptyListMap) { newN.next = n; break; } Node nn = (Node)n; if (key.equals (nn.k)) { n = n.next; continue; } else { if (newN != null) { lastN.next = ListMap.map (nn.k, nn.v, null); lastN = lastN.next; } else { newN = ListMap.map (nn.k, nn.v, null); lastN = newN; } } n = n.next; } return newN; } @Override public int size () { if(next == null) return 1; else return 1+next.size (); } @Override public boolean isEmpty () { return false; } @Override public Option get (K key) { if(key.equals (k)) return Option.makeOption (v); if(next != null) return next.get (key); return Option.makeOption (null); } @Override public Iterator> iterator () { return new NodeIterator (this); } static class NodeIterator implements Iterator> { ListMap n; public NodeIterator (Node n) { this.n = n; } @Override public boolean hasNext () { // return n!= null && n.next != null && !(n.next instanceof EmptyListMap); return n!= null && !(n instanceof EmptyListMap); } @Override public Entry next () { if (n instanceof Node) { Node nn = (Node) n; Pair res = new Pair (nn.k, nn.v); n = n.next; return res; } else { return null; } } @Override public void remove () { throw new RuntimeException("Operation not supported"); } } } }