예제 #1
0
 /// <inheritdoc />
 protected override void SerializeInto(SerializeNode node)
 {
     foreach (var child in Children)
     {
         node.Children.Add(child.Serialize());
     }
 }
예제 #2
0
        /// <summary> Finds the first difference in the two documents. </summary>
        private static void FindDifference(SerializeNode currentState, SerializeNode originalState, string path)
        {
            DidYouKnow.That(currentState.TypeId).Should()
            .Be(originalState.TypeId);

            var type = currentState.TypeId;

            path += "<" + type + ">";

            var fullPath = path + ".Data";

            DidYouKnow.That(currentState.GetDataOrDefault <string>("Body")).Should()
            .Be(originalState.GetDataOrDefault <string>("Body"));

            int max = Math.Min(currentState.Children.Count, originalState.Children.Count);

            for (int i = 0; i < max; i++)
            {
                FindDifference(currentState.Children[i], originalState.Children[i], path + ".[" + i + "]");
            }

            var theFullPath = path + ".Count";

            DidYouKnow.That(currentState.Children.Count).Should().Be(originalState.Children.Count);
        }
예제 #3
0
        /// <summary>
        /// Populates already <see cref="Construct(SerializeNode)"/>-ed <see cref="SerializeNode"/>s using the available <see cref="Consumers"/>, from the bottom of the graph upwards.
        /// </summary>
        /// <param name="startNode"></param>
        private void Populate(SerializeNode startNode)
        {
            if (!populating.Contains(startNode))
            {
                try
                {
                    populating.Add(startNode);
                    if (dependencyMap.ContainsKey(startNode) &&
                        dependencyMap[startNode].Any())
                    {
                        foreach (var dep in dependencyMap[startNode])
                        {
                            Populate(dep.EndNode);
                        }

                        //// Populate all remaining dependencies.
                        Consumers.PopulateObject(
                            startNode.Value,
                            dependencyMap[startNode].ToDictionary(d => d.DependencyId, d => d.EndNode.Value));

                        dependencyMap[startNode].Clear();
                    }
                }
                catch (Exception ex)
                {
                    throw new SerializationException($"Populating {GetPath(startNode)} failed.", ex);
                }
            }
        }
예제 #4
0
        /// <summary> Serializes the given block into a SerializedNode. </summary>
        /// <returns> A SerializeNode that represents the contents in the given block. </returns>
        public SerializeNode Serialize()
        {
            var node = new SerializeNode(DescriptorHandle);

            SerializeInto(node);
            return(node);
        }
        public SerializeNode SerializeAsNode()
        {
            var node = new SerializeNode("temp/document");

            node.Children.Add(Root.Serialize());

            return(node);
        }
예제 #6
0
 /// <summary>
 /// Constructs and populates new <see cref="object"/>s in <see cref="CurrentGraph"/> to match its structure and dependencies.
 /// </summary>
 /// <param name="root">The root object in the graph, which is currently being deserialized.</param>
 /// <returns>The final <see cref="object"/> value stored in the <paramref name="root"/> node.</returns>
 private object ReadGraph(SerializeNode root)
 {
     dependencyMap = new Dictionary <SerializeNode, List <SerializeDependency> >();
     constructed   = new HashSet <SerializeNode>();
     populating    = new HashSet <SerializeNode>();
     Construct(root);
     Populate(root);
     return(root.Value);
 }
예제 #7
0
        /// <summary> Converts a SerializeNode into an XElement </summary>
        public static XElement Serialize(SerializeNode node)
        {
            var childNodes     = node.Children.Select(Serialize);
            var attributeNodes = node.Attributes.Select(kvp => new XElement(AttributeElementName,
                                                                            new XAttribute(KeyAttributeName, kvp.Key),
                                                                            new XAttribute(ValueAttributeName, kvp.Value)));
            var root = new XElement(NodeElementName,
                                    childNodes,
                                    attributeNodes,
                                    new XAttribute(TypeIdAttributeName, node.TypeId));

            return(root);
        }
예제 #8
0
        /// <inheritdoc />
        public override void Deserialize(SerializationContext context, SerializeNode node)
        {
            var originalFirst = FirstBlock;
            var originalLast  = LastBlock;

            foreach (var nodeChild in node.Children)
            {
                var childBlock = context.Deserialize(nodeChild);
                Append(childBlock);
            }

            // remove all blocks that used to exist before
            foreach (var block in GetBlocksBetweenInclusive(originalFirst, originalLast))
            {
                RemoveBlock(block);
            }
        }
예제 #9
0
        /// <summary>
        /// Adds an <see cref="object"/> and its dependencies to the <see cref="CurrentGraph"/>.
        /// </summary>
        /// <param name="value">The <see cref="object"/> to add.</param>
        /// <returns>The created <see cref="SerializeNode"/> representing <paramref name="value"/>.</returns>
        private SerializeNode GetNode(object value)
        {
            if (value != null && !TypeConfiguration.MatchAny().Match(value?.GetType()))
            {
                throw new TypeMatchException(TypeConfiguration.MatchAny(), value?.GetType());
            }

            var existing = CurrentGraph.Nodes.FirstOrDefault(n => object.ReferenceEquals(n.Value, value));

            if (existing != null)
            {
                //// Existing nodes should be reused.
                return(existing);
            }
            else
            {
                var node = new SerializeNode(currentId.ToString(), value);
                currentId++;

                //// Adds the newly-created node to the graph.
                CurrentGraph.AddNode(node);

                //// Check if dependencies need to be resolved or if the value is native/null.
                if (value != null && !TypeConfiguration.MatchNative().Match(value.GetType()))
                {
                    //// Get all of the dependencies as connections (unique for each individual node, so can construct them here).
                    var dependencies = Providers.GetDependencies(value)
                                       .Select(p => new SerializeDependency(p.Key, node, GetNode(p.Value)));

                    foreach (var dep in dependencies)
                    {
                        //// Add new dependencies to the graph.
                        CurrentGraph.AddConnection(dep);
                    }
                }
                else
                {
                    node.IsNative = true;
                }

                return(node);
            }
        }
예제 #10
0
        private SerializeNode ReadNode(JObject node, string[] assemblyNames)
        {
            Type type = null;

            if (node["type"].Type == JTokenType.Object)
            {
                type = ResolveType((JObject)node["type"], assemblyNames);
            }
            var nodeObj = new SerializeNode((string)node["id"], type);

            if (node.ContainsKey("value"))
            {
                nodeObj.Value    = node["value"];
                nodeObj.IsNative = true;
            }
            else
            {
                nodeObj.Value    = null;
                nodeObj.IsNative = false;
            }

            return(nodeObj);
        }
예제 #11
0
        private JObject WriteNode(SerializeNode node, IList <Assembly> assemblies)
        {
            JObject typeJson = null;

            if (node.DesiredType != null)
            {
                typeJson = GetType(node.DesiredType, assemblies);
            }

            if (node.IsNative)
            {
                return(new JObject(
                           new JProperty("id", node.Id),
                           new JProperty("type", typeJson),
                           new JProperty("value", node.Value)));
            }
            else
            {
                return(new JObject(
                           new JProperty("id", node.Id),
                           new JProperty("type", typeJson)));
            }
        }
예제 #12
0
        /// <summary> Converts the XElement into a SerializeNode </summary>
        public static SerializeNode Deserialize(XElement root)
        {
            // ReSharper disable PossibleNullReferenceException
            var typeId = root.Attribute(TypeIdAttributeName).Value;

            var node = new SerializeNode(typeId);

            // recreate each element
            foreach (var attributeElement in root.Elements(AttributeElementName))
            {
                node.AddData(attributeElement.Attribute(KeyAttributeName).Value,
                             attributeElement.Attribute(ValueAttributeName).Value);
            }

            // recreate each block
            foreach (var childElement in root.Elements(NodeElementName))
            {
                node.Children.Add(Deserialize(childElement));
            }

            return(node);
            // ReSharper restore PossibleNullReferenceException
        }
예제 #13
0
        private string GetPath(SerializeNode node)
        {
            var path = CurrentGraph.FindPath(CurrentGraph.Nodes[0], node);

            return($"{{Root}}.{string.Join(".", path.Connections.Select(c => c.DependencyId))}");
        }
예제 #14
0
        private static void SerializeWithSaveOptions(SerializeNode serialize, bool testXElement, bool testXDocument)
        {
            // Test both options at once as they don't really collide
            SaveOptions so = SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces;

            XElement root = XElement.Parse("<root xmlns:a='uri'><child xmlns:a='uri'><baby xmlns:a='uri'>text</baby></child></root>");
            XElement child = root.Element("child");
            XElement baby = child.Element("baby");
            XNode text = baby.FirstNode;

            // Verify that without annotation the output gets indented and the duplicate ns decls are not removed
            if (testXElement)
            {
                Assert.Equal(NormalizeNewLines(serialize(child)), "<child xmlns:a=\"uri\">  <baby xmlns:a=\"uri\">text</baby></child>");
            }

            // Now add annotation to the leaf element node
            // Even though it's in effect the output should stay the same (as there is only one namespace decl and mixed content).
            baby.AddAnnotation(so);

            if (testXElement)
            {
                Assert.Equal(serialize(baby), "<baby xmlns:a=\"uri\">text</baby>");
            }

            // Now add annotation to the middle node
            child.AddAnnotation(so);

            if (testXElement)
            {
                // Verify that the options are applied correctly
                Assert.Equal(NormalizeNewLines(serialize(child)), "<child xmlns:a=\"uri\"><baby>text</baby></child>");
                // Verify that the root node is not affected as we don't look for the annotation among descendants
                Assert.Equal(NormalizeNewLines(serialize(root)), "<root xmlns:a=\"uri\">  <child xmlns:a=\"uri\">    <baby xmlns:a=\"uri\">text</baby>  </child></root>");
            }

            // And now add the annotation to the root and remove it from the child to test that we can correctly skip over a node
            root.AddAnnotation(so);
            child.RemoveAnnotations(typeof(SaveOptions));

            if (testXElement)
            {
                // Verify that the options are still applied to child
                Assert.Equal(serialize(child), "<child xmlns:a=\"uri\"><baby>text</baby></child>");
                // And they should be also applied to the root now
                Assert.Equal(serialize(root), "<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>");
            }

            // Add a document node above it all to test that it works on non-XElement as well
            XDocument doc = new XDocument(root);
            // Add the annotation to the doc and remove it from the root
            doc.AddAnnotation(so);
            root.RemoveAnnotations(typeof(SaveOptions));

            // Options should still apply to root as well as the doc
            if (testXElement)
            {
                Assert.Equal(serialize(root), "<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>");
            }

            if (testXDocument)
            {
                Assert.Equal(serialize(doc), "<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>");
            }
        }
        private static void SerializeWithSaveOptions(SerializeNode serialize, bool testXElement, bool testXDocument)
        {
            // Test both options at once as they don't really collide
            SaveOptions so = SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces;

            XElement root  = XElement.Parse("<root xmlns:a='uri'><child xmlns:a='uri'><baby xmlns:a='uri'>text</baby></child></root>");
            XElement child = root.Element("child");
            XElement baby  = child.Element("baby");
            XNode    text  = baby.FirstNode;

            // Verify that without annotation the output gets indented and the duplicate ns decls are not removed
            if (testXElement)
            {
                Assert.Equal("<child xmlns:a=\"uri\">  <baby xmlns:a=\"uri\">text</baby></child>", NormalizeNewLines(serialize(child)));
            }

            // Now add annotation to the leaf element node
            // Even though it's in effect the output should stay the same (as there is only one namespace decl and mixed content).
            baby.AddAnnotation(so);

            if (testXElement)
            {
                Assert.Equal("<baby xmlns:a=\"uri\">text</baby>", serialize(baby));
            }

            // Now add annotation to the middle node
            child.AddAnnotation(so);

            if (testXElement)
            {
                // Verify that the options are applied correctly
                Assert.Equal("<child xmlns:a=\"uri\"><baby>text</baby></child>", NormalizeNewLines(serialize(child)));
                // Verify that the root node is not affected as we don't look for the annotation among descendants
                Assert.Equal("<root xmlns:a=\"uri\">  <child xmlns:a=\"uri\">    <baby xmlns:a=\"uri\">text</baby>  </child></root>", NormalizeNewLines(serialize(root)));
            }

            // And now add the annotation to the root and remove it from the child to test that we can correctly skip over a node
            root.AddAnnotation(so);
            child.RemoveAnnotations(typeof(SaveOptions));

            if (testXElement)
            {
                // Verify that the options are still applied to child
                Assert.Equal("<child xmlns:a=\"uri\"><baby>text</baby></child>", serialize(child));
                // And they should be also applied to the root now
                Assert.Equal("<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>", serialize(root));
            }

            // Add a document node above it all to test that it works on non-XElement as well
            XDocument doc = new XDocument(root);

            // Add the annotation to the doc and remove it from the root
            doc.AddAnnotation(so);
            root.RemoveAnnotations(typeof(SaveOptions));

            // Options should still apply to root as well as the doc
            if (testXElement)
            {
                Assert.Equal("<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>", serialize(root));
            }

            if (testXDocument)
            {
                Assert.Equal("<root xmlns:a=\"uri\"><child><baby>text</baby></child></root>", serialize(doc));
            }
        }
예제 #16
0
 /// <summary> Loads the state from <paramref name="node"/> into the current instance. </summary>
 /// <param name="context"> The context in which the node is being deserialized. </param>
 /// <param name="node"> The node that contains the data that should be loaded into this block. </param>
 public abstract void Deserialize(SerializationContext context, SerializeNode node);
예제 #17
0
    public void OnBeforeSerialize()
    {
        // not created
        if (nodes == null)
        {
            return;
        }

        var nodeIndexLookup = new Dictionary <Node, int>();
        var edgeIndexLookup = new Dictionary <Edge, int>();

        for (int i = 0; i < nodes.Count; ++i)
        {
            nodeIndexLookup.Add(nodes[i], i);
        }
        for (int i = 0; i < edges.Count; ++i)
        {
            edgeIndexLookup.Add(edges[i], i);
        }

        serializeNodes = new List <SerializeNode>();

        foreach (var node in nodes)
        {
            var serializeNode = new SerializeNode();

#if UNITY_EDITOR
            serializeNode.label = node.label;
#endif

            serializeNode.type = 0;
            if ((node as InputNode) != null)
            {
                serializeNode.type = 1;
            }
            if ((node as OutputNode) != null)
            {
                serializeNode.type = 2;
            }

            serializeNode.sum = node.sum;

            serializeNode.edgeIndices = new List <int>();
            foreach (var edge in node.edges)
            {
                var index = edgeIndexLookup[edge];
                serializeNode.edgeIndices.Add(index);
            }

            serializeNodes.Add(serializeNode);
        }

        serializeEdges = new List <SerializeEdge>();

        foreach (var edge in edges)
        {
            var serializeEdge = new SerializeEdge();

#if UNITY_EDITOR
            serializeEdge.label = edge.label;
#endif
            serializeEdge.srcIndex = nodeIndexLookup[edge.src];
            serializeEdge.dstIndex = nodeIndexLookup[edge.dst];
            serializeEdge.a        = edge.a;
            serializeEdge.b        = edge.b;
            serializeEdge.c        = edge.c;

            serializeEdges.Add(serializeEdge);
        }
    }
예제 #18
0
 /// <summary />
 public void SerializeInto(SerializeNode node)
 {
     node.AddData("Body", _buffer.GetText());
 }
예제 #19
0
        /// <summary />
        public void Deserialize(SerializationContext context, SerializeNode node)
        {
            var text = node.GetDataOrDefault <string>("Body");

            Insert(GetCaretAtStart(), new TextBlockContent(text), autoMerge: false);
        }
예제 #20
0
        /// <summary>
        /// Constructs new instances of the object tree starting at the given <see cref="SerializeNode"/>, passing constructor parameters greedily where possible.
        /// </summary>
        /// <param name="startNode">The <see cref="SerializeNode"/> to start construction at.</param>
        private void Construct(SerializeNode startNode)
        {
            if (!constructed.Contains(startNode))
            {
                try
                {
                    if (startNode.IsNative)
                    {
                        //// Test only against native trusted types.
                        if (startNode.DesiredType != null &&
                            !TypeConfiguration.MatchNative().Match(startNode.DesiredType))
                        {
                            throw new TypeMatchException(TypeConfiguration.MatchNative(), startNode.DesiredType?.GetType());
                        }

                        if (startNode.Value is JToken token)
                        {
                            if (token.Type == JTokenType.Null)
                            {
                                startNode.Value = null;
                            }
                            else
                            {
                                startNode.Value = token.ToObject(startNode.DesiredType);
                            }
                            constructed.Add(startNode);
                        }
                        else
                        {
                            throw new SerializationException("Native object not encapsulated in expected JToken value.");
                        }
                    }
                    else
                    {
                        //// Test only against non-native trusted types.
                        if (!TypeConfiguration.MatchTrusted().Match(startNode.DesiredType))
                        {
                            throw new TypeMatchException(TypeConfiguration.MatchTrusted(), startNode.DesiredType?.GetType());
                        }

                        //// Get all dependencies.
                        var dependencies = CurrentGraph.GetConnections(startNode);
                        dependencyMap.Add(startNode, new List <SerializeDependency>(dependencies));

                        //// Construct an object with non-circular dependencies.
                        object newValue = Constructors.Construct(
                            startNode.DesiredType,
                            dependencies
                            .Where(d => !IsCircular(d))
                            .ToDictionary(
                                d => d.DependencyId,
                                d =>
                        {
                            Construct(d.EndNode);
                            Populate(d.EndNode);
                            return(d.EndNode.Value);
                        }),
                            out var usedKeys);
                        dependencyMap[startNode].RemoveRange(
                            dependencyMap[startNode].ToArray()
                            .Where(d => usedKeys.Contains(d.DependencyId)));
                        startNode.Value = newValue;
                        constructed.Add(startNode);

                        foreach (var dep in dependencyMap[startNode])
                        {
                            Construct(dep.EndNode);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new SerializationException($"Constructing {GetPath(startNode)} failed.", ex);
                }
            }
        }
예제 #21
0
 /// <summary> Saves the state of the current instance into <paramref name="node"/>. </summary>
 /// <param name="node"> The node into which the state of this block should be stored. </param>
 protected abstract void SerializeInto(SerializeNode node);