platform35/org.eclipse.core.resources/src/org/eclipse/core/internal/dtree/DataTreeWriter.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/platform35/org.eclipse.core.resources/src/org/eclipse/core/internal/dtree/DataTreeWriter.java Thu Jul 30 11:56:23 2009 -0500
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.internal.dtree;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import org.eclipse.core.runtime.*;
+
+/**
+ * Class for writing a single data tree (no parents) to an output stream.
+ */
+public class DataTreeWriter {
+ /**
+ * Callback for serializing tree data
+ */
+ protected IDataFlattener flatener;
+
+ /**
+ * The stream to write output to
+ */
+ protected DataOutput output;
+
+ /**
+ * Constant representing infinite recursion depth
+ */
+ public static final int D_INFINITE = -1;
+
+ /**
+ * Creates a new DeltaTreeWriter.
+ */
+ public DataTreeWriter(IDataFlattener f) {
+ flatener = f;
+ }
+
+ /**
+ * Writes the subtree rooted at the given node.
+ * @param node The subtree to write.
+ * @param path The path of the current node.
+ * @param depth The depth of the subtree to write.
+ */
+ protected void writeNode(AbstractDataTreeNode node, IPath path, int depth) throws IOException {
+ int type = node.type();
+
+ /* write the node name */
+ String name = node.getName();
+ if (name == null) {
+ name = ""; //$NON-NLS-1$
+ }
+ output.writeUTF(name);
+
+ /* write the node type */
+ writeNumber(type);
+
+ /* maybe write the data */
+ if (node.hasData()) {
+ Object data = node.getData();
+
+ /**
+ * Write a flag indicating whether or not the data field is null.
+ * Zero means data is null, non-zero means data is present
+ */
+ if (data == null) {
+ writeNumber(0);
+ } else {
+ writeNumber(1);
+ flatener.writeData(path, node.getData(), output);
+ }
+
+ }
+
+ /* maybe write the children */
+ if (depth > 0 || depth == D_INFINITE) {
+ AbstractDataTreeNode[] children = node.getChildren();
+
+ /* write the number of children */
+ writeNumber(children.length);
+
+ /* write the children */
+ int newDepth = (depth == D_INFINITE) ? D_INFINITE : depth - 1;
+ for (int i = 0, imax = children.length; i < imax; i++) {
+ writeNode(children[i], path.append(children[i].getName()), newDepth);
+ }
+ } else {
+ /* write the number of children */
+ writeNumber(0);
+ }
+ }
+
+ /**
+ * Writes an integer in a compact format biased towards
+ * small non-negative numbers. Numbers between
+ * 0 and 254 inclusive occupy 1 byte; other numbers occupy 5 bytes.
+ */
+ protected void writeNumber(int number) throws IOException {
+ if (number >= 0 && number < 0xff) {
+ output.writeByte(number);
+ } else {
+ output.writeByte(0xff);
+ output.writeInt(number);
+ }
+ }
+
+ /**
+ * Writes a single node to the output. Does not recurse
+ * on child nodes, and does not write the number of children.
+ */
+ protected void writeSingleNode(AbstractDataTreeNode node, IPath path) throws IOException {
+ /* write the node name */
+ String name = node.getName();
+ if (name == null) {
+ name = ""; //$NON-NLS-1$
+ }
+ output.writeUTF(name);
+
+ /* write the node type */
+ writeNumber(node.type());
+
+ /* maybe write the data */
+ if (node.hasData()) {
+ Object data = node.getData();
+
+ /**
+ * Write a flag indicating whether or not the data field is null.
+ * Zero means data is null, non-zero means data is present
+ */
+ if (data == null) {
+ writeNumber(0);
+ } else {
+ writeNumber(1);
+ flatener.writeData(path, node.getData(), output);
+ }
+ }
+ }
+
+ /**
+ * Writes the given AbstractDataTree to the given stream. This
+ * writes a single DataTree or DeltaDataTree, ignoring parent
+ * trees.
+ *
+ * @param path Only writes data for the subtree rooted at the given path, and
+ * for all nodes directly between the root and the subtree.
+ * @param depth In the subtree rooted at the given path,
+ * only write up to this depth. A depth of infinity is given
+ * by the constant D_INFINITE.
+ */
+ public void writeTree(AbstractDataTree tree, IPath path, int depth, DataOutput output) throws IOException {
+ this.output = output;
+ /* tunnel down relevant path */
+ AbstractDataTreeNode node = tree.getRootNode();
+ IPath currentPath = Path.ROOT;
+ String[] segments = path.segments();
+ for (int i = 0; i < segments.length; i++) {
+ String nextSegment = segments[i];
+
+ /* write this node to the output */
+ writeSingleNode(node, currentPath);
+
+ currentPath = currentPath.append(nextSegment);
+ node = node.childAtOrNull(nextSegment);
+
+ /* write the number of children for this node */
+ if (node != null) {
+ writeNumber(1);
+ } else {
+ /* can't navigate down the path, just give up with what we have so far */
+ writeNumber(0);
+ return;
+ }
+ }
+
+ Assert.isTrue(currentPath.equals(path), "dtree.navigationError"); //$NON-NLS-1$
+
+ /* recursively write the subtree we're interested in */
+ writeNode(node, path, depth);
+ }
+}