KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > modules > sets > BaseSet


1
2 package org.python.modules.sets;
3
4 import org.python.core.Py;
5 import org.python.core.PyException;
6 import org.python.core.PyIgnoreMethodTag;
7 import org.python.core.PyList;
8 import org.python.core.PyObject;
9 import org.python.core.PyTuple;
10 import org.python.core.__builtin__;
11 import org.python.core.PyType;
12
13 import java.util.Collection JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.Set JavaDoc;
18
19 public abstract class BaseSet extends PyObject /*implements Set*/ {
20
21     /**
22      * The underlying container. HashSet is used rather than Set because
23      * clone is protected on Object and I didn't want to cast.
24      */

25     protected HashSet JavaDoc _set;
26
27     /**
28      * Create a new, empty set instance.
29      */

30     public BaseSet() {
31         super();
32         this._set = new HashSet JavaDoc();
33     }
34
35     /**
36      * Create a new set instance from the values of the iterable object.
37      *
38      * @param data An iterable instance.
39      */

40     public BaseSet(PyObject data) {
41         super();
42         this._set = new HashSet JavaDoc();
43         this._update(data);
44     }
45
46     public BaseSet(PyType type) {
47         super(type);
48         this._set = new HashSet JavaDoc();
49     }
50
51     /**
52      * Update the underlying set with the contents of the iterable.
53      *
54      * @param data An iterable instance.
55      * @throws PyIgnoreMethodTag Ignore.
56      */

57     protected void _update(PyObject data) throws PyIgnoreMethodTag {
58
59         if(data instanceof BaseSet) {
60             // Skip the iteration if both are sets
61
this._set.addAll(((BaseSet)data)._set);
62             return;
63         }
64
65         PyObject value = null;
66         if (data.__findattr__("__iter__") != null) {
67             PyObject iter = data.__iter__();
68             while ((value = iter.__iternext__()) != null) {
69                 try {
70                     this._set.add(value);
71                 } catch (PyException e) {
72                     PyObject immutable = this.asImmutable(e, value);
73                     this._set.add(immutable);
74                 }
75             }
76         } else {
77             int i = 0;
78             while(true) {
79                 try {
80                     value = data.__finditem__(i++);
81                     if (value == null) {
82                         break;
83                     }
84                 } catch (PyException e) {
85                     if(Py.matchException(e, Py.AttributeError)) {
86                         throw Py.TypeError("object not iterable");
87                     }
88                     throw e;
89                 }
90                 try {
91                     this._set.add(value);
92                 } catch (PyException e) {
93                     PyObject immutable = this.asImmutable(e, value);
94                     this._set.add(immutable);
95                 }
96             }
97         }
98     }
99
100     /**
101      * The union of <code>this</code> with <code>other</code>.
102      * <p/>
103      * <br/>
104      * (I.e. all elements that are in either set)
105      *
106      * @param other A <code>BaseSet</code> instance.
107      * @return The union of the two sets as a new set.
108      */

109     public PyObject __or__(PyObject other) {
110         return baseset___or__(other);
111     }
112
113     final PyObject baseset___or__(PyObject other) {
114         if (!(other instanceof BaseSet)) {
115             throw Py.TypeError("Not Implemented");
116         }
117         return baseset_union(other);
118     }
119
120     /**
121      * The intersection of the <code>this</code> with <code>other</code>.
122      * <p/>
123      * <br/>
124      * (I.e. all elements that are in both sets)
125      *
126      * @param other A <code>BaseSet</code> instance.
127      * @return The intersection of the two sets as a new set.
128      */

129     public PyObject __and__(PyObject other) {
130         return baseset___and__(other);
131     }
132
133     final PyObject baseset___and__(PyObject other) {
134         if (!(other instanceof BaseSet)) {
135             throw Py.TypeError("Not Implemented");
136         }
137         return baseset_intersection(other);
138     }
139
140     /**
141      * The difference of the <code>this</code> with <code>other</code>.
142      * <p/>
143      * <br/>
144      * (I.e. all elements that are in this set and not in the other)
145      *
146      * @param other A <code>BaseSet</code> instance.
147      * @return The difference of the two sets as a new set.
148      */

149     public PyObject __sub__(PyObject other) {
150         return baseset___sub__(other);
151     }
152
153     final PyObject baseset___sub__(PyObject other) {
154         if (!(other instanceof BaseSet)) {
155             throw Py.TypeError("Not Implemented");
156         }
157         return difference(other);
158     }
159
160     public PyObject difference(PyObject other) {
161         return baseset_difference(other);
162     }
163
164     final PyObject baseset_difference(PyObject other) {
165         BaseSet iterable = (other instanceof BaseSet) ? (BaseSet) other : new PySet(other);
166         Set JavaDoc set = iterable._set;
167         BaseSet o = (BaseSet) this.getType().__call__();
168         for (Iterator JavaDoc i = this._set.iterator(); i.hasNext();) {
169             Object JavaDoc p = i.next();
170             if (!set.contains(p)) {
171                 o._set.add(p);
172             }
173         }
174
175         return o;
176     }
177
178     /**
179      * The symmetric difference of the <code>this</code> with <code>other</code>.
180      * <p/>
181      * <br/>
182      * (I.e. all elements that are in exactly one of the sets)
183      *
184      * @param other A <code>BaseSet</code> instance.
185      * @return The symmetric difference of the two sets as a new set.
186      */

187     public PyObject __xor__(PyObject other) {
188         return baseset___xor__(other);
189     }
190
191     final PyObject baseset___xor__(PyObject other) {
192         if (!(other instanceof BaseSet)) {
193             throw Py.TypeError("Not Implemented");
194         }
195         return symmetric_difference(other);
196     }
197
198     public PyObject symmetric_difference(PyObject other) {
199         return baseset_symmetric_difference(other);
200     }
201
202     public PyObject baseset_symmetric_difference(PyObject other) {
203         BaseSet iterable = (other instanceof BaseSet) ? (BaseSet) other : new PySet(other);
204         BaseSet o = (BaseSet) this.getType().__call__();
205         for (Iterator JavaDoc i = this._set.iterator(); i.hasNext();) {
206             Object JavaDoc p = i.next();
207             if (!iterable._set.contains(p)) {
208                 o._set.add(p);
209             }
210         }
211         for (Iterator JavaDoc i = iterable._set.iterator(); i.hasNext();) {
212             Object JavaDoc p = i.next();
213             if (!this._set.contains(p)) {
214                 o._set.add(p);
215             }
216         }
217         return o;
218     }
219
220     /**
221      * The hashCode of the set. Only immutable instances can be hashed.
222      *
223      * @return The hashCode of the set.
224      */

225     public abstract int hashCode();
226
227     /**
228      * The length of the set.
229      *
230      * @return The length of the set.
231      */

232     public int __len__() {
233         return baseset___len__();
234     }
235
236     final int baseset___len__() {
237         return this._set.size();
238     }
239
240     /**
241      * Determines if the instance is considered <code>true</code> by Python.
242      * This implementation returns true if the set is not empty.
243      *
244      * @return <code>true</code> if the set is not empty, <code>false</code> otherwise
245      */

246     public boolean __nonzero__() {
247         return baseset___nonzero__();
248     }
249
250     final boolean baseset___nonzero__() {
251         return !this._set.isEmpty();
252     }
253
254     /**
255      * Produce an iterable object.
256      *
257      * @return An iteration of the set.
258      */

259     public PyObject __iter__() {
260         return new PySetIterator(this._set);
261     }
262
263     public boolean __contains__(PyObject other) {
264         return baseset___contains__(other);
265     }
266
267     final boolean baseset___contains__(PyObject other) {
268         return this._set.contains(other);
269     }
270
271     public PyObject __eq__(PyObject other) {
272         return baseset___eq__(other);
273     }
274
275     final PyObject baseset___eq__(PyObject other) {
276         if(other instanceof BaseSet) {
277             BaseSet bs = this._binary_sanity_check(other);
278             return Py.newBoolean(this._set.equals(bs._set));
279         }
280         return Py.Zero;
281     }
282
283     public PyObject __ne__(PyObject other) {
284         return baseset___ne__(other);
285     }
286
287     final PyObject baseset___ne__(PyObject other) {
288         if(other instanceof BaseSet) {
289             BaseSet bs = this._binary_sanity_check(other);
290             return Py.newBoolean(!this._set.equals(bs._set));
291         }
292         return Py.One;
293     }
294
295     public PyObject __le__(PyObject other) {
296         return baseset___le__(other);
297     }
298
299     final PyObject baseset___le__(PyObject other) {
300         return this.baseset_issubset(other);
301     }
302
303     public PyObject __ge__(PyObject other) {
304         return baseset___ge__(other);
305     }
306
307     final PyObject baseset___ge__(PyObject other) {
308         return this.baseset_issuperset(other);
309     }
310
311     public PyObject __lt__(PyObject other) {
312         return baseset___lt__(other);
313     }
314
315     final PyObject baseset___lt__(PyObject other) {
316         BaseSet bs = this._binary_sanity_check(other);
317         return Py.newBoolean(this.__len__() < bs.__len__()
318           && this.baseset_issubset(other).__nonzero__());
319     }
320
321     public PyObject __gt__(PyObject other) {
322         return baseset___gt__(other);
323     }
324
325     public PyObject baseset___gt__(PyObject other) {
326         BaseSet bs = this._binary_sanity_check(other);
327         return Py.newBoolean(this.__len__() > bs.__len__()
328           && this.baseset_issuperset(other).__nonzero__());
329     }
330
331     /**
332      * Used for pickling. Uses the module <code>setsfactory</sets> to
333      * export safe constructors.
334      *
335      * @return a tuple of (constructor, (elements))
336      */

337     public PyObject __reduce__() {
338         String JavaDoc name = getType().getFullName();
339         PyObject factory = __builtin__.__import__("setsfactory");
340         PyObject func = factory.__getattr__(name);
341         return new PyTuple(new PyObject[]{
342             func,
343             new PyTuple(new PyObject[]{
344                 new PyList((PyObject)this)
345             })
346         });
347     }
348
349     public PyObject __deepcopy__(PyObject memo) {
350         return baseset___deepcopy__(memo);
351     }
352
353     final PyObject baseset___deepcopy__(PyObject memo) {
354         PyObject copy = __builtin__.__import__("copy");
355         PyObject deepcopy = copy.__getattr__("deepcopy");
356         BaseSet result = (BaseSet) this.getType().__call__();
357         memo.__setitem__(Py.newInteger(Py.id(this)), result);
358         for (Iterator JavaDoc iterator = this._set.iterator(); iterator.hasNext();) {
359             result._set.add(deepcopy.__call__(Py.java2py(iterator.next()), memo));
360         }
361         return result;
362     }
363
364     /**
365      * Return this instance as a Java object. Only coerces to Collection and subinterfaces.
366      *
367      * @param c The Class to coerce to.
368      * @return the underlying HashSet (not a copy)
369      */

370     public Object JavaDoc __tojava__(Class JavaDoc c) {
371         if (Collection JavaDoc.class.isAssignableFrom(c)) {
372             return Collections.unmodifiableSet(this._set);
373         }
374         return super.__tojava__(c);
375     }
376
377     public PyObject baseset_union(PyObject other) {
378         BaseSet result = (BaseSet) this.getType().__call__(this);
379         result._update(other);
380         return result;
381     }
382
383     public PyObject baseset_intersection(PyObject other) {
384
385         PyObject little, big;
386         if(!(other instanceof BaseSet)) {
387             other = new PySet(other);
388         }
389
390         if (this.__len__() <= __builtin__.len(other)) {
391             little = this;
392             big = other;
393         } else {
394             little = other;
395             big = this;
396         }
397
398         PyObject common = __builtin__.filter(big.__getattr__("__contains__"), little);
399         return other.getType().__call__(common);
400     }
401
402     public PyObject baseset_copy() {
403         BaseSet copy = (BaseSet) this.getType().__call__();
404         copy._set = (HashSet JavaDoc) this._set.clone();
405         return copy;
406     }
407
408     public PyObject baseset_issubset(PyObject other) {
409         BaseSet bs = this._binary_sanity_check(other);
410         if (this.__len__() > bs.__len__()) {
411             return Py.Zero;
412         }
413         for (Iterator JavaDoc iterator = this._set.iterator(); iterator.hasNext();) {
414             if (!bs._set.contains(iterator.next())) {
415                 return Py.Zero;
416             }
417         }
418         return Py.One;
419     }
420
421     public PyObject baseset_issuperset(PyObject other) {
422         BaseSet bs = this._binary_sanity_check(other);
423         if (this.__len__() < bs.__len__()) {
424             return Py.Zero;
425         }
426         for (Iterator JavaDoc iterator = bs._set.iterator(); iterator.hasNext();) {
427             if (!this._set.contains(iterator.next())) {
428                 return Py.Zero;
429             }
430         }
431         return Py.One;
432     }
433
434     final String JavaDoc baseset_toString() {
435         return toString();
436     }
437
438     public String JavaDoc toString() {
439         String JavaDoc name = getType().getFullName();
440         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(name).append("([");
441         for (Iterator JavaDoc i = this._set.iterator(); i.hasNext();) {
442             buf.append(((PyObject) i.next()).__repr__().toString());
443             if (i.hasNext()) {
444                 buf.append(", ");
445             }
446         }
447         buf.append("])");
448         return buf.toString();
449     }
450
451     protected final BaseSet _binary_sanity_check(PyObject other) throws PyIgnoreMethodTag {
452         try {
453             return (BaseSet) other;
454         } catch (ClassCastException JavaDoc e) {
455             throw Py.TypeError("Binary operation only permitted between sets");
456         }
457     }
458
459     /**
460      * If the exception <code>e</code> is a <code>TypeError</code>, attempt to convert
461      * the object <code>value</code> into an ImmutableSet.
462      *
463      * @param e The exception thrown from a hashable operation.
464      * @param value The object which was unhashable.
465      * @return An ImmutableSet if available, a <code>TypeError</code> is thrown otherwise.
466      */

467     protected final PyObject asImmutable(PyException e, PyObject value) {
468         if (Py.matchException(e, Py.TypeError)) {
469             PyObject transform = value.__findattr__("_as_immutable");
470             if (transform != null) {
471                 return transform.__call__();
472             }
473         }
474         throw e;
475     }
476
477 // public int size() {
478
// return this._set.size();
479
// }
480
//
481
// public void clear() {
482
// this._set.clear();
483
// }
484
//
485
// public boolean isEmpty() {
486
// return this._set.isEmpty();
487
// }
488
//
489
// public Object[] toArray() {
490
// return this._set.toArray();
491
// }
492
//
493
// public boolean add(Object o) {
494
// return this._set.add(o);
495
// }
496
//
497
// public boolean contains(Object o) {
498
// return this._set.contains(o);
499
// }
500
//
501
// public boolean remove(Object o) {
502
// return this._set.remove(o);
503
// }
504
//
505
// public boolean addAll(Collection c) {
506
// return this._set.addAll(c);
507
// }
508
//
509
// public boolean containsAll(Collection c) {
510
// return this._set.containsAll(c);
511
// }
512
//
513
// public boolean removeAll(Collection c) {
514
// return this._set.removeAll(c);
515
// }
516
//
517
// public boolean retainAll(Collection c) {
518
// return this._set.retainAll(c);
519
// }
520
//
521
// public Iterator iterator() {
522
// return this._set.iterator();
523
// }
524
//
525
// public Object[] toArray(Object a[]) {
526
// return this._set.toArray(a);
527
// }
528
}
529
Popular Tags