diff options
Diffstat (limited to 'subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java')
-rw-r--r-- | subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java new file mode 100644 index 00000000..906b9e30 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java | |||
@@ -0,0 +1,89 @@ | |||
1 | package tools.refinery.language.web.xtext.server.push; | ||
2 | |||
3 | import java.util.ArrayList; | ||
4 | import java.util.HashMap; | ||
5 | import java.util.List; | ||
6 | import java.util.Map; | ||
7 | |||
8 | import org.eclipse.xtext.util.CancelIndicator; | ||
9 | import org.eclipse.xtext.web.server.IServiceResult; | ||
10 | import org.eclipse.xtext.web.server.model.AbstractCachedService; | ||
11 | import org.eclipse.xtext.web.server.model.DocumentSynchronizer; | ||
12 | import org.eclipse.xtext.web.server.model.XtextWebDocument; | ||
13 | import org.slf4j.Logger; | ||
14 | import org.slf4j.LoggerFactory; | ||
15 | |||
16 | import com.google.common.collect.ImmutableList; | ||
17 | |||
18 | import tools.refinery.language.web.xtext.server.ResponseHandlerException; | ||
19 | |||
20 | public class PushWebDocument extends XtextWebDocument { | ||
21 | private static final Logger LOG = LoggerFactory.getLogger(PushWebDocument.class); | ||
22 | |||
23 | private final List<PrecomputationListener> precomputationListeners = new ArrayList<>(); | ||
24 | |||
25 | private final Map<Class<?>, IServiceResult> precomputedServices = new HashMap<>(); | ||
26 | |||
27 | public PushWebDocument(String resourceId, DocumentSynchronizer synchronizer) { | ||
28 | super(resourceId, synchronizer); | ||
29 | if (resourceId == null) { | ||
30 | throw new IllegalArgumentException("resourceId must not be null"); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | public boolean addPrecomputationListener(PrecomputationListener listener) { | ||
35 | synchronized (precomputationListeners) { | ||
36 | if (precomputationListeners.contains(listener)) { | ||
37 | return false; | ||
38 | } | ||
39 | precomputationListeners.add(listener); | ||
40 | listener.onSubscribeToPrecomputationEvents(getResourceId(), this); | ||
41 | return true; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | public boolean removePrecomputationListener(PrecomputationListener listener) { | ||
46 | synchronized (precomputationListeners) { | ||
47 | return precomputationListeners.remove(listener); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | public <T extends IServiceResult> void precomputeServiceResult(AbstractCachedService<T> service, String serviceName, | ||
52 | CancelIndicator cancelIndicator, boolean logCacheMiss) { | ||
53 | var result = getCachedServiceResult(service, cancelIndicator, logCacheMiss); | ||
54 | if (result == null) { | ||
55 | LOG.error("{} service returned null result", serviceName); | ||
56 | return; | ||
57 | } | ||
58 | var serviceClass = service.getClass(); | ||
59 | var previousResult = precomputedServices.get(serviceClass); | ||
60 | if (previousResult != null && previousResult.equals(result)) { | ||
61 | return; | ||
62 | } | ||
63 | precomputedServices.put(serviceClass, result); | ||
64 | notifyPrecomputationListeners(serviceName, result); | ||
65 | } | ||
66 | |||
67 | private <T extends IServiceResult> void notifyPrecomputationListeners(String serviceName, T result) { | ||
68 | var resourceId = getResourceId(); | ||
69 | var stateId = getStateId(); | ||
70 | List<PrecomputationListener> copyOfListeners; | ||
71 | synchronized (precomputationListeners) { | ||
72 | copyOfListeners = ImmutableList.copyOf(precomputationListeners); | ||
73 | } | ||
74 | var toRemove = new ArrayList<PrecomputationListener>(); | ||
75 | for (var listener : copyOfListeners) { | ||
76 | try { | ||
77 | listener.onPrecomputedServiceResult(resourceId, stateId, serviceName, result); | ||
78 | } catch (ResponseHandlerException e) { | ||
79 | LOG.error("Delivering precomputation push message failed", e); | ||
80 | toRemove.add(listener); | ||
81 | } | ||
82 | } | ||
83 | if (!toRemove.isEmpty()) { | ||
84 | synchronized (precomputationListeners) { | ||
85 | precomputationListeners.removeAll(toRemove); | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||