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.BinaryVennModel;
41  
42  import static org.dishevelled.venn.model.VennModelUtils.toImmutableBitSet;
43  
44  /**
45   * Immutable implementation of BinaryVennModel.
46   *
47   * @param <E> value type
48   * @author  Michael Heuer
49   * @version $Revision$ $Date$
50   */
51  public final class BinaryVennModelImpl<E>
52      implements BinaryVennModel<E>
53  {
54      /** First view. */
55      private final ObservableSet<E> first;
56  
57      /** Second view. */
58      private final ObservableSet<E> second;
59  
60      /** First only view. */
61      private final Set<E> firstOnly;
62  
63      /** Second only view. */
64      private final Set<E> secondOnly;
65  
66      /** Intersection view. */
67      private final Set<E> intersection;
68  
69      /** Union view. */
70      private final Set<E> union;
71  
72      /** Selection view. */
73      private final ObservableSet<E> selection;
74  
75      /** Map of exclusive set views keyed by bit set. */
76      private final Map<ImmutableBitSet, Set<E>> exclusives;
77  
78  
79      /**
80       * Create a new empty binary venn model.
81       */
82      public BinaryVennModelImpl()
83      {
84          this(new HashSet<E>(), new HashSet<E>());
85      }
86  
87      /**
88       * Create a new binary venn model with the specified sets.
89       *
90       * @param first first set, must not be null
91       * @param second second set, must not be null
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         // todo  defensive copy?
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         // copy to immutable map?
120     }
121 
122 
123     /** {@inheritDoc} */
124     public int size()
125     {
126         return 2;
127     }
128 
129     /** {@inheritDoc} */
130     public ObservableSet<E> first()
131     {
132         return first;
133     }
134 
135     /** {@inheritDoc} */
136     public ObservableSet<E> second()
137     {
138         return second;
139     }
140 
141     /** {@inheritDoc} */
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     /** {@inheritDoc} */
161     public Set<E> firstOnly()
162     {
163         return firstOnly;
164     }
165 
166     /** {@inheritDoc} */
167     public Set<E> secondOnly()
168     {
169         return secondOnly;
170     }
171 
172     /** {@inheritDoc} */
173     public Set<E> intersection()
174     {
175         return intersection;
176     }
177 
178     /** {@inheritDoc} */
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     /** {@inheritDoc} */
204     public Set<E> union()
205     {
206         return union;
207     }
208 
209     /** {@inheritDoc} */
210     public ObservableSet<E> selection()
211     {
212         return selection;
213     }
214 }