View Javadoc

1   /*
2   
3       dsh-venn  Lightweight components for venn diagrams.
4       Copyright (c) 2009-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
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.QuaternaryVennModel;
41  
42  import static org.dishevelled.venn.model.VennModelUtils.toImmutableBitSet;
43  
44  /**
45   * Immutable implementation of QuaternaryVennModel.
46   *
47   * @param <E> value type
48   * @author  Michael Heuer
49   * @version $Revision$ $Date$
50   */
51  public final class QuaternaryVennModelImpl<E>
52      implements QuaternaryVennModel<E>
53  {
54      /** First view. */
55      private final ObservableSet<E> first;
56  
57      /** Second view. */
58      private final ObservableSet<E> second;
59  
60      /** Third view. */
61      private final ObservableSet<E> third;
62  
63      /** Fourth view. */
64      private final ObservableSet<E> fourth;
65  
66      /** First only view. */
67      private final Set<E> firstOnly;
68  
69      /** Second only view. */
70      private final Set<E> secondOnly;
71  
72      /** Third only view. */
73      private final Set<E> thirdOnly;
74  
75      /** Fourth only view. */
76      private final Set<E> fourthOnly;
77  
78      /** First second view. */
79      private final Set<E> firstSecond;
80  
81      /** First third view. */
82      private final Set<E> firstThird;
83  
84      /** First fourth view. */
85      private final Set<E> firstFourth;
86  
87      /** Second third view. */
88      private final Set<E> secondThird;
89  
90      /** Second fourth view. */
91      private final Set<E> secondFourth;
92  
93      /** Third fourth view. */
94      private final Set<E> thirdFourth;
95  
96      /** First second third view. */
97      private final Set<E> firstSecondThird;
98  
99      /** First second fourth view. */
100     private final Set<E> firstSecondFourth;
101 
102     /** First third fourth view. */
103     private final Set<E> firstThirdFourth;
104 
105     /** Second third fourth view. */
106     private final Set<E> secondThirdFourth;
107 
108     /** Intersection view. */
109     private final Set<E> intersection;
110 
111     /** Union view. */
112     private final Set<E> union;
113 
114     /** Selection view. */
115     private final ObservableSet<E> selection;
116 
117     /** Map of exclusive set views keyed by bit set. */
118     private final Map<ImmutableBitSet, Set<E>> exclusives;
119 
120 
121     /**
122      * Create a new empty quaternary venn model.
123      */
124     public QuaternaryVennModelImpl()
125     {
126         this(new HashSet<E>(), new HashSet<E>(), new HashSet<E>(), new HashSet<E>());
127     }
128 
129     /**
130      * Create a new quaternary venn model with the specified sets.
131      *
132      * @param first first set, must not be null
133      * @param second second set, must not be null
134      * @param third third set, must not be null
135      * @param fourth fourth set, must not be null
136      */
137     public QuaternaryVennModelImpl(final Set<? extends E> first,
138                                     final Set<? extends E> second,
139                                     final Set<? extends E> third,
140                                     final Set<? extends E> fourth)
141     {
142         if (first == null)
143         {
144             throw new IllegalArgumentException("first must not be null");
145         }
146         if (second == null)
147         {
148             throw new IllegalArgumentException("second must not be null");
149         }
150         if (third == null)
151         {
152             throw new IllegalArgumentException("third must not be null");
153         }
154         if (fourth == null)
155         {
156             throw new IllegalArgumentException("fourth must not be null");
157         }
158 
159         // todo  defensive copy?
160         this.first = new ObservableSetImpl(first);
161         this.second = new ObservableSetImpl(second);
162         this.third = new ObservableSetImpl(third);
163         this.fourth = new ObservableSetImpl(fourth);
164 
165         // alias
166         ObservableSet<E> f = this.first;
167         ObservableSet<E> s = this.second;
168         ObservableSet<E> t = this.third;
169         ObservableSet<E> r = this.fourth;
170         firstOnly = Sets.difference(Sets.difference(Sets.difference(f, s), t), r); // f - s - t - r
171         secondOnly = Sets.difference(Sets.difference(Sets.difference(s, f), t), r); // s - f - t - r
172         thirdOnly = Sets.difference(Sets.difference(Sets.difference(t, f), s), r); // t - f - s - r
173         fourthOnly = Sets.difference(Sets.difference(Sets.difference(r, f), s), t); // r - f - s - t
174         firstSecond = Sets.difference(Sets.difference(Sets.intersection(f, s), t), r); // f n s - t - r
175         firstThird = Sets.difference(Sets.difference(Sets.intersection(f, t), s), r); // f n t - s - r
176         firstFourth = Sets.difference(Sets.difference(Sets.intersection(f, r), s), t); // f n r - s - t
177         secondThird = Sets.difference(Sets.difference(Sets.intersection(s, t), f), r); // s n t - f - r
178         secondFourth = Sets.difference(Sets.difference(Sets.intersection(s, r), f), t); // s n r - f - t
179         thirdFourth = Sets.difference(Sets.difference(Sets.intersection(t, r), f), s); // t n r - f - s
180         firstSecondThird = Sets.difference(Sets.intersection(f, Sets.intersection(s, t)), r); // f n s n t - r
181         firstSecondFourth = Sets.difference(Sets.intersection(f, Sets.intersection(s, r)), t); // f n s n r - t
182         firstThirdFourth = Sets.difference(Sets.intersection(f, Sets.intersection(t, r)), s); // f n t n r - s
183         secondThirdFourth = Sets.difference(Sets.intersection(s, Sets.intersection(t, r)), f); // s n t n r - f
184         intersection = Sets.intersection(f, Sets.intersection(s, Sets.intersection(t, r))); // f n s n t n r
185         union = Sets.union(f, Sets.union(s, Sets.union(t, r))); // f u s u t u r
186         selection = new SelectionView<E>(union, f, s, t, r);
187 
188         exclusives = new HashMap<ImmutableBitSet, Set<E>>(15);
189 
190         exclusives.put(toImmutableBitSet(0), firstOnly);
191         exclusives.put(toImmutableBitSet(1), secondOnly);
192         exclusives.put(toImmutableBitSet(2), thirdOnly);
193         exclusives.put(toImmutableBitSet(3), fourthOnly);
194 
195         exclusives.put(toImmutableBitSet(0, 1), firstSecond);
196         exclusives.put(toImmutableBitSet(0, 2), firstThird);
197         exclusives.put(toImmutableBitSet(0, 3), firstFourth);
198         exclusives.put(toImmutableBitSet(1, 2), secondThird);
199         exclusives.put(toImmutableBitSet(1, 3), secondFourth);
200         exclusives.put(toImmutableBitSet(2, 3), thirdFourth);
201 
202         exclusives.put(toImmutableBitSet(0, 1, 2), firstSecondThird);
203         exclusives.put(toImmutableBitSet(0, 1, 3), firstSecondFourth);
204         exclusives.put(toImmutableBitSet(0, 2, 3), firstThirdFourth);
205         exclusives.put(toImmutableBitSet(1, 2, 3), secondThirdFourth);
206 
207         exclusives.put(toImmutableBitSet(0, 1, 2, 3), intersection);
208     }
209 
210 
211     /** {@inheritDoc} */
212     public int size()
213     {
214         return 4;
215     }
216 
217     /** {@inheritDoc} */
218     public ObservableSet<E> first()
219     {
220         return first;
221     }
222 
223     /** {@inheritDoc} */
224     public ObservableSet<E> second()
225     {
226         return second;
227     }
228 
229     /** {@inheritDoc} */
230     public ObservableSet<E> third()
231     {
232         return third;
233     }
234 
235     /** {@inheritDoc} */
236     public ObservableSet<E> fourth()
237     {
238         return fourth;
239     }
240 
241     /** {@inheritDoc} */
242     public Set<E> get(final int index)
243     {
244         if (index < 0 || index > 3)
245         {
246             throw new IndexOutOfBoundsException("index out of bounds");
247         }
248         switch (index)
249         {
250         case 0:
251             return first;
252         case 1:
253             return second;
254         case 2:
255             return third;
256         case 3:
257             return fourth;
258         default:
259             break;
260         }
261         throw new IllegalStateException("invalid index " + index);
262     }
263 
264     /** {@inheritDoc} */
265     public Set<E> firstOnly()
266     {
267         return firstOnly;
268     }
269 
270     /** {@inheritDoc} */
271     public Set<E> secondOnly()
272     {
273         return secondOnly;
274     }
275 
276     /** {@inheritDoc} */
277     public Set<E> thirdOnly()
278     {
279         return thirdOnly;
280     }
281 
282     /** {@inheritDoc} */
283     public Set<E> fourthOnly()
284     {
285         return fourthOnly;
286     }
287 
288     /** {@inheritDoc} */
289     public Set<E> firstSecond()
290     {
291         return firstSecond;
292     }
293 
294     /** {@inheritDoc} */
295     public Set<E> firstThird()
296     {
297         return firstThird;
298     }
299 
300     /** {@inheritDoc} */
301     public Set<E> firstFourth()
302     {
303         return firstFourth;
304     }
305 
306     /** {@inheritDoc} */
307     public Set<E> secondThird()
308     {
309         return secondThird;
310     }
311 
312     /** {@inheritDoc} */
313     public Set<E> secondFourth()
314     {
315         return secondFourth;
316     }
317 
318     /** {@inheritDoc} */
319     public Set<E> thirdFourth()
320     {
321         return thirdFourth;
322     }
323 
324     /** {@inheritDoc} */
325     public Set<E> firstSecondThird()
326     {
327         return firstSecondThird;
328     }
329 
330     /** {@inheritDoc} */
331     public Set<E> firstSecondFourth()
332     {
333         return firstSecondFourth;
334     }
335 
336     /** {@inheritDoc} */
337     public Set<E> firstThirdFourth()
338     {
339         return firstThirdFourth;
340     }
341 
342     /** {@inheritDoc} */
343     public Set<E> secondThirdFourth()
344     {
345         return secondThirdFourth;
346     }
347 
348     /** {@inheritDoc} */
349     public Set<E> intersection()
350     {
351         return intersection;
352     }
353 
354     /** {@inheritDoc} */
355     public Set<E> exclusiveTo(final int index, final int... additional)
356     {
357         int maxIndex = size() - 1;
358         if (index < 0 || index > maxIndex)
359         {
360             throw new IndexOutOfBoundsException("index out of bounds");
361         }
362         if (additional != null && additional.length > 0)
363         {
364             if (additional.length > maxIndex)
365             {
366                 throw new IndexOutOfBoundsException("too many indices provided");
367             }
368             for (int i = 0, size = additional.length; i < size; i++)
369             {
370                 if (additional[i] < 0 || additional[i] > maxIndex)
371                 {
372                     throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
373                 }
374             }
375         }
376         return exclusives.get(toImmutableBitSet(index, additional));
377     }
378 
379     /** {@inheritDoc} */
380     public Set<E> union()
381     {
382         return union;
383     }
384 
385     /** {@inheritDoc} */
386     public ObservableSet<E> selection()
387     {
388         return selection;
389     }
390 }