All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cedarsoftware.util.SealableNavigableMap Maven / Gradle / Ivy

There is a newer version: 2.18.0
Show newest version
package com.cedarsoftware.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.function.Supplier;

/**
 * SealableNavigableMap provides a NavigableMap or NavigableMap wrapper that can be 'sealed' and 'unsealed.'
 * When sealed, the Map is mutable, when unsealed it is immutable (read-only). The view methods keySet(), entrySet(),
 * values(), navigableKeySet(), descendingMap(), descendingKeySet(), subMap(), headMap(), and tailMap() return a view
 * that honors the Supplier's sealed state.  The sealed state can be changed as often as needed.
 * 

* NOTE: Please do not reformat this code as the current format makes it easy to see the overall structure. *

* @author John DeRegnaucourt *
* Copyright (c) Cedar Software LLC *

* 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 *

* License *

* 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. */ public class SealableNavigableMap implements NavigableMap { private final NavigableMap navMap; private final transient Supplier sealedSupplier; /** * Create a SealableNavigableMap. Since a Map is not supplied, this will use a ConcurrentSkipListMap internally. * If you want a TreeMap to be used internally, use the SealableMap constructor that takes a NavigableMap and pass * it the instance you want it to wrap. * @param sealedSupplier {@code Supplier} that returns 'true' to indicate sealed, 'false' for mutable. */ public SealableNavigableMap(Supplier sealedSupplier) { this.sealedSupplier = sealedSupplier; this.navMap = new ConcurrentSkipListMap<>(); } /** * Create a NavigableSealableMap. Since NavigableMap is not supplied, the elements from the passed in SortedMap * will be copied to an internal ConcurrentSkipListMap. If you want to use a TreeMap for example, use the * SealableNavigableMap constructor that takes a NavigableMap and pass it the instance you want it to wrap. * @param map SortedMap to supply initial elements. These are copied to an internal ConcurrentSkipListMap. * @param sealedSupplier {@code Supplier} that returns 'true' to indicate sealed, 'false' for mutable. */ public SealableNavigableMap(SortedMap map, Supplier sealedSupplier) { this.sealedSupplier = sealedSupplier; this.navMap = new ConcurrentSkipListMap<>(map); } /** * Use this constructor to wrap a NavigableMap (any kind of NavigableMap) and make it a SealableNavigableMap. * No duplicate of the Map is created and the original map is operated on directly if unsealed, or protected * from changes if sealed. * @param map NavigableMap instance to protect. * @param sealedSupplier {@code Supplier} that returns 'true' to indicate sealed, 'false' for mutable. */ public SealableNavigableMap(NavigableMap map, Supplier sealedSupplier) { this.sealedSupplier = sealedSupplier; this.navMap = map; } private void throwIfSealed() { if (sealedSupplier.get()) { throw new UnsupportedOperationException("This map has been sealed and is now immutable"); } } // Immutable APIs public boolean equals(Object o) { return navMap.equals(o); } public int hashCode() { return navMap.hashCode(); } public String toString() { return navMap.toString(); } public boolean isEmpty() { return navMap.isEmpty(); } public boolean containsKey(Object key) { return navMap.containsKey(key); } public boolean containsValue(Object value) { return navMap.containsValue(value); } public int size() { return navMap.size(); } public V get(Object key) { return navMap.get(key); } public Comparator comparator() { return navMap.comparator(); } public K firstKey() { return navMap.firstKey(); } public K lastKey() { return navMap.lastKey(); } public Set keySet() { return new SealableSet<>(navMap.keySet(), sealedSupplier); } public Collection values() { return new SealableList<>(new ArrayList<>(navMap.values()), sealedSupplier); } public Set> entrySet() { return new SealableSet<>(navMap.entrySet(), sealedSupplier); } public Map.Entry lowerEntry(K key) { return navMap.lowerEntry(key); } public K lowerKey(K key) { return navMap.lowerKey(key); } public Map.Entry floorEntry(K key) { return navMap.floorEntry(key); } public K floorKey(K key) { return navMap.floorKey(key); } public Map.Entry ceilingEntry(K key) { return navMap.ceilingEntry(key); } public K ceilingKey(K key) { return navMap.ceilingKey(key); } public Map.Entry higherEntry(K key) { return navMap.higherEntry(key); } public K higherKey(K key) { return navMap.higherKey(key); } public Map.Entry firstEntry() { return navMap.firstEntry(); } public Map.Entry lastEntry() { return navMap.lastEntry(); } public NavigableMap descendingMap() { return new SealableNavigableMap<>(navMap.descendingMap(), sealedSupplier); } public NavigableSet navigableKeySet() { return new SealableNavigableSet<>(navMap.navigableKeySet(), sealedSupplier); } public NavigableSet descendingKeySet() { return new SealableNavigableSet<>(navMap.descendingKeySet(), sealedSupplier); } public SortedMap subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { return new SealableNavigableMap<>(navMap.subMap(fromKey, fromInclusive, toKey, toInclusive), sealedSupplier); } public SortedMap headMap(K toKey) { return headMap(toKey, false); } public NavigableMap headMap(K toKey, boolean inclusive) { return new SealableNavigableMap<>(navMap.headMap(toKey, inclusive), sealedSupplier); } public SortedMap tailMap(K fromKey) { return tailMap(fromKey, true); } public NavigableMap tailMap(K fromKey, boolean inclusive) { return new SealableNavigableMap<>(navMap.tailMap(fromKey, inclusive), sealedSupplier); } // Mutable APIs public Map.Entry pollFirstEntry() { throwIfSealed(); return navMap.pollFirstEntry(); } public Map.Entry pollLastEntry() { throwIfSealed(); return navMap.pollLastEntry(); } public V put(K key, V value) { throwIfSealed(); return navMap.put(key, value); } public V remove(Object key) { throwIfSealed(); return navMap.remove(key); } public void putAll(Map m) { throwIfSealed(); navMap.putAll(m); } public void clear() { throwIfSealed(); navMap.clear(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy