public void TestDuplicateRecursive() { Node child = new Node { Key = 17 }; Node parent = new Node { Nodes = new[] { child, child, child } }; child.Nodes = new[] { parent }; VerifyNodeTree(parent); }
// [Test] known variation... public void TestEmptyArray() { Node node = new Node { Key = 27, Nodes = new Node[0] }; VerifyNodeTree(node); }
static bool AreEqual(Node x, Node y, out string msg) { // compare core if (ReferenceEquals(x, y)) { msg = ""; return true; } if (x == null || y == null) { msg = "1 node null"; return false; } if (x.Key != y.Key) { msg = "key"; return false; } Node[] xNodes = x.Nodes, yNodes = y.Nodes; if (ReferenceEquals(xNodes,yNodes)) { // trivial } else { if (xNodes == null || yNodes == null) { msg = "1 Nodes null"; return false; } if (xNodes.Length != yNodes.Length) { msg = "Nodes length"; return false; } for (int i = 0; i < xNodes.Length; i++) { bool eq = AreEqual(xNodes[i], yNodes[i], out msg); if (!eq) { msg = i.ToString() + "; " + msg; return false; } } } // run out of things to be different! msg = ""; return true; }
static void VerifyNodeTree(Node node) { Node clone = Serializer.DeepClone(node); string msg; bool eq = AreEqual(node, clone, out msg); Assert.IsTrue(eq, msg); }
public void TestNestedArray() { Node node = new Node { Key = 27, Nodes = new[] { new Node { Key = 19, Nodes = new[] { new Node {Key = 1}, new Node {Key = 14}, }, }, new Node { Key = 3 }, new Node { Key = 3, Nodes = new[] { new Node {Key = 234} } } } }; VerifyNodeTree(node); }
public void TestNullArray() { Node node = new Node { Key = 27, Nodes = null }; VerifyNodeTree(node); }
public void TestObjectArray() { Node node = new Node { Key = 27, Nodes = new[] { new Node { Key = 1 }, new Node { Key = 3 } } }; VerifyNodeTree(node); }
/// <summary> /// Removes nodes from start up to but not including the end node. /// Start and end are assumed to have the same parent. /// </summary> private static void RemoveSameParent(Node startNode, Node endNode) { if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode)) throw new ArgumentException("Start and end nodes are expected to have the same parent."); Node curChild = startNode; while ((curChild != null) && (curChild != endNode)) { Node nextChild = curChild.NextSibling; curChild.Remove(); curChild = nextChild; } }
/// <summary> /// Retrieves text from start up to but not including the end node. /// </summary> private static string GetTextSameParent(Node startNode, Node endNode) { if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode)) throw new ArgumentException("Start and end nodes are expected to have the same parent."); StringBuilder builder = new StringBuilder(); for (Node child = startNode; !child.Equals(endNode); child = child.NextSibling) builder.Append(child.GetText()); return builder.ToString(); }
/// <summary> /// Goes through siblings starting from the start node until it finds a node of the specified type or null. /// </summary> private static Node FindNextSibling(Node startNode, NodeType nodeType) { for (Node node = startNode; node != null; node = node.NextSibling) { if (node.NodeType.Equals(nodeType)) return node; } return null; }
internal Hyperlink(FieldStart fieldStart) { if (fieldStart == null) throw new ArgumentNullException("fieldStart"); if (!fieldStart.FieldType.Equals(FieldType.FieldHyperlink)) throw new ArgumentException("Field start type must be FieldHyperlink."); mFieldStart = fieldStart; // Find the field separator node. mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator); if (mFieldSeparator == null) throw new InvalidOperationException("Cannot find field separator."); // Find the field end node. Normally field end will always be found, but in the example document // there happens to be a paragraph break included in the hyperlink and this puts the field end // in the next paragraph. It will be much more complicated to handle fields which span several // paragraphs correctly, but in this case allowing field end to be null is enough for our purposes. mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd); // Field code looks something like [ HYPERLINK "http:\\www.myurl.com" ], but it can consist of several runs. string fieldCode = GetTextSameParent(mFieldStart.NextSibling, mFieldSeparator); Match match = gRegex.Match(fieldCode.Trim()); mIsLocal = (match.Groups[1].Length > 0); //The link is local if \l is present in the field code. mTarget = match.Groups[2].Value; }
internal MergeField(FieldStart fieldStart) { if (fieldStart.Equals(null)) throw new ArgumentNullException("fieldStart"); if (!fieldStart.FieldType.Equals(FieldType.FieldMergeField)) throw new ArgumentException("Field start type must be FieldMergeField."); mFieldStart = fieldStart; // Find the field separator node. mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator); if (mFieldSeparator == null) throw new InvalidOperationException("Cannot find field separator."); // Find the field end node. Normally field end will always be found, but in the example document // there happens to be a paragraph break included in the hyperlink and this puts the field end // in the next paragraph. It will be much more complicated to handle fields which span several // paragraphs correctly, but in this case allowing field end to be null is enough for our purposes. mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd); }
public void TestDuplicateRecursive() { try { Node child = new Node { Key = 17 }; Node parent = new Node { Nodes = new[] { child, child, child } }; child.Nodes = new[] { parent }; VerifyNodeTree(parent); Assert.Fail(); } catch (ProtoException) { } }
//ExStart //ExFor:Paragraph.IsEndOfSection //ExId:InsertDocumentMain //ExSummary:This is a method that inserts contents of one document at a specified location in another document. /// <summary> /// Inserts content of the external document after the specified node. /// Section breaks and section formatting of the inserted document are ignored. /// </summary> /// <param name="insertAfterNode">Node in the destination document after which the content /// should be inserted. This node should be a block level node (paragraph or table).</param> /// <param name="srcDoc">The document to insert.</param> static void InsertDocument(Node insertAfterNode, Document srcDoc) { // Make sure that the node is either a paragraph or table. if ((!insertAfterNode.NodeType.Equals(NodeType.Paragraph)) & (!insertAfterNode.NodeType.Equals(NodeType.Table))) throw new ArgumentException("The destination node should be either a paragraph or table."); // We will be inserting into the parent of the destination paragraph. CompositeNode dstStory = insertAfterNode.ParentNode; // This object will be translating styles and lists during the import. NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.Document, ImportFormatMode.KeepSourceFormatting); // Loop through all sections in the source document. foreach (Section srcSection in srcDoc.Sections) { // Loop through all block level nodes (paragraphs and tables) in the body of the section. foreach (Node srcNode in srcSection.Body) { // Let's skip the node if it is a last empty paragraph in a section. if (srcNode.NodeType.Equals(NodeType.Paragraph)) { Paragraph para = (Paragraph)srcNode; if (para.IsEndOfSection && !para.HasChildNodes) continue; } // This creates a clone of the node, suitable for insertion into the destination document. Node newNode = importer.ImportNode(srcNode, true); // Insert new node after the reference node. dstStory.InsertAfter(newNode, insertAfterNode); insertAfterNode = newNode; } } }