Working on fp and di.

This commit is contained in:
JesseBrault0709 2024-05-13 16:42:57 +02:00
parent 59badf96f6
commit 4f0f3dfb33
17 changed files with 330 additions and 52 deletions

View File

@ -8,6 +8,7 @@ plugins {
dependencies { dependencies {
api libs.jakarta.inject api libs.jakarta.inject
api libs.groovy
compileOnlyApi libs.jetbrains.anotations compileOnlyApi libs.jetbrains.anotations
implementation libs.slf4j.api, libs.groovy implementation libs.slf4j.api, libs.groovy
} }

View File

@ -75,8 +75,8 @@ public abstract class AbstractRegistryObjectFactory extends AbstractInjectingObj
} }
@Override @Override
public void configureRegistry(Consumer<? super Registry> use) { public Registry getRegistry() {
use.accept(this.registry); return this.registry;
} }
@Override @Override

View File

@ -6,6 +6,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
public interface Registry extends ExtensionContainer, QualifierHandlerContainer, ScopeHandlerContainer { public interface Registry extends ExtensionContainer, QualifierHandlerContainer, ScopeHandlerContainer {
<T> void bind(Class<T> key, Consumer<? super BindingConfigurator<T>> configure); <T> void bind(Class<T> key, Consumer<? super BindingConfigurator<T>> configure);
@Nullable <T> Binding<T> getBinding(Class<T> key); @Nullable <T> Binding<T> getBinding(Class<T> key);
void removeBinding(Class<?> key); void removeBinding(Class<?> key);

View File

@ -1,5 +1,9 @@
package groowt.util.di; package groowt.util.di;
import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import groovy.transform.stc.ClosureParams;
import groovy.transform.stc.FromString;
import groowt.util.di.filters.FilterHandler; import groowt.util.di.filters.FilterHandler;
import groowt.util.di.filters.IterableFilterHandler; import groowt.util.di.filters.IterableFilterHandler;
import jakarta.inject.Provider; import jakarta.inject.Provider;
@ -22,7 +26,21 @@ public interface RegistryObjectFactory extends ObjectFactory {
T build(); T build();
} }
void configureRegistry(Consumer<? super Registry> use); Registry getRegistry();
default void configureRegistry(Consumer<? super Registry> use) {
use.accept(this.getRegistry());
}
default void configureRegistry(
@DelegatesTo(Registry.class)
@ClosureParams(value = FromString.class, options = "groowt.util.di.Registry")
Closure<?> configureClosure
) {
final Registry registry = this.getRegistry();
configureClosure.setDelegate(registry);
configureClosure.call(registry);
}
<A extends Annotation> @Nullable ScopeHandler<A> findScopeHandler(Class<A> scopeType); <A extends Annotation> @Nullable ScopeHandler<A> findScopeHandler(Class<A> scopeType);

View File

@ -9,6 +9,7 @@ repositories {
} }
dependencies { dependencies {
api libs.groovy
compileOnlyApi libs.jetbrains.anotations compileOnlyApi libs.jetbrains.anotations
} }

View File

@ -12,6 +12,14 @@ public final class Monoid<T> {
this.zero = Objects.requireNonNull(zero); this.zero = Objects.requireNonNull(zero);
} }
public SemiGroup<T> getSemiGroup() {
return this.semiGroup;
}
public Zero<T> getZero() {
return this.zero;
}
public T concat(T left, T right) { public T concat(T left, T right) {
return this.semiGroup.concat(left, right); return this.semiGroup.concat(left, right);
} }

View File

@ -0,0 +1,68 @@
package groowt.util.fp.property;
import groowt.util.fp.provider.DefaultListProvider;
import groowt.util.fp.provider.ListProvider;
import groowt.util.fp.provider.Provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
public class DefaultListProperty<T> implements ListProperty<T> {
private final List<Provider<T>> elementProviders = new ArrayList<>();
@Override
public void addElement(T element) {
this.elementProviders.add(Provider.of(element));
}
@SuppressWarnings("unchecked")
@Override
public void addProvider(Provider<? extends T> elementProvider) {
this.elementProviders.add((Provider<T>) elementProvider);
}
@Override
public void addAllElements(Collection<? extends T> elements) {
elements.forEach(this::addElement);
}
@Override
public void addAllProviders(Collection<? extends Provider<? extends T>> elementProviders) {
elementProviders.forEach(this::addProvider);
}
@Override
public <U> ListProvider<U> mapElements(Function<? super T, ? extends U> mapper) {
return new DefaultListProvider<>(
this.elementProviders.stream()
.<Provider<U>>map(elementProvider -> elementProvider.map(mapper))
.toList()
);
}
@Override
public <U> ListProvider<U> flatMapElements(Function<? super T, ? extends Provider<? extends U>> flatMapper) {
return new DefaultListProvider<>(
this.elementProviders.stream()
.map(elementProvider -> elementProvider.flatMap(flatMapper))
.toList()
);
}
@Override
public ListProvider<T> filterElements(Predicate<? super T> predicate) {
return new DefaultListProvider<>(this.elementProviders, List.of(predicate));
}
@Override
public List<T> get() {
return this.elementProviders.stream()
.map(Provider::get)
.toList();
}
}

View File

@ -0,0 +1,13 @@
package groowt.util.fp.property;
import groowt.util.fp.provider.ListProvider;
import groowt.util.fp.provider.Provider;
import java.util.Collection;
public interface ListProperty<T> extends ListProvider<T> {
void addElement(T element);
void addProvider(Provider<? extends T> elementProvider);
void addAllElements(Collection<? extends T> elements);
void addAllProviders(Collection<? extends Provider<? extends T>> elementProviders);
}

View File

@ -1,5 +1,9 @@
package groowt.util.fp.property; package groowt.util.fp.property;
import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import groovy.transform.stc.ClosureParams;
import groovy.transform.stc.FromString;
import groowt.util.fp.provider.Provider; import groowt.util.fp.provider.Provider;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -7,7 +11,7 @@ import java.util.function.Supplier;
public interface Property<T> extends Provider<T> { public interface Property<T> extends Provider<T> {
static <T> Property<T> get(Class<? extends T> tClass) { static <T> Property<T> empty() {
return new SimpleProperty<>(); return new SimpleProperty<>();
} }
@ -17,7 +21,7 @@ public interface Property<T> extends Provider<T> {
return property; return property;
} }
static <T> Property<T> ofLazy(Provider<T> tProvider) { static <T> Property<T> ofProvider(Provider<T> tProvider) {
final Property<T> property = new SimpleProperty<>(); final Property<T> property = new SimpleProperty<>();
property.set(tProvider); property.set(tProvider);
return property; return property;
@ -34,6 +38,12 @@ public interface Property<T> extends Provider<T> {
void setConvention(T t); void setConvention(T t);
void setConvention(Provider<? extends T> tProvider); void setConvention(Provider<? extends T> tProvider);
void configure(
@DelegatesTo(type = "T")
@ClosureParams(value = FromString.class, options = "T")
Closure<?> configureClosure
);
boolean isPresent(); boolean isPresent();
boolean isEmpty(); boolean isEmpty();

View File

@ -1,11 +1,16 @@
package groowt.util.fp.property; package groowt.util.fp.property;
import groovy.lang.Closure;
import groowt.util.fp.provider.Provider; import groowt.util.fp.provider.Provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
final class SimpleProperty<T> implements Property<T> { final class SimpleProperty<T> implements Property<T> {
private final List<Closure<?>> configureClosures = new ArrayList<>();
private Provider<? extends T> provider; private Provider<? extends T> provider;
private Provider<? extends T> convention; private Provider<? extends T> convention;
@ -44,14 +49,30 @@ final class SimpleProperty<T> implements Property<T> {
} }
@Override @Override
public T get() { public void configure(Closure<?> configureClosure) {
if (!this.isPresent()) { this.configureClosures.add(configureClosure);
throw new NullPointerException("Cannot get() from an empty Property. Set the value or set the convention."); }
} else if (this.provider != null) {
return this.provider.get(); private void doConfigures(T t) {
} else { for (final var configureClosure : this.configureClosures) {
return this.convention.get(); configureClosure.setDelegate(t);
configureClosure.call(t);
} }
} }
@Override
public T get() {
if (!this.isPresent()) {
throw new NullPointerException("Cannot get() from an empty Property. Set the value or set the convention.");
}
final T t;
if (this.provider != null) {
t = this.provider.get();
} else {
t = this.convention.get();
}
this.doConfigures(t);
return t;
}
} }

View File

@ -0,0 +1,68 @@
package groowt.util.fp.provider;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
public class DefaultListProvider<T> implements ListProvider<T> {
private final List<Provider<T>> elementProviders;
private final List<Predicate<? super T>> filters;
public DefaultListProvider(List<? extends Provider<T>> elementProviders) {
this.elementProviders = new ArrayList<>(elementProviders);
this.filters = List.of();
}
public DefaultListProvider(
List<? extends Provider<T>> elementProviders,
List<? extends Predicate<? super T>> filters
) {
this.elementProviders = new ArrayList<>(elementProviders);
this.filters = new ArrayList<>(filters);
}
private DefaultListProvider(DefaultListProvider<T> old, Predicate<? super T> filterToAdd) {
this.elementProviders = new ArrayList<>(old.elementProviders);
this.filters = new ArrayList<>(old.filters);
this.filters.add(filterToAdd);
}
@Override
public ListProvider<T> filterElements(Predicate<? super T> predicate) {
return new DefaultListProvider<>(this, predicate);
}
@Override
public <U> ListProvider<U> mapElements(Function<? super T, ? extends U> mapper) {
final List<Provider<U>> uProviders = this.elementProviders.stream()
.<Provider<U>>map(elementProvider -> elementProvider.map(mapper))
.toList();
return new DefaultListProvider<>(uProviders);
}
@Override
public <U> ListProvider<U> flatMapElements(Function<? super T, ? extends Provider<? extends U>> flatMapper) {
final List<Provider<U>> uProviders = this.elementProviders.stream()
.map(elementProvider -> elementProvider.flatMap(flatMapper))
.toList();
return new DefaultListProvider<>(uProviders);
}
@Override
public List<T> get() {
final List<? extends T> filtered = this.elementProviders.stream()
.map(Provider::get)
.filter(element -> {
for (final var filter : this.filters) {
if (!filter.test(element)) {
return false;
}
}
return true;
}).toList();
return new ArrayList<>(filtered);
}
}

View File

@ -0,0 +1,28 @@
package groowt.util.fp.provider;
public class DefaultNamedProvider<T> implements NamedProvider<T> {
private final String name;
private final Provider<T> delegate;
public DefaultNamedProvider(String name, T element) {
this.name = name;
this.delegate = Provider.of(element);
}
public DefaultNamedProvider(String name, Provider<T> delegate) {
this.name = name;
this.delegate = delegate;
}
@Override
public String getName() {
return this.name;
}
@Override
public T get() {
return this.delegate.get();
}
}

View File

@ -1,18 +0,0 @@
package groowt.util.fp.provider;
import java.util.function.Supplier;
final class LazyProvider<T> implements Provider<T> {
private final Supplier<? extends T> lazy;
public LazyProvider(Supplier<? extends T> supplier) {
this.lazy = supplier;
}
@Override
public T get() {
return this.lazy.get();
}
}

View File

@ -0,0 +1,18 @@
package groowt.util.fp.provider;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
public interface ListProvider<T> extends Provider<List<T>> {
<U> ListProvider<U> mapElements(Function<? super T, ? extends U> mapper);
<U> ListProvider<U> flatMapElements(Function<? super T, ? extends Provider<? extends U>> flatMapper);
ListProvider<T> filterElements(Predicate<? super T> predicate);
default <R extends T> ListProvider<R> filterElementsByType(Class<? extends R> type) {
return this.filterElements(type::isInstance).mapElements(type::cast);
}
}

View File

@ -0,0 +1,20 @@
package groowt.util.fp.provider;
import groowt.util.fp.hkt.SemiGroup;
public interface NamedProvider<T> extends Provider<T> {
String getName();
default NamedProvider<T> zipWithNames(
SemiGroup<T> tSemiGroup,
SemiGroup<String> nameSemiGroup,
NamedProvider<? extends T> other
) {
return new DefaultNamedProvider<>(
nameSemiGroup.concat(this.getName(), other.getName()),
Provider.ofLazy(() -> tSemiGroup.concat(this.get(), other.get()))
);
}
}

View File

@ -1,26 +1,65 @@
package groowt.util.fp.provider; package groowt.util.fp.provider;
import groowt.util.fp.hkt.SemiGroup;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
/**
* @implSpec Must throw {@link NullPointerException} if the contained value is {@code null}
* when either created or when retrieved.
*
* @param <T> The type of the value contained within.
*/
@FunctionalInterface
public interface Provider<T> { public interface Provider<T> {
static <T> Provider<T> of(T t) { static <T> Provider<T> of(T t) {
return new SimpleProvider<>(t); Objects.requireNonNull(t);
return () -> t;
} }
static <T> Provider<T> ofLazy(Supplier<? extends T> tSupplier) { static <T> Provider<T> ofLazy(Supplier<? extends T> tSupplier) {
return new LazyProvider<>(tSupplier); Objects.requireNonNull(tSupplier);
return () -> Objects.requireNonNull(tSupplier.get(), "This Provider is empty.");
} }
/**
* @implSpec Must throw {@link NullPointerException} if the value is null.
*
* @throws NullPointerException if the value contained within this Provider is null.
* @return The value.
*/
T get(); T get();
default Provider<T> filter(Predicate<? super T> filter) {
Objects.requireNonNull(filter);
return () -> {
final T t = this.get();
if (filter.test(t)) {
return t;
} else {
throw new NullPointerException("This Provider is empty.");
}
};
}
default <U> Provider<U> map(Function<? super T, ? extends U> mapper) { default <U> Provider<U> map(Function<? super T, ? extends U> mapper) {
return new LazyProvider<>(() -> mapper.apply(this.get())); Objects.requireNonNull(mapper);
return () -> mapper.apply(this.get());
} }
default <U> Provider<U> flatMap(Function<? super T, ? extends Provider<? extends U>> flatMapper) { default <U> Provider<U> flatMap(Function<? super T, ? extends Provider<? extends U>> flatMapper) {
return new LazyProvider<>(() -> flatMapper.apply(this.get()).get()); Objects.requireNonNull(flatMapper);
return () -> flatMapper.apply(this.get()).get();
}
default Provider<T> zip(SemiGroup<T> semiGroup, Provider<? extends T> other) {
Objects.requireNonNull(semiGroup);
Objects.requireNonNull(other);
return () -> semiGroup.concat(this.get(), other.get());
} }
} }

View File

@ -1,18 +0,0 @@
package groowt.util.fp.provider;
import java.util.Objects;
final class SimpleProvider<T> implements Provider<T> {
private final T t;
public SimpleProvider(T t) {
this.t = Objects.requireNonNull(t);
}
@Override
public T get() {
return t;
}
}