1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ch.elca.el4j.util.observer.impl;
18
19
20 import java.util.LinkedList;
21 import java.util.List;
22
23 import ch.elca.el4j.util.codingsupport.Reject;
24 import ch.elca.el4j.util.codingsupport.annotations.ImplementationAssumption;
25 import ch.elca.el4j.util.observer.InquisitiveValueObserver;
26 import ch.elca.el4j.util.observer.ObservableValue;
27 import ch.elca.el4j.util.observer.ValueObserver;
28
29
30
31
32
33
34
35
36
37
38
39 public abstract class AbstractObservableValue<T> implements ObservableValue<T> {
40
41 private static class ValueHolder<T> {
42
43 private T m_value;
44 }
45
46
47
48 private ValueHolder<T> m_holder = null;
49
50
51 private List<ValueObserver<? super T>> m_obs
52 = new LinkedList<ValueObserver<? super T>>();
53
54
55
56
57 protected AbstractObservableValue() { }
58
59
60
61
62 public AbstractObservableValue(T initialReference) {
63 set(initialReference);
64 }
65
66
67
68
69 public void subscribeSilently(ValueObserver<? super T> o) {
70 Reject.ifNull(o);
71 m_obs.add(o);
72 }
73
74
75
76
77 public void subscribe(ValueObserver<? super T> o) {
78 subscribeSilently(o);
79 if (m_holder != null) {
80 o.changed(m_holder.m_value);
81 }
82 }
83
84
85
86
87 public void unsubscribe(ValueObserver<? super T> o) {
88 m_obs.remove(o);
89 }
90
91
92 @ImplementationAssumption(
93 "An observer processing a notification never unsubscribes "
94 + "(directly or indirectly) a yet-to-be-notified observer.")
95 private void announce() {
96 List<ValueObserver<? super T>> observersSnapshot
97 = new LinkedList<ValueObserver<? super T>>(m_obs);
98 for (ValueObserver<? super T> o : observersSnapshot) {
99 o.changed(m_holder.m_value);
100 }
101 for (ValueObserver<? super T> o : observersSnapshot) {
102 if (o instanceof InquisitiveValueObserver<?>) {
103 InquisitiveValueObserver<? super T> ivo
104 = (InquisitiveValueObserver<? super T>) o;
105
106
107 ivo.notified();
108 }
109 }
110 }
111
112
113 protected void set(T newValue) {
114 if (m_holder != null) {
115 if (equal(m_holder.m_value, newValue)) { return; }
116 } else {
117 m_holder = new ValueHolder<T>();
118 }
119 m_holder.m_value = newValue;
120 announce();
121 }
122
123
124
125
126 public T get() throws IllegalStateException {
127 LiveValue.observableGetterInterceptor(this);
128 if (m_holder == null) {
129 throw new IllegalStateException(
130 "reference does not exist yet."
131 );
132 }
133 return m_holder.m_value;
134 }
135
136
137
138
139 protected boolean equal(T a, T b) {
140 if (a == null) {
141 return b == null;
142 } else {
143 return a.equals(b);
144 }
145 }
146 }