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

org.organicdesign.fp.collections.UnmodMap Maven / Gradle / Ivy

// Copyright 2015-04-13 PlanBase Inc. & Glen Peterson
//
// 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.organicdesign.fp.collections;

import org.organicdesign.fp.tuple.Tuple2;

import java.util.Iterator;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 An unmodifiable map.
 This cannot extend Collection because the remove() method would then be inherited
 from both Collection and Map and Collection.remove() returns a boolean while Map.remove() returns
 a V (the type of the value in the key/value pair).  Maybe an UnmodSizedIterable is called for?
 */
public interface UnmodMap extends Map, UnmodIterable> {
    // ========================================== Static ==========================================
    /**
     * A map entry (key-value pair).  The UnmodMap.entrySet method returns
     * a collection-view of the map, whose elements are of this class.  The
     * only way to obtain a reference to a map entry is from the
     * iterator of this collection-view.
     *
     * @see UnmodMap#entrySet()
     */
    interface UnEntry extends Map.Entry {
        /** Not allowed - this is supposed to be unmodifiable */
        @SuppressWarnings("deprecation")
        @Override @Deprecated default V setValue(V value) {
            throw new UnsupportedOperationException("Modification attempted");
        }

        static  UnEntry entryToUnEntry(Map.Entry entry) {
            return Tuple2.of(entry.getKey(), entry.getValue());
        }

        static 
        UnmodIterator> entryIterToUnEntryUnIter(Iterator> innerIter) {
            return new UnmodIterator>() {
                @Override public boolean hasNext() { return innerIter.hasNext(); }
                @Override public UnEntry next() {
                    return UnmodMap.UnEntry.entryToUnEntry(innerIter.next());
                }
            };
        }

        static  UnmodSortedIterator> unSortIterEntToUnSortIterUnEnt(
                UnmodSortedIterator> innerIter) {
            return new UnmodSortedIterator>() {
                @Override public boolean hasNext() { return innerIter.hasNext(); }
                @Override public UnEntry next() {
                    return UnmodMap.UnEntry.entryToUnEntry(innerIter.next());
                }
            };
        }
//
//        class Impl implements UnEntry {
//            private final K key;
//            private final V val;
//            private Impl(K k, V v) { key = k; val = v; }
//            @Override public K getKey() { return key; }
//            @Override public V getValue() { return val; }
//            @Override
//            public boolean equals(Object other) {
//                if (this == other) { return true; }
//                if ((other == null) || !(other instanceof UnEntry)) { return false; }
//
//                UnEntry that = (UnEntry) other;
//                return Objects.equals(this.key, that.getKey()) &&
//                       Objects.equals(this.getValue(), that.getValue());
//            }
//
//            @Override
//            public int hashCode() {
//                int ret = 0;
//                if (key != null) { ret = key.hashCode(); }
//                if (val != null) { return ret ^ val.hashCode(); }
//                // If it's uninitialized, it's equal to every other uninitialized instance.
//                return ret;
//            }
//
//            @Override public String toString() {
//                return "UnEntry(" + key + "," + val + ")";
//            }
//        };
    }

    UnmodMap EMPTY = new UnmodMap() {
        @Override public UnmodSet> entrySet() { return UnmodSet.empty(); }
        @Override public UnmodSet keySet() { return UnmodSet.empty(); }
        @Override public UnmodCollection values() { return UnmodCollection.empty(); }
        @Override public int size() { return 0; }
        @Override public boolean isEmpty() { return true; }
        @Override public UnmodIterator> iterator() {
            return UnmodIterator.empty();
        }
        @Override public boolean containsKey(Object key) { return false; }
        @Override public boolean containsValue(Object value) { return false; }
        @Override public Object get(Object key) { return null; }
    };
    @SuppressWarnings("unchecked")
    static  UnmodMap empty() { return (UnmodMap) EMPTY; }

    // ========================================= Instance =========================================

    // Modification Operations

    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default void clear() {
        throw new UnsupportedOperationException("Modification attempted");
    }

    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated
    default V compute(K key, BiFunction remappingFunction) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated
    default V computeIfAbsent(K key, Function mappingFunction) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated
    default V computeIfPresent(K key,
                               BiFunction remappingFunction) {
        throw new UnsupportedOperationException("Modification attempted");
    }
// boolean	containsKey(Object key)
// boolean	containsValue(Object value)

    /**
     Most maps are not designed for this - the default implementation has O(n) performance.
     {@inheritDoc}
     */
    @SuppressWarnings("SuspiciousMethodCalls")
    @Override default boolean containsValue(Object value) { return this.values().contains(value); }

    /**
     Returns a view of the mappings contained in this map.  The set should actually contain
     UnmodMap.UnEntry items, but that return signature is illegal in Java, so you'll just have to
     remember.
     */
    @Override
    UnmodSet> entrySet();

// boolean	equals(Object o)

//    @Override default boolean equals(Object other) {
//        // Cheapest operation first...
//        if (this == other) { return true; }
//
//        if ( (other == null) ||
//                !(other instanceof Map) ||
//                (this.hashCode() != other.hashCode()) ) {
//            return false;
//        }
//        // Details...
//        final Map that = (Map) other;
//        if (this.size() != that.size()) {
//            return false;
//        }
//        return this.entrySet().containsAll(that.entrySet());
//    }

// default void	forEach(BiConsumer action)
// V	get(Object key)
// default V	getOrDefault(Object key, V defaultValue)

//    @Override default int hashCode() {
//        if (size() == 0) { return 0; }
//        return Arrays.hashCode(entrySet().toArray());
//    };

    /** {@inheritDoc} */
    @Override default boolean isEmpty() { return size() == 0; }

    /** Returns a view of the keys contained in this map. */
    @Override
    UnmodSet keySet();

    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated
    default V merge(K key, V value,
                    BiFunction remappingFunction) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default V put(K key, V value) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default void putAll(Map m) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default V putIfAbsent(K key, V value) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default V remove(Object key) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default boolean remove(Object key, Object value) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default boolean replace(K key, V oldValue, V newValue) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated default V replace(K key, V value) {
        throw new UnsupportedOperationException("Modification attempted");
    }
    /** Not allowed - this is supposed to be unmodifiable */
    @Override @Deprecated
    default void replaceAll(BiFunction function) {
        throw new UnsupportedOperationException("Modification attempted");
    }

// int	size()

    /** Returns a view of the values contained in this map. */
    @Override
    UnmodCollection values();
}