1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.venn.model;
25
26 import java.util.HashSet;
27 import java.util.Set;
28
29 import java.util.HashMap;
30 import java.util.Map;
31
32 import com.google.common.collect.Sets;
33
34 import org.dishevelled.bitset.ImmutableBitSet;
35
36 import org.dishevelled.observable.ObservableSet;
37
38 import org.dishevelled.observable.impl.ObservableSetImpl;
39
40 import org.dishevelled.venn.BinaryVennModel;
41
42 import static org.dishevelled.venn.model.VennModelUtils.toImmutableBitSet;
43
44
45
46
47
48
49
50
51 public final class BinaryVennModelImpl<E>
52 implements BinaryVennModel<E>
53 {
54
55 private final ObservableSet<E> first;
56
57
58 private final ObservableSet<E> second;
59
60
61 private final Set<E> firstOnly;
62
63
64 private final Set<E> secondOnly;
65
66
67 private final Set<E> intersection;
68
69
70 private final Set<E> union;
71
72
73 private final ObservableSet<E> selection;
74
75
76 private final Map<ImmutableBitSet, Set<E>> exclusives;
77
78
79
80
81
82 public BinaryVennModelImpl()
83 {
84 this(new HashSet<E>(), new HashSet<E>());
85 }
86
87
88
89
90
91
92
93 public BinaryVennModelImpl(final Set<? extends E> first, final Set<? extends E> second)
94 {
95 if (first == null)
96 {
97 throw new IllegalArgumentException("first must not be null");
98 }
99 if (second == null)
100 {
101 throw new IllegalArgumentException("second must not be null");
102 }
103
104
105 this.first = new ObservableSetImpl(first);
106 this.second = new ObservableSetImpl(second);
107 firstOnly = Sets.difference(this.first, this.second);
108 secondOnly = Sets.difference(this.second, this.first);
109 intersection = Sets.intersection(this.first, this.second);
110 union = Sets.union(this.first, this.second);
111 selection = new SelectionView<E>(union, this.first, this.second);
112
113 exclusives = new HashMap<ImmutableBitSet, Set<E>>(3);
114
115 exclusives.put(toImmutableBitSet(0), firstOnly);
116 exclusives.put(toImmutableBitSet(1), secondOnly);
117
118 exclusives.put(toImmutableBitSet(0, 1), intersection);
119
120 }
121
122
123
124 public int size()
125 {
126 return 2;
127 }
128
129
130 public ObservableSet<E> first()
131 {
132 return first;
133 }
134
135
136 public ObservableSet<E> second()
137 {
138 return second;
139 }
140
141
142 public Set<E> get(final int index)
143 {
144 if (index < 0 || index > 1)
145 {
146 throw new IndexOutOfBoundsException("index out of bounds");
147 }
148 switch (index)
149 {
150 case 0:
151 return first;
152 case 1:
153 return second;
154 default:
155 break;
156 }
157 throw new IllegalStateException("invalid index " + index);
158 }
159
160
161 public Set<E> firstOnly()
162 {
163 return firstOnly;
164 }
165
166
167 public Set<E> secondOnly()
168 {
169 return secondOnly;
170 }
171
172
173 public Set<E> intersection()
174 {
175 return intersection;
176 }
177
178
179 public Set<E> exclusiveTo(final int index, final int... additional)
180 {
181 int maxIndex = size() - 1;
182 if (index < 0 || index > maxIndex)
183 {
184 throw new IndexOutOfBoundsException("index out of bounds");
185 }
186 if (additional != null && additional.length > 0)
187 {
188 if (additional.length > maxIndex)
189 {
190 throw new IndexOutOfBoundsException("too many indices provided");
191 }
192 for (int i = 0, size = additional.length; i < size; i++)
193 {
194 if (additional[i] < 0 || additional[i] > maxIndex)
195 {
196 throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
197 }
198 }
199 }
200 return exclusives.get(toImmutableBitSet(index, additional));
201 }
202
203
204 public Set<E> union()
205 {
206 return union;
207 }
208
209
210 public ObservableSet<E> selection()
211 {
212 return selection;
213 }
214 }