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();
}