move serialization code into DocumentFragmentTransfer

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
index ebaa393..ba1feec 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
@@ -11,12 +11,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.dom;
 
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 import org.eclipse.core.runtime.QualifiedName;
@@ -24,17 +19,10 @@
 /**
  * Represents a fragment of an XML document.
  */
-public class DocumentFragment implements Serializable {
+public class DocumentFragment {
 
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * Mime type representing document fragments: "application/x-vex-document-fragment"
-	 */
-	public static final String MIME_TYPE = "application/x-vex-document-fragment";
-
-	private Content content;
-	private List<Node> nodes;
+	private final Content content;
+	private final List<Node> nodes;
 
 	/**
 	 * @param content
@@ -86,116 +74,4 @@
 		return Document.createNodeList(getContent(), 0, getContent().length(), getElements());
 	}
 
-	/*
-	 * Custom Serialization Methods
-	 */
-
-	private void writeObject(final ObjectOutputStream out) throws IOException {
-		writeContent(content, out);
-		for (final Node node : nodes) {
-			node.accept(new BaseNodeVisitor() {
-				@Override
-				public void visit(final Element element) {
-					try {
-						writeElement(element, out);
-					} catch (final IOException e) {
-						// TODO Auto-generated catch block
-						e.printStackTrace();
-					}
-				}
-			});
-		}
-	}
-
-	private static void writeContent(final Content content, final ObjectOutputStream out) throws IOException {
-		final int contentLength = content.length();
-		out.write(contentLength);
-		for (int i = 0; i < contentLength; i++) {
-			if (content.isElementMarker(i)) {
-				out.writeUTF("\0"); // This internal representation of element markers has nothing to do with the internal representation in GapContent.
-			} else {
-				out.writeUTF(content.getText(i, 1));
-			}
-		}
-	}
-
-	private static void writeElement(final Element element, final ObjectOutputStream out) throws IOException {
-		out.writeObject(element.getQualifiedName());
-		out.writeInt(element.getStartOffset());
-		out.writeInt(element.getEndOffset());
-		final Collection<Attribute> attributes = element.getAttributes();
-		out.writeInt(attributes.size());
-		for (final Attribute attribute : attributes) {
-			out.writeObject(attribute.getQualifiedName());
-			out.writeObject(attribute.getValue());
-		}
-		final List<Element> children = element.getChildElements();
-		out.writeInt(children.size());
-		for (int i = 0; i < children.size(); i++) {
-			writeElement(children.get(i), out);
-		}
-	}
-
-	private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
-		content = readContent(in);
-		final int n = in.readInt();
-		nodes = new ArrayList<Node>(n);
-		for (int i = 0; i < n; i++) {
-			nodes.add(readElement(in, content));
-		}
-	}
-
-	private static Content readContent(final ObjectInputStream in) throws IOException {
-		final int contentLength = in.readInt();
-		final Content result = new GapContent(contentLength);
-		for (int i = 0; i < contentLength; i++) {
-			final String input = in.readUTF();
-			if ("\0".equals(input)) { // This internal representation of element markers has nothing to do with the internal representation in GapContent.
-				result.insertElementMarker(i);
-			} else {
-				result.insertText(i, input);
-			}
-		}
-		return result;
-	}
-
-	private static Element readElement(final ObjectInputStream in, final Content content) throws IOException, ClassNotFoundException {
-		final QualifiedName elementName = createQualifiedName(in.readObject());
-		final int startOffset = in.readInt();
-		final int endOffset = in.readInt();
-		final Element element = new Element(elementName);
-		element.associate(content, startOffset, endOffset);
-
-		final int attrCount = in.readInt();
-		for (int i = 0; i < attrCount; i++) {
-			final QualifiedName attributeName = createQualifiedName(in.readObject());
-			final String value = (String) in.readObject();
-			try {
-				element.setAttribute(attributeName, value);
-			} catch (final DocumentValidationException e) {
-				// Should never happen; there ain't no document
-				e.printStackTrace();
-			}
-		}
-
-		final int childCount = in.readInt();
-		for (int i = 0; i < childCount; i++) {
-			final Element child = readElement(in, content);
-			child.setParent(element);
-			element.insertChild(i, child);
-		}
-
-		return element;
-	}
-
-	private static QualifiedName createQualifiedName(final Object object) {
-		final String serializedQualifiedName = object.toString();
-		final int localNameStartIndex = serializedQualifiedName.lastIndexOf(':') + 1;
-		if (localNameStartIndex == 0) {
-			return new QualifiedName(null, serializedQualifiedName);
-		}
-		final String qualifier = serializedQualifiedName.substring(0, localNameStartIndex - 1);
-		final String localName = serializedQualifiedName.substring(localNameStartIndex);
-		return new QualifiedName(qualifier, localName);
-	}
 }
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
index 3252b5c..28157ab 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
@@ -15,16 +15,29 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
+import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.swt.dnd.ByteArrayTransfer;
 import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.vex.core.internal.dom.Attribute;
+import org.eclipse.vex.core.internal.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.internal.dom.Content;
 import org.eclipse.vex.core.internal.dom.DocumentFragment;
+import org.eclipse.vex.core.internal.dom.DocumentValidationException;
+import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.internal.dom.GapContent;
+import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Transfer object that handles Vex DocumentFragments.
  */
 public class DocumentFragmentTransfer extends ByteArrayTransfer {
 
+	private static final String MIME_TYPE = "application/x-vex-document-fragment";
+
 	/**
 	 * Returns the singleton instance of the DocumentFragmentTransfer.
 	 */
@@ -58,7 +71,7 @@
 				// pMedium
 				final ByteArrayOutputStream out = new ByteArrayOutputStream();
 				final ObjectOutputStream oos = new ObjectOutputStream(out);
-				oos.writeObject(frag);
+				writeFragment(frag, oos);
 				final byte[] buffer = out.toByteArray();
 				oos.close();
 				super.javaToNative(buffer, transferData);
@@ -79,7 +92,7 @@
 			try {
 				final ByteArrayInputStream in = new ByteArrayInputStream(buffer);
 				final ObjectInputStream ois = new ObjectInputStream(in);
-				final Object object = ois.readObject();
+				final Object object = readFragment(ois);
 				ois.close();
 				return object;
 			} catch (final ClassNotFoundException ex) {
@@ -94,11 +107,122 @@
 
 	// =================================================== PRIVATE
 
-	private static final String[] typeNames = { DocumentFragment.MIME_TYPE };
-	private static final int[] typeIds = { ByteArrayTransfer.registerType(DocumentFragment.MIME_TYPE) };
+	private static final String[] typeNames = { MIME_TYPE };
+	private static final int[] typeIds = { ByteArrayTransfer.registerType(MIME_TYPE) };
 
 	private static DocumentFragmentTransfer instance;
 
 	private DocumentFragmentTransfer() {
 	}
+
+	private void writeFragment(final DocumentFragment fragment, final ObjectOutputStream out) throws IOException {
+		writeContent(fragment.getContent(), out);
+		for (final Node node : fragment.getNodes()) {
+			node.accept(new BaseNodeVisitor() {
+				@Override
+				public void visit(final Element element) {
+					try {
+						writeElement(element, out);
+					} catch (final IOException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+				}
+			});
+		}
+	}
+
+	private static void writeContent(final Content content, final ObjectOutputStream out) throws IOException {
+		final int contentLength = content.length();
+		out.write(contentLength);
+		for (int i = 0; i < contentLength; i++) {
+			if (content.isElementMarker(i)) {
+				out.writeUTF("\0"); // This internal representation of element markers has nothing to do with the internal representation in GapContent.
+			} else {
+				out.writeUTF(content.getText(i, 1));
+			}
+		}
+	}
+
+	private static void writeElement(final Element element, final ObjectOutputStream out) throws IOException {
+		out.writeObject(element.getQualifiedName());
+		out.writeInt(element.getStartOffset());
+		out.writeInt(element.getEndOffset());
+		final Collection<Attribute> attributes = element.getAttributes();
+		out.writeInt(attributes.size());
+		for (final Attribute attribute : attributes) {
+			out.writeObject(attribute.getQualifiedName());
+			out.writeObject(attribute.getValue());
+		}
+		final List<Element> children = element.getChildElements();
+		out.writeInt(children.size());
+		for (int i = 0; i < children.size(); i++) {
+			writeElement(children.get(i), out);
+		}
+	}
+
+	private DocumentFragment readFragment(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+		final Content content = readContent(in);
+		final int n = in.readInt();
+		final ArrayList<Node> nodes = new ArrayList<Node>(n);
+		for (int i = 0; i < n; i++) {
+			nodes.add(readElement(in, content));
+		}
+		return new DocumentFragment(content, nodes);
+	}
+
+	private static Content readContent(final ObjectInputStream in) throws IOException {
+		final int contentLength = in.readInt();
+		final Content result = new GapContent(contentLength);
+		for (int i = 0; i < contentLength; i++) {
+			final String input = in.readUTF();
+			if ("\0".equals(input)) { // This internal representation of element markers has nothing to do with the internal representation in GapContent.
+				result.insertElementMarker(i);
+			} else {
+				result.insertText(i, input);
+			}
+		}
+		return result;
+	}
+
+	private static Element readElement(final ObjectInputStream in, final Content content) throws IOException, ClassNotFoundException {
+		final QualifiedName elementName = createQualifiedName(in.readObject());
+		final int startOffset = in.readInt();
+		final int endOffset = in.readInt();
+		final Element element = new Element(elementName);
+		element.associate(content, startOffset, endOffset);
+
+		final int attrCount = in.readInt();
+		for (int i = 0; i < attrCount; i++) {
+			final QualifiedName attributeName = createQualifiedName(in.readObject());
+			final String value = (String) in.readObject();
+			try {
+				element.setAttribute(attributeName, value);
+			} catch (final DocumentValidationException e) {
+				// Should never happen; there ain't no document
+				e.printStackTrace();
+			}
+		}
+
+		final int childCount = in.readInt();
+		for (int i = 0; i < childCount; i++) {
+			final Element child = readElement(in, content);
+			child.setParent(element);
+			element.insertChild(i, child);
+		}
+
+		return element;
+	}
+
+	private static QualifiedName createQualifiedName(final Object object) {
+		final String serializedQualifiedName = object.toString();
+		final int localNameStartIndex = serializedQualifiedName.lastIndexOf(':') + 1;
+		if (localNameStartIndex == 0) {
+			return new QualifiedName(null, serializedQualifiedName);
+		}
+		final String qualifier = serializedQualifiedName.substring(0, localNameStartIndex - 1);
+		final String localName = serializedQualifiedName.substring(localNameStartIndex);
+		return new QualifiedName(qualifier, localName);
+	}
+
 }