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

org.apache.isis.commons.collections.Can_Singleton Maven / Gradle / Ivy

Go to download

Apache Isis Commons is a library with utilities, that are shared with the entire Apache Isis ecosystem.

There is a newer version: 2.0.0-M9
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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.apache.isis.commons.collections;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.springframework.lang.Nullable;

import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._Objects;
import org.apache.isis.commons.internal.exceptions._Exceptions;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;

@RequiredArgsConstructor(staticName="of")
final class Can_Singleton implements Can {

    private static final long serialVersionUID = 1L;

    private final T element;

    @Override
    public Optional getSingleton() {
        return Optional.of(element);
    }

    @Override
    public Cardinality getCardinality() {
        return Cardinality.ONE;
    }

    @Override
    public Stream stream() {
        return Stream.of(element);
    }

    @Override
    public Stream parallelStream() {
        return Stream.of(element);
    }

    @Override
    public Optional getFirst() {
        return getSingleton();
    }

    @Override
    public Optional getLast() {
        return getSingleton();
    }

    @Override
    public Optional get(final int elementIndex) {
        return getSingleton();
    }

    @Override
    public int size() {
        return 1;
    }

    @Override
    public boolean contains(final @Nullable T element) {
        return Objects.equals(this.element, element);
    }

    @Override
    public Iterator iterator() {
        return Collections.singletonList(element).iterator();
    }

    @Override
    public Can unique() {
        return this;
    }

    @Override
    public Can reverse() {
        return this;
    }

    @Override
    public Iterator reverseIterator() {
        return iterator();
    }

    @Override
    public void forEach(final @NonNull Consumer action) {
        action.accept(this.element);
    }

    @Override
    public Can filter(final @Nullable Predicate predicate) {
        if(predicate==null) {
            return this; // identity
        }
        return predicate.test(element)
                ? this // identity
                : Can.empty();
    }

    @Override
    public  void zip(final Iterable zippedIn, final BiConsumer action) {
        action.accept(element, zippedIn.iterator().next());
    }

    @Override
    public  Can zipMap(final Iterable zippedIn, final BiFunction mapper) {
        return Can_Singleton.of(mapper.apply(element, zippedIn.iterator().next()));
    }

    @Override
    public Can add(final @Nullable T element) {
        return element!=null
                ? Can.ofStream(Stream.of(this.element, element)) // append
                : this;
    }

    @Override
    public Can addAll(final @Nullable Can other) {
        if(other==null
                || other.isEmpty()) {
            return this;
        }
        if(other.isCardinalityOne()) {
            return add(other.getSingleton().orElseThrow(_Exceptions::unexpectedCodeReach));
        }
        val newElements = new ArrayList(other.size()+1);
        newElements.add(element);
        other.forEach(newElements::add);
        return Can_Multiple.of(newElements);
    }

    @Override
    public Can add(final int index, final @Nullable T element) {
        if(element==null) {
            return this; // no-op
        }
        if(index==0) {
            return Can.ofStream(Stream.of(element, this.element)); // insert before
        }
        if(index==1) {
            return Can.ofStream(Stream.of(this.element, element)); // append
        }
        throw new IndexOutOfBoundsException(
                "cannot add to singleton with index other than 0 or 1; got " + index);
    }

    @Override
    public Can replace(final int index, final @Nullable T element) {
        if(index!=0) {
            throw new IndexOutOfBoundsException(
                "cannot replace on singleton with index other than 0; got " + index);
        }
        return element!=null
                ? Can.ofSingleton(element)
                : Can.empty();
    }

    @Override
    public Can remove(final int index) {
        if(index==0) {
            return Can.empty();
        }
        throw new IndexOutOfBoundsException(
                "cannot remove from singleton with index other than 0; got " + index);
    }

    @Override
    public Can remove(final @Nullable T element) {
        if(this.element.equals(element)) {
            return Can.empty();
        }
        return this;
    }

    @Override
    public Can pickByIndex(final @Nullable int... indices) {
        if(indices==null
                ||indices.length==0) {
            return Can.empty();
        }
        int pickCount = 0; // actual size of the returned Can
        for(int index:indices) {
            if(index==0) {
                ++pickCount;
            }
        }
        if(pickCount==0) {
            return Can.empty();
        }
        if(pickCount==1) {
            return this;
        }
        val newElements = new ArrayList(pickCount);
        for(int i=0; i) obj).isEqualTo(this);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return element.hashCode();
    }

    @Override
    public int compareTo(final @Nullable Can other) {
        // when returning
        // -1 ... this (singleton) is before other
        // +1 ... this (singleton) is after other
        if(other==null
                || other.isEmpty()) {
            return 1; // all empty Cans are same and come first
        }
        final int firstElementComparison = _Objects.compareNonNull(
                this.element,
                other.getFirstOrFail());
        if(firstElementComparison!=0
                || other.isCardinalityOne()) {
            return firstElementComparison; // when both Cans are singletons, just compare by their contained values
        }
        // at this point firstElementComparison is 0 and other is of cardinality MULTIPLE
        return -1; // singletons come before multi-cans
    }

    @Override
    public List toList() {
        return Collections.singletonList(element); // serializable and immutable
    }

    @Override
    public Set toSet() {
        return Collections.singleton(element); // serializable and immutable
    }

    @Override
    public Set toSet(final @NonNull Consumer onDuplicated) {
        return Collections.singleton(element); // serializable and immutable
    }

    @Override
    public > C toCollection(final @NonNull Supplier collectionFactory) {
        val collection = collectionFactory.get();
        collection.add(element);
        return collection;
    }

    @Override
    public T[] toArray(final @NonNull Class elementType) {
        val array = _Casts.uncheckedCast(Array.newInstance(elementType, 1));
        array[0] = element;
        return array;
    }




}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy