| KeyIterator.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 as published by
5 * the Free Software Foundation. This program is distributed in the hope
6 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 * ID: $Id: KeyIterator.java 2050 2010-12-09 15:31:45Z dmsmith $
21 */
22 package org.crosswire.jsword.passage;
23
24 import java.util.Iterator;
25 import java.util.NoSuchElementException;
26 import java.util.Stack;
27
28 /**
29 * This KeyIterator performs a depth first iteration over the subkeys in the
30 * key.
31 *
32 * @see gnu.lgpl.License for license details.<br>
33 * The copyright to this program is held by it's authors.
34 * @author DM Smith [dmsmith555 at yahoo dot com]
35 */
36 public class KeyIterator implements Iterator<Key> {
37 public KeyIterator(Key key) {
38 stack = new Stack<Locator>();
39 stack.push(new Locator(key));
40 }
41
42 protected void prepare() {
43 // If there is nothing on the stack we have nothing to do.
44 if (stack.size() == 0) {
45 return;
46 }
47
48 // Check to see if there are more children to process
49 Locator peek = stack.peek();
50
51 if (peek.getParent().getChildCount() > peek.getPosition()) {
52 return;
53 }
54
55 // There are no more so we are done with this Locator.
56 stack.pop();
57
58 // Try the next
59 prepare();
60 }
61
62 public boolean hasNext() {
63 prepare();
64 return stack.size() != 0;
65 }
66
67 public Key next() {
68 if (!hasNext()) {
69 throw new NoSuchElementException();
70 }
71
72 Locator peek = stack.peek();
73
74 // Determine which child in the list of children to consider
75 int childNum = peek.getPosition();
76
77 // Advance to the next potential child
78 peek.setPosition(childNum + 1);
79
80 // If we have exhausted all the children,
81 // then return the parent key
82 if (childNum == -1) {
83 return peek.getParent();
84 }
85
86 stack.push(new Locator(peek.getParent().get(childNum)));
87
88 return next();
89 }
90
91 public void remove() {
92 throw new UnsupportedOperationException();
93 }
94
95 /**
96 * A helper class that remembers where we've been and where we are.
97 */
98 public static class Locator {
99 private Key parent;
100 private int position;
101
102 public Locator(Key parent) {
103 this.parent = parent;
104 this.position = -1;
105 }
106
107 /**
108 * @return the parent
109 */
110 public Key getParent() {
111 return parent;
112 }
113
114 /**
115 * @param parent
116 * the parent to set
117 */
118 public void setParent(Key parent) {
119 this.parent = parent;
120 }
121
122 /**
123 * @return the position
124 */
125 public int getPosition() {
126 return position;
127 }
128
129 /**
130 * @param position
131 * the position to set
132 */
133 public void setPosition(int position) {
134 this.position = position;
135 }
136
137 }
138
139 private Stack<Locator> stack;
140 }
141