X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.util%2Fsrc%2Forg%2Fargeo%2Futil%2Fregister%2FComponent.java;h=275811e9db66510cbb77cdf4be350ec33115d70c;hb=3c1cdc594d954520b14646102b366290bdad58c7;hp=4a812f83b04059bf4cdcf6888995ac9106b3018c;hpb=9f729eeb8255a9d800ad2506735dda8cc215a135;p=lgpl%2Fargeo-commons.git 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..275811e9d 100644 --- a/org.argeo.util/src/org/argeo/util/register/Component.java +++ b/org.argeo.util/src/org/argeo/util/register/Component.java @@ -1,17 +1,21 @@ package org.argeo.util.register; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.function.Consumer; +import java.util.function.Supplier; /** * A wrapper for an object, whose dependencies and life cycle can be managed. */ -public class Component { +public class Component implements Supplier, Comparable> { private final I instance; @@ -20,6 +24,7 @@ public class Component { private final Map, PublishedType> types; private final Set> dependencies; + private final Map properties; private CompletableFuture activationStarted = null; private CompletableFuture activated = null; @@ -27,10 +32,13 @@ public class Component { private CompletableFuture deactivationStarted = null; private CompletableFuture deactivated = null; + // internal private Set> dependants = new HashSet<>(); - Component(Consumer> register, I instance, Runnable init, Runnable close, - Set> dependencies, Set> classes) { + private RankingKey rankingKey; + + Component(ComponentRegister register, I instance, Runnable init, Runnable close, Set> dependencies, + Set> classes, Map properties) { assert instance != null; assert init != null; assert close != null; @@ -64,7 +72,11 @@ public class Component { // TODO check whether context is active, so that we start right away prepareNextActivation(); - register.accept(this); + long serviceId = register.register(this); + Map props = new HashMap<>(properties); + props.put(RankingKey.SERVICE_ID, serviceId); + this.properties = Collections.unmodifiableMap(props); + rankingKey = new RankingKey(properties); } private void prepareNextActivation() { @@ -83,11 +95,11 @@ public class Component { .thenRun(() -> prepareNextActivation()); } - public CompletableFuture getActivated() { + CompletableFuture getActivated() { return activated; } - public CompletableFuture getDeactivated() { + CompletableFuture getDeactivated() { return deactivated; } @@ -130,49 +142,77 @@ public class Component { dependants.add(dependant); } - I getInstance() { + @Override + public I get() { 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); } + public Map getProperties() { + return properties; + } + + @Override + public int compareTo(Component o) { + return rankingKey.compareTo(rankingKey); + } + + @Override + public int hashCode() { + Long serviceId = (Long) properties.get(RankingKey.SERVICE_ID); + if (serviceId != null) + return serviceId.intValue(); + else + return super.hashCode(); + } + + @Override + public String toString() { + List classes = new ArrayList<>(); + for (Class clss : types.keySet()) { + classes.add(clss.getName()); + } + return "Component " + classes + " " + properties + ""; + } + + /** 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; } + + public CompletionStage getValue() { + return value.minimalCompletionStage(); + } } - public static class Builder { + /** Builds a {@link Component}. */ + public static class Builder implements Supplier { private final I instance; private Runnable init; @@ -180,12 +220,13 @@ public class Component { private Set> dependencies = new HashSet<>(); private Set> types = new HashSet<>(); + private final Map properties = new HashMap<>(); public Builder(I instance) { this.instance = instance; } - public Component build(Consumer> register) { + public Component build(ComponentRegister register) { // default values if (types.isEmpty()) { types.add(getInstanceClass()); @@ -199,7 +240,7 @@ public class Component { }; // instantiation - Component component = new Component(register, instance, init, close, dependencies, types); + Component component = new Component(register, instance, init, close, dependencies, types, properties); for (Dependency dependency : dependencies) { dependency.type.getPublisher().addDependant(dependency); } @@ -211,14 +252,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; @@ -230,6 +271,13 @@ public class Component { return this; } + public void addProperty(String key, Object value) { + if (properties.containsKey(key)) + throw new IllegalStateException("Key " + key + " is already set."); + properties.put(key, value); + } + + @Override public I get() { return instance; } @@ -254,8 +302,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