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

org.wildfly.service.Dependency Maven / Gradle / Ivy

There is a newer version: 27.0.0.Final
Show newest version
/*
 * Copyright The WildFly Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.wildfly.service;

import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.wildfly.common.function.Functions;

/**
 * Encapsulates logic for registering a value providing dependency with a service builder.
 * @author Paul Ferraro
 */
public interface Dependency, V> extends Consumer, Supplier {

    @Override
    default Dependency andThen(Consumer after) {
        Objects.requireNonNull(after);
        return new Dependency<>() {
            @Override
            public void accept(B builder) {
                Dependency.this.accept(builder);
                after.accept(builder);
            }

            @Override
            public V get() {
                return Dependency.this.get();
            }
        };
    }

    /**
     * Returns a dependency whose value is the result of applying the specified mapping function.
     * @param  the mapped value type
     * @param mapper a mapping function
     * @return a dependency whose value is the result of applying the specified mapping function.
     * @throws NullPointerException if {@code mapper} was null
     */
    default  Dependency map(Function mapper) {
        Objects.requireNonNull(mapper);
        return new Dependency<>() {
            @Override
            public void accept(B builder) {
                Dependency.this.accept(builder);
            }

            @Override
            public R get() {
                return mapper.apply(Dependency.this.get());
            }
        };
    }

    /**
     * Returns a dependency that combines this dependency with the specified dependency, whose value is determined by the specified mapping function.
     * @param  the other dependency type
     * @param  the mapped value type
     * @param dependency another dependency
     * @param mapper a mapping function
     * @return a dependency that combines this dependency with the specified dependency, whose value is determined by the specified mapping function.
     * @throws NullPointerException if {@code dependency} or {@code mapper} were null.
     */
    default  Dependency combine(Dependency dependency, BiFunction mapper) {
        Objects.requireNonNull(dependency);
        Objects.requireNonNull(mapper);
        return new Dependency<>() {
            @Override
            public void accept(B builder) {
                Dependency.this.accept(builder);
                dependency.accept(builder);
            }

            @Override
            public R get() {
                return mapper.apply(Dependency.this.get(), dependency.get());
            }
        };
    }

    /**
     * Indicates whether this dependency will never provide a value.
     * @return true, if this dependency will not provide a value, false otherwise.
     */
    default boolean isEmpty() {
        return false;
    }

    /**
     * Indicates whether this dependency will provide a value.
     * This method is the direct inverse of {@link #isEmpty()}.
     * @return true, if this dependency will provide a value, false otherwise.
     */
    default boolean isPresent() {
        return !this.isEmpty();
    }

    class SimpleDependency, V> implements Dependency {

        private final V value;

        protected SimpleDependency(V value) {
            this.value = value;
        }

        @Override
        public V get() {
            return this.value;
        }

        @Override
        public boolean isEmpty() {
            return this.value == null;
        }

        @Override
        public void accept(B builder) {
            // Nothing to register
        }
    }

    class SuppliedDependency, V> implements Dependency {

        private final Supplier supplier;

        protected SuppliedDependency(Supplier supplier) {
            this.supplier = supplier;
        }

        @Override
        public V get() {
            return this.supplier.get();
        }

        @Override
        public void accept(B builder) {
            // Nothing to register
        }
    }

    abstract class AbstractDependency, V> implements Dependency, Function> {

        private volatile Supplier supplier = Functions.constantSupplier(null);

        @Override
        public V get() {
            return this.supplier.get();
        }

        @Override
        public void accept(B builder) {
            this.supplier = this.apply(builder);
        }
    }

    class DefaultDependency, V> extends AbstractDependency {

        private final ServiceName name;

        protected DefaultDependency(ServiceName name) {
            this.name = name;
        }

        @Override
        public Supplier apply(B builder) {
            return builder.requires(this.name);
        }

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

        @Override
        public boolean equals(Object object) {
            if (!(object instanceof DefaultDependency)) return false;
            return this.name.equals(((DefaultDependency) object).name);
        }

        @Override
        public String toString() {
            return this.name.toString();
        }
    }
}