01: package org.python.modules.sets;
02:
03: import org.python.core.PyObject;
04: import org.python.core.Py;
05:
06: import java.util.Iterator;
07: import java.util.Set;
08: import java.util.ConcurrentModificationException;
09:
10: public class PySetIterator extends PyObject {
11: private Set _set;
12: private int _count;
13: private Iterator _iterator;
14:
15: public PySetIterator(Set set) {
16: super ();
17: this ._set = set;
18: this ._count = 0;
19: this ._iterator = set.iterator();
20: }
21:
22: public PyObject __iter__() {
23: return this ;
24: }
25:
26: /**
27: * Returns the next item in the iteration or raises a StopIteration.
28: * <p/>
29: * <p/>
30: * This differs from the core Jython Set iterator in that it checks if
31: * the underlying Set changes in size during the course and upon completion
32: * of the iteration. A RuntimeError is raised if the Set ever changes size
33: * or is concurrently modified.
34: * </p>
35: *
36: * @return the next item in the iteration
37: */
38: public PyObject next() {
39: PyObject o = this .__iternext__();
40: if (o == null) {
41: if (this ._count != this ._set.size()) {
42: // CPython throws an exception even if you have iterated through the
43: // entire set, this is not true for Java, so check by hand
44: throw Py
45: .RuntimeError("dictionary changed size during iteration");
46: }
47: throw Py.StopIteration("");
48: }
49: return o;
50: }
51:
52: /**
53: * Returns the next item in the iteration.
54: *
55: * @return the next item in the iteration
56: * or null to signal the end of the iteration
57: */
58: public PyObject __iternext__() {
59: if (this ._iterator.hasNext()) {
60: this ._count++;
61: try {
62: return Py.java2py(this ._iterator.next());
63: } catch (ConcurrentModificationException e) {
64: throw Py
65: .RuntimeError("dictionary changed size during iteration");
66: }
67: }
68: return null;
69: }
70: }
|