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

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

The newest version!
/*
 * @(#)SequencedMapFacade.java
 * Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
 */

package org.jhotdraw8.icollection.facade;

import org.jhotdraw8.icollection.impl.iteration.MappedIterator;
import org.jhotdraw8.icollection.impl.iteration.MappedSpliterator;
import org.jhotdraw8.icollection.readonly.ReadOnlySequencedMap;
import org.jspecify.annotations.Nullable;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.SequencedCollection;
import java.util.SequencedMap;
import java.util.SequencedSet;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.IntSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Provides a {@link SequencedMap} facade to a set of {@code Map} functions.
 *
 * @param  the key type
 * @param  the value type
 * @author Werner Randelshofer
 */
public class SequencedMapFacade extends MapFacade implements SequencedMap {
    private final Supplier> firstEntryFunction;
    private final Supplier> lastEntryFunction;
    private final BiFunction putFirstFunction;
    private final BiFunction putLastFunction;
    private final Supplier>> reverseIteratorFunction;
    private final Supplier>> reverseSpliteratorFunction;

    public SequencedMapFacade(ReadOnlySequencedMap m) {
        super(m);
        this.firstEntryFunction = m::firstEntry;
        this.lastEntryFunction = m::lastEntry;
        this.putFirstFunction = (k, v) -> {
            throw new UnsupportedOperationException();
        };
        this.putLastFunction = (k, v) -> {
            throw new UnsupportedOperationException();
        };
        this.reverseIteratorFunction = () -> m.readOnlyReversed().iterator();
        this.reverseSpliteratorFunction = () -> m.readOnlyReversed().spliterator();
    }

    public SequencedMapFacade(SequencedMap m) {
        super(m);
        this.firstEntryFunction = m::firstEntry;
        this.lastEntryFunction = m::lastEntry;
        this.putFirstFunction = m::putFirst;
        this.putLastFunction = m::putLast;
        this.reverseIteratorFunction = () -> m.reversed().sequencedEntrySet().iterator();
        this.reverseSpliteratorFunction = () -> m.reversed().sequencedEntrySet().spliterator();
    }

    public SequencedMapFacade(
            Supplier>> iteratorFunction,
            Supplier>> reverseIteratorFunction,
            IntSupplier sizeFunction,
            Predicate containsKeyFunction,
            Function getFunction,
            @Nullable Runnable clearFunction,
            @Nullable Function removeFunction,
            Supplier> firstEntryFunction,
            Supplier> lastEntryFunction,
            @Nullable BiFunction putFunction,
            @Nullable BiFunction putFirstFunction,
            @Nullable BiFunction putLastFunction) {
        this(iteratorFunction,
                () -> Spliterators.spliterator(iteratorFunction.get(), sizeFunction.getAsInt(), Spliterator.DISTINCT),
                reverseIteratorFunction,
                () -> Spliterators.spliterator(reverseIteratorFunction.get(), sizeFunction.getAsInt(), Spliterator.DISTINCT),
                sizeFunction, containsKeyFunction,
                getFunction, clearFunction, removeFunction, firstEntryFunction, lastEntryFunction,
                putFunction, putFirstFunction, putLastFunction);
    }

    public SequencedMapFacade(
            Supplier>> iteratorFunction,
            Supplier>> spliteratorFunction,
            Supplier>> reverseIteratorFunction,
            Supplier>> reverseSpliteratorFunction,
            IntSupplier sizeFunction,
            Predicate containsKeyFunction,
            Function getFunction,
            @Nullable Runnable clearFunction,
            @Nullable Function removeFunction,
            Supplier> firstEntryFunction,
            Supplier> lastEntryFunction,
            @Nullable BiFunction putFunction,
            @Nullable BiFunction putFirstFunction,
            @Nullable BiFunction putLastFunction) {
        super(iteratorFunction, spliteratorFunction, sizeFunction, containsKeyFunction, getFunction, clearFunction,
                removeFunction, putFunction);
        this.firstEntryFunction = firstEntryFunction;
        this.lastEntryFunction = lastEntryFunction;
        this.putFirstFunction = putFirstFunction == null ? (k, v) -> {
            throw new UnsupportedOperationException();
        } : putFirstFunction;
        this.putLastFunction = putLastFunction == null ? (k, v) -> {
            throw new UnsupportedOperationException();
        } : putLastFunction;
        this.reverseIteratorFunction = reverseIteratorFunction;
        this.reverseSpliteratorFunction = reverseSpliteratorFunction;
    }

    @SuppressWarnings({"SuspiciousMethodCalls"})
    public static  SequencedSet createKeySet(SequencedMap m) {
        return new SequencedSetFacade<>(
                () -> new MappedIterator<>(m.sequencedEntrySet().iterator(), Entry::getKey),
                () -> new MappedSpliterator<>(m.sequencedEntrySet().spliterator(), Entry::getKey,
                        Spliterator.DISTINCT | Spliterator.SIZED | Spliterator.ORDERED, null),
                () -> new MappedIterator<>(m.reversed().sequencedEntrySet().iterator(), Entry::getKey),
                () -> new MappedSpliterator<>(m.reversed().sequencedEntrySet().spliterator(), Entry::getKey,
                        Spliterator.DISTINCT | Spliterator.SIZED | Spliterator.ORDERED, null),
                m::size,
                m::containsKey,
                m::clear,
                o -> {
                    if (m.containsKey(o)) {
                        m.remove(o);
                        return true;
                    }
                    return false;
                },
                () -> {
                    Entry e = m.firstEntry();
                    if (e == null) {
                        throw new NoSuchElementException();
                    }
                    return e.getKey();
                },
                () -> {
                    Entry e = m.lastEntry();
                    if (e == null) {
                        throw new NoSuchElementException();
                    }
                    return e.getKey();
                },
                null, null, null, null);
    }

    public static  SequencedCollection createValues(SequencedMap m) {
        return new SequencedCollectionFacade<>(
                () -> new MappedIterator<>(m.sequencedEntrySet().iterator(), Entry::getValue),
                () -> new MappedIterator<>(m.reversed().sequencedEntrySet().iterator(), Entry::getValue),
                m::size,
                m::containsValue,
                m::clear,
                (o) -> {
                    for (Entry entry : m.sequencedEntrySet()) {
                        if (Objects.equals(entry.getValue(), o)) {
                            m.remove(entry.getKey());
                            return true;
                        }
                    }
                    return false;
                },
                () -> {
                    Entry entry = m.firstEntry();
                    if (entry == null) {
                        throw new NoSuchElementException();
                    }
                    return entry.getValue();
                },
                () -> {
                    Entry entry = m.lastEntry();
                    if (entry == null) {
                        throw new NoSuchElementException();
                    }
                    return entry.getValue();
                },
                null, null,
                null);
    }

    @Override
    public SequencedSet> sequencedEntrySet() {
        return new SequencedSetFacade<>(
                iteratorFunction, spliteratorFunction,
                reverseIteratorFunction, reverseSpliteratorFunction,
                sizeFunction,
                this::containsEntry,
                clearFunction,
                this::removeEntry,
                firstEntryFunction,
                lastEntryFunction, null, null, null, null);
    }

    @Override
    public Entry firstEntry() {
        return firstEntryFunction.get();
    }

    @Override
    public SequencedSet sequencedKeySet() {
        return new SequencedSetFacade<>(
                () -> new MappedIterator<>(iteratorFunction.get(), Map.Entry::getKey),
                () -> new MappedSpliterator<>(spliteratorFunction.get(), Map.Entry::getKey, Spliterator.DISTINCT | Spliterator.SIZED, null),
                () -> new MappedIterator<>(reverseIteratorFunction.get(), Map.Entry::getKey),
                () -> new MappedSpliterator<>(spliteratorFunction.get(), Map.Entry::getKey, Spliterator.DISTINCT | Spliterator.SIZED, null),
                sizeFunction,
                this::containsKey,
                clearFunction,
                this::removeEntry,
                () -> {
                    Entry e = lastEntryFunction.get();
                    if (e == null) {
                        throw new NoSuchElementException();
                    }
                    return e.getKey();
                },
                () -> {
                    Entry e = firstEntryFunction.get();
                    if (e == null) {
                        throw new NoSuchElementException();
                    }
                    return e.getKey();
                },
                null, null, null, null);
    }

    @Override
    public Entry lastEntry() {
        return lastEntryFunction.get();
    }

    @Override
    public @Nullable V putFirst(K k, V v) {
        return putFirstFunction.apply(k, v);
    }

    @Override
    public @Nullable V putLast(K k, V v) {
        return putLastFunction.apply(k, v);
    }

    @Override
    public SequencedMap reversed() {
        return new SequencedMapFacade<>(
                reverseIteratorFunction,
                iteratorFunction,
                sizeFunction,
                containsKeyFunction,
                getFunction,
                clearFunction,
                removeFunction,
                lastEntryFunction,
                firstEntryFunction,
                putFunction,
                putLastFunction,
                putFirstFunction
        );
    }

    @Override
    public SequencedCollection sequencedValues() {
        return new SequencedCollectionFacade<>(
                () -> new MappedIterator<>(iteratorFunction.get(), Map.Entry::getValue),
                () -> new MappedIterator<>(reverseIteratorFunction.get(), Map.Entry::getValue),
                sizeFunction,
                this::containsKey,
                clearFunction,
                this::removeEntry,
                () -> {
                    Entry entry = firstEntry();
                    if (entry == null) {
                        throw new NoSuchElementException();
                    }
                    return entry.getValue();
                },
                () -> {
                    Entry entry = lastEntry();
                    if (entry == null) {
                        throw new NoSuchElementException();
                    }
                    return entry.getValue();
                }, null, null,
                null);
    }
}