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.TernaryVennModel;
41  
42  import static org.dishevelled.venn.model.VennModelUtils.toImmutableBitSet;
43  
44  /**
45   * Immutable implementation of TernaryVennModel.
46   *
47   * @param <E> value type
48   * @author  Michael Heuer
49   * @version $Revision$ $Date$
50   */
51  public final class TernaryVennModelImpl<E>
52      implements TernaryVennModel<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      /** First only view. */
64      private final Set<E> firstOnly;
65  
66      /** Second only view. */
67      private final Set<E> secondOnly;
68  
69      /** Third only view. */
70      private final Set<E> thirdOnly;
71  
72      /** First second view. */
73      private final Set<E> firstSecond;
74  
75      /** First third view. */
76      private final Set<E> firstThird;
77  
78      /** Second third view. */
79      private final Set<E> secondThird;
80  
81      /** Intersection view. */
82      private final Set<E> intersection;
83  
84      /** Union view. */
85      private final Set<E> union;
86  
87      /** Selection view. */
88      private final ObservableSet<E> selection;
89  
90      /** Map of exclusive set views keyed by bit set. */
91      private final Map<ImmutableBitSet, Set<E>> exclusives;
92  
93  
94      /**
95       * Create a new empty ternary venn model.
96       */
97      public TernaryVennModelImpl()
98      {
99          this(new HashSet<E>(), new HashSet<E>(), new HashSet<E>());
100     }
101 
102     /**
103      * Create a new ternary venn model with the specified sets.
104      *
105      * @param first first set, must not be null
106      * @param second second set, must not be null
107      * @param third third set, must not be null
108      */
109     public TernaryVennModelImpl(final Set<? extends E> first,
110                                 final Set<? extends E> second,
111                                 final Set<? extends E> third)
112     {
113         if (first == null)
114         {
115             throw new IllegalArgumentException("first must not be null");
116         }
117         if (second == null)
118         {
119             throw new IllegalArgumentException("second must not be null");
120         }
121         if (third == null)
122         {
123             throw new IllegalArgumentException("third must not be null");
124         }
125 
126         // todo  defensive copy?
127         this.first = new ObservableSetImpl(first);
128         this.second = new ObservableSetImpl(second);
129         this.third = new ObservableSetImpl(third);
130 
131         // alias
132         ObservableSet<E> f = this.first;
133         ObservableSet<E> s = this.second;
134         ObservableSet<E> t = this.third;
135         firstOnly = Sets.difference(Sets.difference(f, s), t); // f - s - t
136         secondOnly = Sets.difference(Sets.difference(s, f), t); // s - f - t
137         thirdOnly = Sets.difference(Sets.difference(t, f), s); // t - f - s
138         firstSecond = Sets.difference(Sets.intersection(f, s), t); // f n s - t
139         firstThird = Sets.difference(Sets.intersection(f, t), s); // f n t - s
140         secondThird = Sets.difference(Sets.intersection(s, t), f); // s n t - f
141         intersection = Sets.intersection(f, Sets.intersection(s, t)); // f n s n t
142         union = Sets.union(f, Sets.union(s, t)); // f u s u t
143         selection = new SelectionView<E>(union, f, s, t);
144 
145         exclusives = new HashMap<ImmutableBitSet, Set<E>>(7);
146 
147         exclusives.put(toImmutableBitSet(0), firstOnly);
148         exclusives.put(toImmutableBitSet(1), secondOnly);
149         exclusives.put(toImmutableBitSet(2), thirdOnly);
150 
151         exclusives.put(toImmutableBitSet(0, 1), firstSecond);
152         exclusives.put(toImmutableBitSet(0, 2), firstThird);
153         exclusives.put(toImmutableBitSet(1, 2), secondThird);
154 
155         exclusives.put(toImmutableBitSet(0, 1, 2), intersection);
156     }
157 
158 
159     /** {@inheritDoc} */
160     public int size()
161     {
162         return 3;
163     }
164 
165     /** {@inheritDoc} */
166     public ObservableSet<E> first()
167     {
168         return first;
169     }
170 
171     /** {@inheritDoc} */
172     public ObservableSet<E> second()
173     {
174         return second;
175     }
176 
177     /** {@inheritDoc} */
178     public ObservableSet<E> third()
179     {
180         return third;
181     }
182 
183     /** {@inheritDoc} */
184     public Set<E> get(final int index)
185     {
186         if (index < 0 || index > 2)
187         {
188             throw new IndexOutOfBoundsException("index out of bounds");
189         }
190         switch (index)
191         {
192         case 0:
193             return first;
194         case 1:
195             return second;
196         case 2:
197             return third;
198         default:
199             break;
200         }
201         throw new IllegalStateException("invalid index " + index);
202     }
203 
204     /** {@inheritDoc} */
205     public Set<E> firstOnly()
206     {
207         return firstOnly;
208     }
209 
210     /** {@inheritDoc} */
211     public Set<E> secondOnly()
212     {
213         return secondOnly;
214     }
215 
216     /** {@inheritDoc} */
217     public Set<E> thirdOnly()
218     {
219         return thirdOnly;
220     }
221 
222     /** {@inheritDoc} */
223     public Set<E> firstSecond()
224     {
225         return firstSecond;
226     }
227 
228     /** {@inheritDoc} */
229     public Set<E> firstThird()
230     {
231         return firstThird;
232     }
233 
234     /** {@inheritDoc} */
235     public Set<E> secondThird()
236     {
237         return secondThird;
238     }
239 
240     /** {@inheritDoc} */
241     public Set<E> intersection()
242     {
243         return intersection;
244     }
245 
246     /** {@inheritDoc} */
247     public Set<E> exclusiveTo(final int index, final int... additional)
248     {
249         int maxIndex = size() - 1;
250         if (index < 0 || index > maxIndex)
251         {
252             throw new IndexOutOfBoundsException("index out of bounds");
253         }
254         if (additional != null && additional.length > 0)
255         {
256             if (additional.length > maxIndex)
257             {
258                 throw new IndexOutOfBoundsException("too many indices provided");
259             }
260             for (int i = 0, size = additional.length; i < size; i++)
261             {
262                 if (additional[i] < 0 || additional[i] > maxIndex)
263                 {
264                     throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
265                 }
266             }
267         }
268         return exclusives.get(toImmutableBitSet(index, additional));
269     }
270 
271     /** {@inheritDoc} */
272     public Set<E> union()
273     {
274         return union;
275     }
276 
277     /** {@inheritDoc} */
278     public ObservableSet<E> selection()
279     {
280         return selection;
281     }
282 }