]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/register/StaticRegister.java
Improve static register framework
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / register / StaticRegister.java
1 package org.argeo.util.register;
2
3 import java.util.HashSet;
4 import java.util.IdentityHashMap;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.concurrent.CompletableFuture;
8 import java.util.concurrent.ExecutionException;
9 import java.util.concurrent.atomic.AtomicBoolean;
10 import java.util.function.Predicate;
11
12 /** A minimal component register. */
13 public class StaticRegister implements ComponentRegister {
14 private final static StaticRegister instance = new StaticRegister();
15
16 public static ComponentRegister getInstance() {
17 return instance;
18 }
19
20 private final AtomicBoolean started = new AtomicBoolean(false);
21 private final IdentityHashMap<Object, Component<?>> components = new IdentityHashMap<>();
22
23 @Override
24 public void accept(Component<?> component) {
25 registerComponent(component);
26 }
27
28 @SuppressWarnings({ "unchecked" })
29 @Override
30 public synchronized <T> Component<? extends T> find(Class<T> clss, Predicate<Map<String, Object>> filter) {
31 Set<Component<? extends T>> result = new HashSet<>();
32 instances: for (Object instance : components.keySet()) {
33 if (!clss.isAssignableFrom(instance.getClass()))
34 continue instances;
35 Component<? extends T> component = (Component<? extends T>) components.get(instance);
36
37 // TODO filter
38 if (component.isPublishedType(clss))
39 result.add(component);
40 }
41 if (result.isEmpty())
42 return null;
43 return result.iterator().next();
44
45 }
46
47 synchronized void registerComponent(Component<?> component) {
48 if (started.get()) // TODO make it really dynamic
49 throw new IllegalStateException("Already activated");
50 if (components.containsKey(component.getInstance()))
51 throw new IllegalArgumentException("Already registered as component");
52 components.put(component.getInstance(), component);
53 }
54
55 @Override
56 public synchronized Component<?> get(Object instance) {
57 if (!components.containsKey(instance))
58 throw new IllegalArgumentException("Not registered as component");
59 return components.get(instance);
60 }
61
62 @Override
63 public synchronized void activate() {
64 if (started.get())
65 throw new IllegalStateException("Already activated");
66 Set<CompletableFuture<?>> constraints = new HashSet<>();
67 for (Component<?> component : components.values()) {
68 component.startActivating();
69 constraints.add(component.getActivated());
70 }
71
72 // wait
73 try {
74 CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(true))
75 .get();
76 } catch (InterruptedException e) {
77 throw new RuntimeException("Register activation has been interrupted", e);
78 } catch (ExecutionException e) {
79 if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
80 throw (RuntimeException) e.getCause();
81 } else {
82 throw new IllegalStateException("Cannot activate register", e.getCause());
83 }
84 }
85 }
86
87 @Override
88 public synchronized void deactivate() {
89 if (!started.get())
90 throw new IllegalStateException("Not activated");
91 Set<CompletableFuture<?>> constraints = new HashSet<>();
92 for (Component<?> component : components.values()) {
93 component.startDeactivating();
94 constraints.add(component.getDeactivated());
95 }
96
97 // wait
98 try {
99 CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(false))
100 .get();
101 } catch (InterruptedException e) {
102 throw new RuntimeException("Register deactivation has been interrupted", e);
103 } catch (ExecutionException e) {
104 if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
105 throw (RuntimeException) e.getCause();
106 } else {
107 throw new IllegalStateException("Cannot deactivate register", e.getCause());
108 }
109 }
110 }
111
112 @Override
113 public synchronized boolean isActive() {
114 return started.get();
115 }
116
117 @Override
118 public synchronized void clear() {
119 components.clear();
120 }
121
122 }