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