public Iterator iterator()

in wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java [558:668]


	public Iterator<Component> iterator()
	{
		/**
		 * Iterator that knows how to change between a single child, list of children and map of
		 * children. Keeps track when the iterator was last sync'd with the markup container's
		 * tracking of changes to the list of children.
		 */
		class MarkupChildIterator implements Iterator<Component>
		{
			private int indexInRemovalsSinceLastUpdate;
			private int expectedModCounter = -1;
			private Component currentComponent = null;
			private Iterator<Component> internalIterator = null;

			@Override
			public boolean hasNext()
			{
				refreshInternalIteratorIfNeeded();
				return internalIterator.hasNext();
			}

			@Override
			public Component next()
			{
				refreshInternalIteratorIfNeeded();
				return currentComponent = internalIterator.next();
			}

			@Override
			public void remove()
			{
				MarkupContainer.this.remove(currentComponent);
				refreshInternalIteratorIfNeeded();
			}

			private void refreshInternalIteratorIfNeeded()
			{
				if (expectedModCounter >= modCounter) {
					// no new modifications
					return;
				}

				if (children == null)
				{
					internalIterator = Collections.emptyIterator();
				}
				else if (children instanceof Component)
				{
					internalIterator = Collections.singleton((Component)children).iterator();
				}
				else if (children instanceof List)
				{
					List<Component> childrenList = children();
					internalIterator = childrenList.iterator();
				}
				else
				{
					Map<String, Component> childrenMap = children();
					internalIterator = childrenMap.values().iterator();
				}

				// since we now have a new iterator, we need to set it to the last known position
				currentComponent = findLastExistingChildAlreadyReturned(currentComponent);
				expectedModCounter = modCounter;

				if (currentComponent != null)
				{
					// move the new internal iterator to the place of the last processed component
					while (internalIterator.hasNext() &&
						internalIterator.next() != currentComponent)
						// noop
						;
				}
			}

			private Component findLastExistingChildAlreadyReturned(Component current)
			{
				if (current == null) {
					indexInRemovalsSinceLastUpdate = 0;
				} else {
					LinkedList<RemovedChild> removals = removals_get();
					if (removals != null) {
						check_removed:
						while (current != null)
						{
							for (int i = indexInRemovalsSinceLastUpdate; i < removals.size(); i++)
							{
								RemovedChild removal = removals.get(i);
								if (removal.removedChild == current ||
									removal.removedChild == null)
								{
									current = removal.previousSibling;
									
									// current was removed, use its sibling instead
									continue check_removed;
								}
							}
							
							// current wasn't removed, keep it
							break;
						}
						
						indexInRemovalsSinceLastUpdate = removals.size();
					}
				}
				
				return current;
			}
		};
		return new MarkupChildIterator();
	}