Skip to content

Commit 308e9b6

Browse files
committed
First pass at CompositeBinding
1 parent dfc3e64 commit 308e9b6

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package rx.subscriptions;
2+
3+
import javafx.beans.binding.Binding;
4+
import rx.Subscription;
5+
import rx.exceptions.Exceptions;
6+
7+
import java.util.*;
8+
9+
10+
/**
11+
* A group of of Bindings that are disposed together.
12+
* <p>
13+
* All methods of this class are thread-safe.
14+
*/
15+
public final class CompositeBinding {
16+
17+
private Set<Binding> bindings;
18+
private boolean disposedInd;
19+
20+
public CompositeBinding() {}
21+
22+
public CompositeBinding(final Binding... bindings) {
23+
this.bindings = new HashSet<>(Arrays.asList(bindings));
24+
}
25+
26+
public void invalidate() {
27+
bindings.forEach(Binding::invalidate);
28+
}
29+
public boolean isDisposed() {
30+
return disposedInd;
31+
}
32+
33+
/**
34+
* Adds a new {@link Binding} to this {@code CompositeBinding} if the
35+
* {@code CompositeBinding} is not yet disposedInd. If the {@code CompositeBinding} <em>is</em>
36+
* disposed, {@code add} will indicate this by explicitly unsubscribing the new {@code Subscription} as
37+
* well.
38+
*
39+
* @param b the {@link Subscription} to add
40+
*/
41+
public void add(final Binding b) {
42+
if (!disposedInd) {
43+
if (bindings == null) {
44+
bindings = new HashSet<>(4);
45+
}
46+
bindings.add(b);
47+
return;
48+
}
49+
b.dispose();
50+
}
51+
52+
/**
53+
* Removes a {@link Binding} from this {@code CompositeBinding}, and disposes the
54+
* {@link Binding}.
55+
*
56+
* @param b the {@link Binding} to remove
57+
*/
58+
public void remove(final Binding b) {
59+
if (!disposedInd) {
60+
boolean unsubscribe = false;
61+
if (bindings == null) {
62+
return;
63+
}
64+
unsubscribe = bindings.remove(b);
65+
if (unsubscribe) {
66+
// if we removed successfully we then need to call dispose on it
67+
b.dispose();
68+
}
69+
}
70+
}
71+
72+
/**
73+
* Disposes any bindings that are currently part of this {@code CompositeBinding} and remove
74+
* them from the {@code CompositeBinding} so that the {@code CompositeBinding} is empty and
75+
* able to manage new bindings.
76+
*/
77+
public void clear() {
78+
if (!disposedInd) {
79+
Collection<Binding> unsubscribe = null;
80+
if (bindings == null) {
81+
return;
82+
} else {
83+
unsubscribe = bindings;
84+
bindings = null;
85+
}
86+
unsubscribeFromAll(unsubscribe);
87+
}
88+
}
89+
90+
91+
/**
92+
* Disposes itself and all inner Bindings.
93+
* <p>After call of this method, new {@code Binding}s added to {@link CompositeBinding}
94+
* will be disposed immediately.
95+
*/
96+
public void dispose() {
97+
if (!disposedInd) {
98+
Collection<Binding> unsubscribe = null;
99+
disposedInd = true;
100+
unsubscribe = bindings;
101+
bindings = null;
102+
// we will only get here once
103+
unsubscribeFromAll(unsubscribe);
104+
}
105+
}
106+
107+
private static void unsubscribeFromAll(Collection<Binding> bindings) {
108+
if (bindings == null) {
109+
return;
110+
}
111+
List<Throwable> es = null;
112+
for (Binding b : bindings) {
113+
try {
114+
b.dispose();
115+
} catch (Throwable e) {
116+
if (es == null) {
117+
es = new ArrayList<>();
118+
}
119+
es.add(e);
120+
}
121+
}
122+
Exceptions.throwIfAny(es);
123+
}
124+
125+
/**
126+
* Returns true if this composite is not disposed and contains Bindings.
127+
*
128+
* @return {@code true} if this composite is not disposed and contains Bindings.
129+
* @since 1.0.7
130+
*/
131+
public boolean hasSubscriptions() {
132+
if (!disposedInd) {
133+
return bindings != null && !bindings.isEmpty();
134+
}
135+
return false;
136+
}
137+
}
138+

0 commit comments

Comments
 (0)