From 7974745f1de448353bf47012b5df36b451dce2fa Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 20 May 2022 11:37:43 +0200 Subject: [PATCH] Improve static register framework --- .../org/argeo/util/register/Component.java | 32 +++++----- .../util/register/ComponentRegister.java | 19 ++++++ .../argeo/util/register/StaticRegister.java | 63 +++++++++++++------ 3 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 org.argeo.util/src/org/argeo/util/register/ComponentRegister.java diff --git a/org.argeo.util/src/org/argeo/util/register/Component.java b/org.argeo.util/src/org/argeo/util/register/Component.java index 4a812f83b..66ac2ada9 100644 --- a/org.argeo.util/src/org/argeo/util/register/Component.java +++ b/org.argeo.util/src/org/argeo/util/register/Component.java @@ -83,11 +83,11 @@ public class Component { .thenRun(() -> prepareNextActivation()); } - public CompletableFuture getActivated() { + CompletableFuture getActivated() { return activated; } - public CompletableFuture getDeactivated() { + CompletableFuture getDeactivated() { return deactivated; } @@ -130,48 +130,44 @@ public class Component { dependants.add(dependant); } - I getInstance() { + public I getInstance() { return instance; } @SuppressWarnings("unchecked") - PublishedType getType(Class clss) { + public PublishedType getType(Class clss) { if (!types.containsKey(clss)) throw new IllegalArgumentException(clss.getName() + " is not a type published by this component"); return (PublishedType) types.get(clss); } - boolean isPublishedType(Class clss) { + public boolean isPublishedType(Class clss) { return types.containsKey(clss); } + /** A type which has been explicitly exposed by a component. */ public static class PublishedType { private Component component; private Class clss; -// private CompletableFuture> publisherAvailable; private CompletableFuture value; public PublishedType(Component component, Class clss) { this.clss = clss; this.component = component; value = CompletableFuture.completedFuture((T) component.instance); -// value = publisherAvailable.thenApply((c) -> c.getInstance()); } - Component getPublisher() { + public Component getPublisher() { return component; } -// CompletableFuture> publisherAvailable() { -// return publisherAvailable; -// } - - Class getType() { + public Class getType() { return clss; } } + /** Builds a {@link Component}. */ public static class Builder { private final I instance; @@ -211,14 +207,14 @@ public class Component { return this; } - public Builder addInit(Runnable init) { + public Builder addActivation(Runnable init) { if (this.init != null) throw new IllegalArgumentException("init method is already set"); this.init = init; return this; } - public Builder addClose(Runnable close) { + public Builder addDeactivation(Runnable close) { if (this.close != null) throw new IllegalArgumentException("close method is already set"); this.close = close; @@ -254,8 +250,10 @@ public class Component { public Dependency(PublishedType types, Consumer set, Consumer unset) { super(); this.type = types; - this.set = set; - this.unset = unset != null ? unset : (v) -> set.accept(null); + this.set = set != null ? set : t -> { + }; + this.unset = unset != null ? unset : t -> { + }; } // live diff --git a/org.argeo.util/src/org/argeo/util/register/ComponentRegister.java b/org.argeo.util/src/org/argeo/util/register/ComponentRegister.java new file mode 100644 index 000000000..eb8acba02 --- /dev/null +++ b/org.argeo.util/src/org/argeo/util/register/ComponentRegister.java @@ -0,0 +1,19 @@ +package org.argeo.util.register; + +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public interface ComponentRegister extends Consumer> { + Component find(Class clss, Predicate> filter); + + Component get(Object instance); + + void activate(); + + void deactivate(); + + boolean isActive(); + + void clear(); +} diff --git a/org.argeo.util/src/org/argeo/util/register/StaticRegister.java b/org.argeo.util/src/org/argeo/util/register/StaticRegister.java index c186aff08..0dcba13f8 100644 --- a/org.argeo.util/src/org/argeo/util/register/StaticRegister.java +++ b/org.argeo.util/src/org/argeo/util/register/StaticRegister.java @@ -7,23 +7,27 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; import java.util.function.Predicate; /** A minimal component register. */ -public class StaticRegister { - private final static AtomicBoolean started = new AtomicBoolean(false); - private final static IdentityHashMap> components = new IdentityHashMap<>(); +public class StaticRegister implements ComponentRegister { + private final static StaticRegister instance = new StaticRegister(); - public static Consumer> asConsumer() { - return (c) -> registerComponent(c); + public static ComponentRegister getInstance() { + return instance; } -// public static BiFunction, Predicate>, Component> asProvider() { -// -// } + private final AtomicBoolean started = new AtomicBoolean(false); + private final IdentityHashMap> components = new IdentityHashMap<>(); - static synchronized Component find(Class clss, Predicate> filter) { + @Override + public void accept(Component component) { + registerComponent(component); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public synchronized Component find(Class clss, Predicate> filter) { Set> result = new HashSet<>(); instances: for (Object instance : components.keySet()) { if (!clss.isAssignableFrom(instance.getClass())) @@ -40,7 +44,7 @@ public class StaticRegister { } - static synchronized void registerComponent(Component component) { + synchronized void registerComponent(Component component) { if (started.get()) // TODO make it really dynamic throw new IllegalStateException("Already activated"); if (components.containsKey(component.getInstance())) @@ -48,13 +52,15 @@ public class StaticRegister { components.put(component.getInstance(), component); } - static synchronized Component get(Object instance) { + @Override + public synchronized Component get(Object instance) { if (!components.containsKey(instance)) throw new IllegalArgumentException("Not registered as component"); return components.get(instance); } - synchronized static void activate() { + @Override + public synchronized void activate() { if (started.get()) throw new IllegalStateException("Already activated"); Set> constraints = new HashSet<>(); @@ -67,12 +73,19 @@ public class StaticRegister { try { CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(true)) .get(); - } catch (ExecutionException | InterruptedException e) { - throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException("Register activation has been interrupted", e); + } catch (ExecutionException e) { + if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) { + throw (RuntimeException) e.getCause(); + } else { + throw new IllegalStateException("Cannot activate register", e.getCause()); + } } } - synchronized static void deactivate() { + @Override + public synchronized void deactivate() { if (!started.get()) throw new IllegalStateException("Not activated"); Set> constraints = new HashSet<>(); @@ -85,12 +98,24 @@ public class StaticRegister { try { CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(false)) .get(); - } catch (ExecutionException | InterruptedException e) { - throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException("Register deactivation has been interrupted", e); + } catch (ExecutionException e) { + if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) { + throw (RuntimeException) e.getCause(); + } else { + throw new IllegalStateException("Cannot deactivate register", e.getCause()); + } } } - synchronized static void clear() { + @Override + public synchronized boolean isActive() { + return started.get(); + } + + @Override + public synchronized void clear() { components.clear(); } -- 2.30.2