Improve static register framework
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 20 May 2022 09:37:43 +0000 (11:37 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 20 May 2022 09:37:43 +0000 (11:37 +0200)
org.argeo.util/src/org/argeo/util/register/Component.java
org.argeo.util/src/org/argeo/util/register/ComponentRegister.java [new file with mode: 0644]
org.argeo.util/src/org/argeo/util/register/StaticRegister.java

index 4a812f83b04059bf4cdcf6888995ac9106b3018c..66ac2ada9233b9d9b121eb24b6d29648ef3e4869 100644 (file)
@@ -83,11 +83,11 @@ public class Component<I> {
                                .thenRun(() -> prepareNextActivation());
        }
 
-       public CompletableFuture<Void> getActivated() {
+       CompletableFuture<Void> getActivated() {
                return activated;
        }
 
-       public CompletableFuture<Void> getDeactivated() {
+       CompletableFuture<Void> getDeactivated() {
                return deactivated;
        }
 
@@ -130,48 +130,44 @@ public class Component<I> {
                dependants.add(dependant);
        }
 
-       I getInstance() {
+       public I getInstance() {
                return instance;
        }
 
        @SuppressWarnings("unchecked")
-       <T> PublishedType<T> getType(Class<T> clss) {
+       public <T> PublishedType<T> getType(Class<T> clss) {
                if (!types.containsKey(clss))
                        throw new IllegalArgumentException(clss.getName() + " is not a type published by this component");
                return (PublishedType<T>) types.get(clss);
        }
 
-       <T> boolean isPublishedType(Class<T> clss) {
+       public <T> boolean isPublishedType(Class<T> clss) {
                return types.containsKey(clss);
        }
 
+       /** A type which has been explicitly exposed by a component. */
        public static class PublishedType<T> {
                private Component<? extends T> component;
                private Class<T> clss;
 
-//             private CompletableFuture<Component<? extends T>> publisherAvailable;
                private CompletableFuture<T> value;
 
                public PublishedType(Component<? extends T> component, Class<T> 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<Component<? extends T>> publisherAvailable() {
-//                     return publisherAvailable;
-//             }
-
-               Class<T> getType() {
+               public Class<T> getType() {
                        return clss;
                }
        }
 
+       /** Builds a {@link Component}. */
        public static class Builder<I> {
                private final I instance;
 
@@ -211,14 +207,14 @@ public class Component<I> {
                        return this;
                }
 
-               public Builder<I> addInit(Runnable init) {
+               public Builder<I> addActivation(Runnable init) {
                        if (this.init != null)
                                throw new IllegalArgumentException("init method is already set");
                        this.init = init;
                        return this;
                }
 
-               public Builder<I> addClose(Runnable close) {
+               public Builder<I> 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<I> {
                public Dependency(PublishedType<D> types, Consumer<D> set, Consumer<D> 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 (file)
index 0000000..eb8acba
--- /dev/null
@@ -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<?>> {
+       <T> Component<? extends T> find(Class<T> clss, Predicate<Map<String, Object>> filter);
+
+       Component<?> get(Object instance);
+
+       void activate();
+
+       void deactivate();
+
+       boolean isActive();
+
+       void clear();
+}
index c186aff08fdf49714ccc38584e739160a14a75de..0dcba13f8bb7b2ec90ac37ff0695c1fb97ff8102 100644 (file)
@@ -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<Object, Component<?>> components = new IdentityHashMap<>();
+public class StaticRegister implements ComponentRegister {
+       private final static StaticRegister instance = new StaticRegister();
 
-       public static Consumer<Component<?>> asConsumer() {
-               return (c) -> registerComponent(c);
+       public static ComponentRegister getInstance() {
+               return instance;
        }
 
-//     public static BiFunction<Class<?>, Predicate<Map<String, Object>>, Component<?>> asProvider() {
-//
-//     }
+       private final AtomicBoolean started = new AtomicBoolean(false);
+       private final IdentityHashMap<Object, Component<?>> components = new IdentityHashMap<>();
 
-       static synchronized <T> Component<? extends T> find(Class<T> clss, Predicate<Map<String, Object>> filter) {
+       @Override
+       public void accept(Component<?> component) {
+               registerComponent(component);
+       }
+
+       @SuppressWarnings({ "unchecked" })
+       @Override
+       public synchronized <T> Component<? extends T> find(Class<T> clss, Predicate<Map<String, Object>> filter) {
                Set<Component<? extends T>> 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<CompletableFuture<?>> 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<CompletableFuture<?>> 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();
        }