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

org.jhotdraw8.icollection.facade.ImmutableMapFacade Maven / Gradle / Ivy

/*
 * @(#)ImmutableMapFacade.java
 * Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
 */

package org.jhotdraw8.icollection.facade;

import org.jhotdraw8.icollection.immutable.ImmutableMap;
import org.jhotdraw8.icollection.impl.iteration.Iterators;
import org.jhotdraw8.icollection.readonly.AbstractReadOnlyMap;
import org.jhotdraw8.icollection.readonly.ReadOnlyCollection;
import org.jspecify.annotations.Nullable;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Spliterator;
import java.util.function.Function;

/**
 * Provides a {@link ImmutableMap} facade to a set of {@code ImmutableMap} functions.
 *
 * @param  the key type
 * @param  the element type
 */
public class ImmutableMapFacade extends AbstractReadOnlyMap implements ImmutableMap {

    private final Map target;
    private final Function, Map> cloneFunction;

    public ImmutableMapFacade(Map target, Function, Map> cloneFunction) {
        this.target = target;
        this.cloneFunction = cloneFunction;
    }

    @Override
    public ImmutableMapFacade clear() {
        if (isEmpty()) {
            return this;
        }
        Map clone = cloneFunction.apply(target);
        clone.clear();
        return new ImmutableMapFacade<>(clone, cloneFunction);
    }

    @Override
    public ImmutableMapFacade put(K key, @Nullable V value) {
        if (containsKey(key) && Objects.equals(get(key), value)) {
            return this;
        }
        Map clone = cloneFunction.apply(target);
        clone.put(key, value);
        return new ImmutableMapFacade<>(clone, cloneFunction);
    }


    @Override
    public ImmutableMapFacade putAll(Iterable> c) {
        Map clone = cloneFunction.apply(target);
        for (Map.Entry e : c) {
            clone.put(e.getKey(), e.getValue());
        }
        if (clone.equals(target)) {
            return this;
        }
        return new ImmutableMapFacade<>(clone, cloneFunction);
    }

    @Override
    public ImmutableMapFacade remove(K key) {
        if (!containsKey(key)) {
            return this;
        }
        Map clone = cloneFunction.apply(target);
        clone.remove(key);
        return new ImmutableMapFacade<>(clone, cloneFunction);
    }

    @SuppressWarnings("SuspiciousMethodCalls")
    @Override
    public ImmutableMapFacade removeAll(Iterable c) {
        if (isEmpty()) {
            return this;
        }
        Map clone = cloneFunction.apply(target);
        if (c instanceof Collection coll) {
            if (coll.isEmpty()) {
                return this;
            }
            clone.keySet().removeAll(coll);
        } else {
            boolean changed = false;
            for (K k : c) {
                changed |= clone.containsKey(k);
                clone.remove(k);
            }
            if (!changed) {
                return this;
            }
        }
        return new ImmutableMapFacade<>(clone, cloneFunction);
    }

    @SuppressWarnings("unchecked")
    @Override
    public ImmutableMapFacade retainAll(Iterable c) {
        if (isEmpty()) {
            return this;
        }
        Map clone = cloneFunction.apply(target);
        Collection collection;
        if (c instanceof ReadOnlyCollection rc) {
            collection = (Collection) rc.asCollection();
        } else if (c instanceof Collection cc) {
            collection = (Collection) cc;
        } else {
            collection = new HashSet<>();
            c.forEach(collection::add);
        }
        return clone.keySet().retainAll(collection) ? new ImmutableMapFacade<>(clone, cloneFunction) : this;
    }

    @Override
    public boolean isEmpty() {
        return target.isEmpty();
    }

    @Override
    public Iterator> iterator() {
        return Iterators.unmodifiableIterator(target.entrySet().iterator());
    }

    @Override
    public int maxSize() {
        return Integer.MAX_VALUE;
    }

    @Override
    public int size() {
        return target.size();
    }

    @SuppressWarnings("SuspiciousMethodCalls")
    @Override
    public @Nullable V get(Object key) {
        return target.get(key);
    }

    @SuppressWarnings("SuspiciousMethodCalls")
    @Override
    public boolean containsKey(@Nullable Object key) {
        return target.containsKey(key);
    }

    @Override
    public Map toMutable() {
        return cloneFunction.apply(target);
    }

    @Override
    public int characteristics() {
        return Spliterator.IMMUTABLE | super.characteristics();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy