package xcordion.impl.command;

import xcordion.api.CommandType;
import xcordion.api.EvaluationContext;
import xcordion.api.TestElement;
import xcordion.api.Xcordion;
import xcordion.impl.AbstractCommand;

public class ForEachCommand extends AbstractCommand {

	@Override
	public CommandType getCommandType() {
		return CommandType.EXECUTE;
	}

	@Override
	public <T extends TestElement<T>, C extends EvaluationContext<C>> void runElementAndChildren(Xcordion<T> xcordion, T target, C context, String expression) {
		Iterable<C> iterable;
		try {
			iterable = context.iterate(expression, target);
		} catch (Exception e) {
			xcordion.getBroadcaster().exception(target, expression, e);
			return;
		}

		T parent = target.getParent();
		T placeholder = target.getDocument().newElement("span");
        parent.insertChildAfter(target, placeholder);
		T lastSibling = placeholder;
		T prototype = target.duplicate();
		parent.remove(target);
		for (C itemContext : iterable) {
            T newContent = prototype.duplicate();
            parent.insertChildAfter(lastSibling, newContent);
            runChildren(xcordion, newContent.getChildren(), itemContext);
            lastSibling = newContent;
		}
		parent.remove(placeholder);
	}

}

@@ -207,16 +207,46 @@
 and;%0D%0A%0D%0A
+import java.util.Iterator;%0D%0A%0D%0A
 public c
@@ -994,16 +994,20 @@
 rget);%0D%0A
+%0D%0A//
 %09%09for (C
@@ -1034,16 +1034,18 @@
 ble) %7B%0D%0A
+//
         
@@ -1083,24 +1083,983 @@
 plicate();%0D%0A
+//            parent.insertChildAfter(lastSibling, newContent);%0D%0A//            runChildren(xcordion, newContent.getChildren(), itemContext);%0D%0A//            lastSibling = newContent;%0D%0A//%09%09%7D%0D%0A%0D%0A        // The above code wasn't robust against e.g. ConcurrentModificationExceptions (see Issue 7).%0D%0A        // New code is far more paranoid/ugly, but fails slightly more graciously.%0D%0A        Iterator%3CC%3E iterator = iterable.iterator();%0D%0A        while (true) %7B%0D%0A            T newContent = prototype.duplicate();%0D%0A            C itemContext;%0D%0A            try %7B%0D%0A                if (!iterator.hasNext()) %7B%0D%0A                    break;%0D%0A                %7D%0D%0A                itemContext = iterator.next();%0D%0A            %7D catch (Exception e) %7B%0D%0A                parent.insertChildAfter(lastSibling, newContent);%0D%0A                xcordion.getBroadcaster().exception(newContent, expression, e);%0D%0A                lastSibling = newContent;%0D%0A                break;%0D%0A            %7D%0D%0A
             
@@ -2223,19 +2223,27 @@
 ntent;%0D%0A
-%09%09%7D
+        %7D%0D%0A
 %0D%0A%09%09pare

fix issue 7 in xcordion 2 (ConcurrentModificationExceptions result in graceless failure mode)