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

panda.std.reactive.Reference Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2021 dzikoysk
 *
 * 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 panda.std.reactive;

import org.jetbrains.annotations.NotNull;
import panda.std.Option;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class Reference implements Publisher, V> {

    protected final Collection> subscribers = new ArrayList<>();
    protected V value;

    public Reference(V value) {
        set(value);
    }

    void set(V newValue) {
        if (newValue == null) {
            throw new IllegalArgumentException("Reference does not support null values");
        }

        V oldValue = value;
        this.value = newValue;
        notifySubscribers(oldValue, newValue);
    }


    protected void notifySubscribers(V oldValue, V newValue) {
        subscribers.forEach(subscriber -> subscriber.onComplete(oldValue, newValue));
    }

    @Override
    public Reference subscribe(Subscriber subscriber) {
        return subscribeDetailed((oldValue, newValue) -> subscriber.onComplete(newValue), false);
    }

    public Reference subscribe(Subscriber subscriber, boolean immediately) {
        return subscribeDetailed((oldValue, newValue) -> subscriber.onComplete(newValue), immediately);
    }

    public Reference subscribeDetailed(DetailedSubscriber subscriber) {
        return subscribeDetailed(subscriber, false);
    }

    public Reference subscribeDetailed(DetailedSubscriber subscriber, boolean immediately) {
        if (immediately) {
            subscriber.onComplete(get(), get());
        }
        subscribers.add(subscriber);
        return this;
    }

    public V get() {
        return value;
    }

    public  R map(Function function) {
        return function.apply(get());
    }

    public Reference peek(Consumer consumer) {
        consumer.accept(get());
        return this;
    }

    public  Reference computed(Function recalculateFunction) {
        Reference computed = new Reference<>(recalculateFunction.apply(get()));
        subscribe(value -> computed.set(recalculateFunction.apply(value)));
        return computed;
    }

    public Option toOption() {
        return Option.of(get());
    }

    @SuppressWarnings("unchecked")
    public Class getType() {
        return (Class) value.getClass();
    }

    public static  @NotNull Reference reference(T value) {
        return new Reference<>(value);
    }

    public static class Dependencies {

        final List> references;

        Dependencies(List> references) {
            this.references = references;
        }

        public  @NotNull Reference computed(Supplier recalculateFunction) {
            Reference computed = reference(recalculateFunction.get());
            references.forEach(reference -> reference.subscribe(newValue -> computed.set(recalculateFunction.get())));
            return computed;
        }

        public static Dependencies dependencies(List> references) {
            return new Dependencies(references);
        }

        public static Dependencies dependencies(Reference... references) {
             return new Dependencies(Arrays.asList(references));
        }

    }

    public static  @NotNull Reference computed(Dependencies dependencies, Supplier recalculateFunction) {
        return dependencies.computed(recalculateFunction);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy