1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.framework.ioc;
35
36
37 import info.magnolia.event.EventBus;
38
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Optional;
44 import java.util.stream.Stream;
45
46 import com.google.common.collect.HashMultimap;
47 import com.google.common.collect.Multimap;
48 import com.google.inject.Key;
49 import com.vaadin.server.VaadinSession;
50
51
52
53
54
55
56
57
58 public class SessionStore {
59
60
61
62
63 public static SessionStore access() {
64 return access(VaadinSession.getCurrent());
65 }
66
67
68
69
70 public static SessionStore access(VaadinSession session) {
71 return session.getAttribute(SessionStore.class);
72 }
73
74 private final VaadinSession vaadinSession;
75
76 private final EventBus eventBus;
77
78 private final Multimap<UiContextReference, UiContextReference> beanStoreHierarchy = HashMultimap.create();
79 private final Map<UiContextReference, UiContextReference> beanStoreParentReferences = new HashMap<>();
80
81 public SessionStore(VaadinSession vaadinSession, EventBus eventBus) {
82 this.vaadinSession = vaadinSession;
83 this.eventBus = eventBus;
84 }
85
86 public BeanStore createBeanStore(UiContextReference uiContextReference) {
87 BeanStore existingBeanStore = getBeanStore(uiContextReference);
88 if (existingBeanStore != null) {
89 return existingBeanStore;
90 }
91 return createBeanStore(uiContextReference, Collections.emptyMap());
92 }
93
94 public BeanStore createBeanStore(UiContextReference key, Map<Key, Object> initialInstances) {
95
96 final BeanStoreBeanStore.html#BeanStore">BeanStore beanStore = new BeanStore();
97 vaadinSession.setAttribute(key.asString(), beanStore);
98 key.getDirectParentReference().ifPresent(parentRef -> {
99 beanStoreHierarchy.put(parentRef, key);
100 beanStoreParentReferences.put(key, parentRef);
101 });
102 initialInstances.forEach(beanStore::put);
103
104 eventBus.fireEvent(new BeanStoreLifecycleEvent.Create(key, beanStore));
105
106 return beanStore;
107 }
108
109
110
111
112
113 public BeanStore getBeanStore(UiContextReference uiContextReference) {
114 return (BeanStore) vaadinSession.getAttribute(uiContextReference.asString());
115 }
116
117 public Optional<UiContextReference> lookupRelatedUiContextReference(Object instance) {
118 return beanStoreHierarchy.values().stream()
119 .filter(ref ->
120 Optional.ofNullable(this.getBeanStore(ref))
121 .map(beanStore -> beanStore.contains(instance))
122 .orElse(false))
123 .findFirst();
124 }
125
126
127
128
129 public void releaseBeanStore(UiContextReference uiContextReference) {
130 final BeanStore store = getBeanStore(uiContextReference);
131
132 if (store == null) {
133 throw new IllegalArgumentException(String.format("No bean store registered for provided uiContextReference [%s]...", uiContextReference));
134 }
135
136 eventBus.fireEvent(new BeanStoreLifecycleEvent.BeforeDestroy(uiContextReference, store));
137
138
139 this.beanStoreHierarchy.removeAll(uiContextReference).forEach(this::releaseBeanStore);
140 Optional.ofNullable(this.beanStoreParentReferences.remove(uiContextReference))
141 .ifPresent(parentReference -> this.beanStoreHierarchy.remove(parentReference, uiContextReference));
142
143 store.clear();
144 vaadinSession.setAttribute(uiContextReference.asString(), null);
145
146 eventBus.fireEvent(new BeanStoreLifecycleEvent.Destroy(uiContextReference, store));
147 }
148
149 public static <T> Stream<T> lookUpInstancesOf(UiContextReference uiContextReference, Class<T> clazz) {
150 BeanStore beanStore = SessionStore.access().getBeanStore(uiContextReference);
151 return Stream.concat(
152 Stream.of(beanStore.getClosestInstance(clazz)),
153 uiContextReference.getParentReferences().stream()
154 .map(parentRef -> SessionStore.access().getBeanStore(parentRef))
155 .filter(Objects::nonNull)
156 .map(parentStore -> parentStore.getClosestInstance(clazz)))
157 .filter(Objects::nonNull);
158 }
159 }