Start making the component system more dynamic
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 4 Jan 2022 06:42:06 +0000 (07:42 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 4 Jan 2022 06:42:06 +0000 (07:42 +0100)
org.argeo.enterprise/src/org/argeo/util/register/Component.java
org.argeo.enterprise/src/org/argeo/util/register/StaticRegister.java

index dccb77d38dbefdfb44bad2f6373350be69e7899a..4a812f83b04059bf4cdcf6888995ac9106b3018c 100644 (file)
@@ -29,8 +29,8 @@ public class Component<I> {
 
        private Set<Dependency<?>> dependants = new HashSet<>();
 
-       Component(I instance, Runnable init, Runnable close, Set<Dependency<?>> dependencies,
-                       Set<Class<? super I>> classes) {
+       Component(Consumer<Component<?>> register, I instance, Runnable init, Runnable close,
+                       Set<Dependency<?>> dependencies, Set<Class<? super I>> classes) {
                assert instance != null;
                assert init != null;
                assert close != null;
@@ -44,9 +44,9 @@ public class Component<I> {
                // types
                Map<Class<? super I>, PublishedType<? super I>> types = new HashMap<>(classes.size());
                for (Class<? super I> clss : classes) {
-                       if (!clss.isAssignableFrom(instance.getClass()))
-                               throw new IllegalArgumentException(
-                                               "Type " + clss.getName() + " is not compatible with " + instance.getClass().getName());
+//                     if (!clss.isAssignableFrom(instance.getClass()))
+//                             throw new IllegalArgumentException(
+//                                             "Type " + clss.getName() + " is not compatible with " + instance.getClass().getName());
                        types.put(clss, new PublishedType<>(this, clss));
                }
                this.types = Collections.unmodifiableMap(types);
@@ -64,7 +64,7 @@ public class Component<I> {
                // TODO check whether context is active, so that we start right away
                prepareNextActivation();
 
-               StaticRegister.registerComponent(this);
+               register.accept(this);
        }
 
        private void prepareNextActivation() {
@@ -106,7 +106,7 @@ public class Component<I> {
        CompletableFuture<Void> dependenciesActivated(Void v) {
                Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependencies.size());
                for (Dependency<?> dependency : this.dependencies) {
-                       CompletableFuture<Void> dependencyActivated = dependency.getPublisher().activated //
+                       CompletableFuture<Void> dependencyActivated = dependency.publisherActivated() //
                                        .thenCompose(dependency::set);
                        constraints.add(dependencyActivated);
                }
@@ -116,7 +116,7 @@ public class Component<I> {
        CompletableFuture<Void> dependantsDeactivated(Void v) {
                Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependants.size());
                for (Dependency<?> dependant : this.dependants) {
-                       CompletableFuture<Void> dependantDeactivated = dependant.getDependantComponent().deactivated //
+                       CompletableFuture<Void> dependantDeactivated = dependant.dependantDeactivated() //
                                        .thenCompose(dependant::unset);
                        constraints.add(dependantDeactivated);
                }
@@ -141,22 +141,32 @@ public class Component<I> {
                return (PublishedType<T>) types.get(clss);
        }
 
+       <T> boolean isPublishedType(Class<T> clss) {
+               return types.containsKey(clss);
+       }
+
        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() {
                        return component;
                }
 
+//             CompletableFuture<Component<? extends T>> publisherAvailable() {
+//                     return publisherAvailable;
+//             }
+
                Class<T> getType() {
                        return clss;
                }
@@ -175,7 +185,7 @@ public class Component<I> {
                        this.instance = instance;
                }
 
-               public Component<I> build() {
+               public Component<I> build(Consumer<Component<?>> register) {
                        // default values
                        if (types.isEmpty()) {
                                types.add(getInstanceClass());
@@ -189,7 +199,7 @@ public class Component<I> {
                                };
 
                        // instantiation
-                       Component<I> component = new Component<I>(instance, init, close, dependencies, types);
+                       Component<I> component = new Component<I>(register, instance, init, close, dependencies, types);
                        for (Dependency<?> dependency : dependencies) {
                                dependency.type.getPublisher().addDependant(dependency);
                        }
@@ -253,12 +263,12 @@ public class Component<I> {
                        this.dependantComponent = component;
                }
 
-               Component<?> getPublisher() {
-                       return type.getPublisher();
+               CompletableFuture<Void> publisherActivated() {
+                       return type.getPublisher().activated.copy();
                }
 
-               Component<?> getDependantComponent() {
-                       return dependantComponent;
+               CompletableFuture<Void> dependantDeactivated() {
+                       return dependantComponent.deactivated.copy();
                }
 
                CompletableFuture<Void> set(Void v) {
index 0c55bddb2dda02eab787fc822aec1345d7835102..c186aff08fdf49714ccc38584e739160a14a75de 100644 (file)
@@ -2,16 +2,44 @@ package org.argeo.util.register;
 
 import java.util.HashSet;
 import java.util.IdentityHashMap;
+import java.util.Map;
 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 static Consumer<Component<?>> asConsumer() {
+               return (c) -> registerComponent(c);
+       }
+
+//     public static BiFunction<Class<?>, Predicate<Map<String, Object>>, Component<?>> asProvider() {
+//
+//     }
+
+       static 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()))
+                               continue instances;
+                       Component<? extends T> component = (Component<? extends T>) components.get(instance);
+
+                       // TODO filter
+                       if (component.isPublishedType(clss))
+                               result.add(component);
+               }
+               if (result.isEmpty())
+                       return null;
+               return result.iterator().next();
+
+       }
+
        static synchronized void registerComponent(Component<?> component) {
                if (started.get()) // TODO make it really dynamic
                        throw new IllegalStateException("Already activated");
@@ -62,4 +90,8 @@ public class StaticRegister {
                }
        }
 
+       synchronized static void clear() {
+               components.clear();
+       }
+
 }