예제 #1
0
        /// <summary>
        /// Find the matching context path that results in a single field.
        /// </summary>
        protected ContextValue CreateContextValue(Parser parser, string val, int recordNumber, params Type[] types)
        {
            ContextValue cv = parser.CreateContextValue(val, recordNumber, types);

            AddOrUpdate(cv);

            return(cv);
        }
예제 #2
0
        protected ContextNode CreateNode(int i, Guid id, ContextValue cv, ContextNode node, Type type)
        {
            if (i == cv.TypePath.Count - 1)
            {
                // At this point, node.Children[].Type && node.Children[].ContextValue.RecordNumber must be unique!
                Assert.That <ContextValueDictionaryException>(!node.Children.Any(c => c.Type == type && c.ContextValue.RecordNumber == cv.RecordNumber), "ContextValue type and record number must be unique to parent context.");
            }

            ContextNode childNode = new ContextNode(id, type);

            node.AddChild(childNode);

            // Since we're creating a node, add it to the flat tree view.
            if (!flatView.TryGetValue(type, out List <ContextNode> nodes))
            {
                flatView[type] = new List <ContextNode>();
            }

            flatView[type].Add(childNode);

            return(childNode);
        }
예제 #3
0
        public ContextValue CreateContextValue(string val, int recordNumber, params Type[] types)
        {
            Assert.That(types.Last().HasInterface <IValueEntity>(), "The last type in the context path must implement the IValueEntity interface.");

            // Clone the working list.
            List <FieldContextPath> matchingFieldPaths = new List <FieldContextPath>(fieldContextPaths);
            int n = 0;

            foreach (Type type in types)
            {
                // Reduce the working list down to only the matches.
                matchingFieldPaths = new List <FieldContextPath>(matchingFieldPaths.Where(fcp => fcp.Path[n].Type == type));
                ++n;
            }

            Assert.That(matchingFieldPaths.Count == 1, "Expected a single matching field to remain.");

            List <Guid>  instancePath = CreateInstancePath(types);
            ContextValue cv           = matchingFieldPaths[0].Field.CreateValue(val, instancePath);

            cv.RecordNumber = recordNumber;

            return(cv);
        }
예제 #4
0
        public void AddOrUpdate(ContextValue cv)
        {
            // We have to process this synchronously!
            // If async, we might get simultaneous requests (particularly from the browser's async PUT calls) to add a value.
            // While we're constructing the dictionary entry for one context path, another request might come in before we've
            // created all the nodes for the first call.
            lock (this)
            {
                // Walk the instance/path, creating new nodes in the context tree as required.

                Assert.That(cv.TypePath.Count == cv.InstancePath.Count, "type path and instance path should have the same number of entries.");
                ContextNode node = tree;

                for (int i = 0; i < cv.TypePath.Count; i++)
                {
                    // Walk the tree.
                    var(id, type) = (cv.InstancePath[i], cv.TypePath[i]);

                    if (node.Children.TryGetSingle(c => c.InstanceId == id, out ContextNode childNode))
                    {
                        node = childNode;
                    }
                    else
                    {
                        // Are we referencing an existing sub-context?
                        if (flatView.TryGetValue(type, out List <ContextNode> nodes))
                        {
                            // The instance path of the node must match all the remaining instance paths in the context
                            // we're adding/updating!
                            bool foundExistingSubContext = false;

                            foreach (var fvnode in nodes)
                            {
                                foreach (var fvnodepath in fvnode.ChildInstancePaths())
                                {
                                    if (cv.InstancePath.Skip(i).SequenceEqual(fvnodepath))
                                    {
                                        // This node get's a child referencing the existing sub-context node.
                                        node.AddChild(fvnode);
                                        node = fvnode;
                                        foundExistingSubContext = true;
                                        break;
                                    }
                                }

                                if (foundExistingSubContext)
                                {
                                    break;
                                }
                            }

                            if (!foundExistingSubContext)
                            {
                                node = CreateNode(i, id, cv, node, type);
                            }
                        }
                        else
                        {
                            node = CreateNode(i, id, cv, node, type);
                        }
                    }
                }

                // The last entry in the tree gets the actual context value.  We've either added this node to the tree
                // or updating an existing node.
                node.ContextValue = cv;
            }
        }