+ // Add source components to invalidation tree
+ for (RocketComponent c : src) {
+ toInvalidate.add(c);
+ }
+
+ return toInvalidate;
+ }
+
+ protected void invalidate() {
+ invalidator.invalidate();
+ }
+
+
+ ////////// Iterator implementation ///////////
+
+ /**
+ * Private inner class to implement the Iterator.
+ *
+ * This iterator is fail-fast if the root of the structure is a Rocket.
+ */
+ private static class RocketComponentIterator implements Iterator<RocketComponent> {
+ // Stack holds iterators which still have some components left.
+ private final Deque<Iterator<RocketComponent>> iteratorStack = new ArrayDeque<Iterator<RocketComponent>>();
+
+ private final Rocket root;
+ private final int treeModID;
+
+ private final RocketComponent original;
+ private boolean returnSelf = false;
+
+ // Construct iterator with component's child's iterator, if it has elements
+ public RocketComponentIterator(RocketComponent c, boolean returnSelf) {
+
+ RocketComponent gp = c.getRoot();
+ if (gp instanceof Rocket) {
+ root = (Rocket) gp;
+ treeModID = root.getTreeModID();
+ } else {
+ root = null;
+ treeModID = -1;
+ }
+
+ Iterator<RocketComponent> i = c.children.iterator();
+ if (i.hasNext())
+ iteratorStack.push(i);
+
+ this.original = c;
+ this.returnSelf = returnSelf;
+ }
+
+ @Override
+ public boolean hasNext() {
+ checkID();
+ if (returnSelf)
+ return true;
+ return !iteratorStack.isEmpty(); // Elements remain if stack is not empty
+ }
+
+ @Override
+ public RocketComponent next() {
+ Iterator<RocketComponent> i;
+
+ checkID();
+
+ // Return original component first
+ if (returnSelf) {
+ returnSelf = false;
+ return original;
+ }
+
+ // Peek first iterator from stack, throw exception if empty
+ i = iteratorStack.peek();
+ if (i == null) {
+ throw new NoSuchElementException("No further elements in RocketComponent iterator");
+ }
+
+ // Retrieve next component of the iterator, remove iterator from stack if empty
+ RocketComponent c = i.next();
+ if (!i.hasNext())
+ iteratorStack.pop();
+
+ // Add iterator of component children to stack if it has children
+ i = c.children.iterator();
+ if (i.hasNext())
+ iteratorStack.push(i);
+
+ return c;
+ }
+
+ private void checkID() {
+ if (root != null) {
+ if (root.getTreeModID() != treeModID) {
+ throw new IllegalStateException("Rocket modified while being iterated");
+ }
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("remove() not supported by " +
+ "RocketComponent iterator");
+ }