do not use Element.clone() to get or insert a DocumentFragment

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
index 514b45c..50dbff7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
@@ -12,7 +12,6 @@
 package org.eclipse.vex.core.internal.dom;
 
 import java.text.MessageFormat;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -278,6 +277,35 @@
 		return canInsertAt(getInsertionParentAt(offset), offset, fragment.getNodeNames());
 	}
 
+	public void insertFragment(final int offset, final DocumentFragment fragment) throws DocumentValidationException {
+		if (offset < 1 || offset >= getLength()) {
+			throw new IllegalArgumentException("Error inserting document fragment");
+		}
+
+		if (!canInsertAt(getInsertionParentAt(offset), offset, fragment.getNodeNames())) {
+			throw new DocumentValidationException("Cannot insert document fragment");
+		}
+
+		final Element parent = getElementAt(offset);
+
+		fireBeforeContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+
+		getContent().insertContent(offset, fragment.getContent());
+
+		final DeepCopy deepCopy = new DeepCopy(fragment);
+		final List<Node> newNodes = deepCopy.getNodes();
+		int index = parent.getInsertionIndex(offset);
+		for (final Node newNode : newNodes) {
+			parent.insertChild(index, newNode);
+			newNode.associate(getContent(), newNode.getRange().moveBounds(offset));
+			index++;
+		}
+
+		final IUndoableEdit edit = undoEnabled ? new InsertFragmentEdit(offset, fragment) : null;
+
+		fireContentInserted(new DocumentEvent(this, parent, offset, fragment.getContent().length(), edit));
+	}
+
 	public void delete(final Range range) throws DocumentValidationException {
 		final Element surroundingElement = getElementAt(range.getStartOffset() - 1);
 		final Element elementAtEndOffset = getElementAt(range.getEndOffset() + 1);
@@ -367,25 +395,9 @@
 	}
 
 	public DocumentFragment getFragment(final Range range) {
-		final List<Node> childNodes = getParentOfRange(range).getChildNodes();
-
-		final Content cloneContent = getContent().getContent(range);
-		final List<Node> cloneChildNodes = new ArrayList<Node>();
-
-		for (final Node child : childNodes) {
-			if (child.getEndOffset() <= range.getStartOffset()) {
-				continue;
-			} else if (child.getStartOffset() >= range.getEndOffset()) {
-				break;
-			} else {
-				final Node cloneChildNode = cloneNode(child, cloneContent, -range.getStartOffset(), null);
-				if (cloneChildNode != null) {
-					cloneChildNodes.add(cloneChildNode);
-				}
-			}
-		}
-
-		return new DocumentFragment(cloneContent, cloneChildNodes);
+		final Parent parent = getParentOfRange(range);
+		final DeepCopy deepCopy = new DeepCopy(parent, range);
+		return new DocumentFragment(deepCopy.getContent(), deepCopy.getNodes());
 	}
 
 	private Parent getParentOfRange(final Range range) {
@@ -400,71 +412,10 @@
 		return parent;
 	}
 
-	private Node cloneNode(final Node original, final Content content, final int shift, final Parent parent) {
-		final Node result[] = new Node[1];
-		original.accept(new BaseNodeVisitor() {
-			@Override
-			public void visit(final Element element) {
-				result[0] = cloneElement(element, content, shift, parent);
-			}
-		});
-
-		return result[0];
-	}
-
-	private Element cloneElement(final Element original, final Content content, final int shift, final Parent parent) {
-		final Element clone = original.clone();
-		clone.associate(content, original.getRange().moveBounds(shift, shift));
-		clone.setParent(parent);
-
-		final List<Node> children = original.getChildNodes();
-		for (final Node child : children) {
-			final Node cloneChild = cloneNode(child, content, shift, clone);
-			if (cloneChild != null) {
-				clone.addChild(cloneChild);
-			}
-		}
-
-		return clone;
-	}
-
 	public List<Node> getNodes(final Range range) {
 		return getParentOfRange(range).getChildNodes(range);
 	}
 
-	public void insertFragment(final int offset, final DocumentFragment fragment) throws DocumentValidationException {
-		if (offset < 1 || offset >= getLength()) {
-			throw new IllegalArgumentException("Error inserting document fragment");
-		}
-
-		if (!canInsertAt(getInsertionParentAt(offset), offset, fragment.getNodeNames())) {
-			throw new DocumentValidationException("Cannot insert document fragment");
-		}
-
-		final Element parent = getElementAt(offset);
-
-		fireBeforeContentInserted(new DocumentEvent(this, parent, offset, 2, null));
-
-		getContent().insertContent(offset, fragment.getContent());
-
-		final List<Element> children = parent.getChildElements();
-		int index = 0;
-		while (index < children.size() && children.get(index).getEndOffset() < offset) {
-			index++;
-		}
-
-		final List<Element> elements = fragment.getElements();
-		for (int i = 0; i < elements.size(); i++) {
-			final Element newElement = cloneElement(elements.get(i), getContent(), offset, parent);
-			parent.insertChild(index, newElement);
-			index++;
-		}
-
-		final IUndoableEdit edit = undoEnabled ? new InsertFragmentEdit(offset, fragment) : null;
-
-		fireContentInserted(new DocumentEvent(this, parent, offset, fragment.getContent().length(), edit));
-	}
-
 	public void fireAttributeChanged(final DocumentEvent e) {
 		listeners.fireEvent("attributeChanged", e);
 	}