Example #1
0
        /// <summary>
        /// Removes duplicate properties in the current object record.
        /// </summary>
        /// <remarks>
        /// This method assumes that we are buffering and that the current buffered node is a StartObject.
        /// It then goes, buffers the entire object record (and all its children) and removes duplicate properties (using the WCF DS Server algorithm).
        /// It will remove duplicate properties on any objects in the subtree of the top-level object as well (behaves recursively).
        /// The method also checks for in-stream errors and throws if it finds one.
        /// </remarks>
        private void RemoveDuplicateProperties()
        {
            Debug.Assert(this.removeDuplicateProperties, "The RemoveDuplicateProperties method should only be called if the removal of duplicate properties is turned on.");
            Debug.Assert(this.currentBufferedNode.NodeType == JsonNodeType.StartObject, "this.currentBufferedNode.NodeType == JsonNodeType.StartObject");
            Debug.Assert(this.parsingInStreamError, "this.parsingInStreamError");
            this.AssertBuffering();

            // Read ahead the entire object and create a map of properties.
            // This will buffer the object record we are on and all its children (the entire subtree).
            // We store a stack, which holds an item for each object record we find.
            // Each item on this stack is a dictionary
            //   - key is the name of the property of a property in the object record
            //   - value is a List<PropertyDeduplicationRecord>, in this list we store a new record
            //     every time we find a property of a given name for the objet record.
            //     This stores pointer to the property node and pointer to the node after the property value.
            Stack <ObjectRecordPropertyDeduplicationRecord> objectRecordStack = new Stack <ObjectRecordPropertyDeduplicationRecord>();

            do
            {
                if (this.currentBufferedNode.NodeType == JsonNodeType.StartObject)
                {
                    // New object record - add the node to our stack
                    objectRecordStack.Push(new ObjectRecordPropertyDeduplicationRecord());

                    // See if it's an in-stream error
                    BufferedNode startObjectPosition = this.currentBufferedNode;
                    this.TryReadErrorAndThrow();
                    this.currentBufferedNode = startObjectPosition;
                }
                else if (this.currentBufferedNode.NodeType == JsonNodeType.EndObject)
                {
                    // End of object record
                    // Pop the node from our stack
                    ObjectRecordPropertyDeduplicationRecord currentObjectRecord = objectRecordStack.Pop();

                    // If there is a current property, mark its last value node.
                    if (currentObjectRecord.CurrentPropertyRecord != null)
                    {
                        currentObjectRecord.CurrentPropertyRecord.LastPropertyValueNode = this.currentBufferedNode.Previous;
                    }

                    // Now walk the list of properties for the object record and deduplicate them
                    foreach (List <PropertyDeduplicationRecord> propertyDeduplicationRecords in currentObjectRecord.Values)
                    {
                        // If there's just one property of this name - there's nothing to do.
                        if (propertyDeduplicationRecords.Count <= 1)
                        {
                            continue;
                        }

                        // Walk all the properties and each time remove the property we find from its current place and move it
                        // inplace of the first property. Note that since the property names are the same we can replace the property node itself
                        // without losing any information.
                        // Once we walk the entire list the outcome will be that we will have just one property of a given name,
                        // it will be in the position of the first property, but it will be the last property value.
                        // We could completely remove the property occurences which are not first or last, but it's easier to move them
                        // to the first one by one as it keeps the algorithm simple (and the performence difference is small enough).
                        PropertyDeduplicationRecord firstProperty = propertyDeduplicationRecords[0];
                        for (int propertyIndex = 1; propertyIndex < propertyDeduplicationRecords.Count; propertyIndex++)
                        {
                            PropertyDeduplicationRecord currentProperty = propertyDeduplicationRecords[propertyIndex];
                            Debug.Assert((string)firstProperty.PropertyNode.Value == (string)currentProperty.PropertyNode.Value, "The property names must be the same.");

                            // Note that property nodes must be preceded at least by the start object node and followed by the end object node
                            // so we don't have to check for end of list here.
                            // Remove the current property from the list
                            currentProperty.PropertyNode.Previous.Next          = currentProperty.LastPropertyValueNode.Next;
                            currentProperty.LastPropertyValueNode.Next.Previous = currentProperty.PropertyNode.Previous;

                            // Now replace the first property with the current property
                            firstProperty.PropertyNode.Previous.Next          = currentProperty.PropertyNode;
                            currentProperty.PropertyNode.Previous             = firstProperty.PropertyNode.Previous;
                            firstProperty.LastPropertyValueNode.Next.Previous = currentProperty.LastPropertyValueNode;
                            currentProperty.LastPropertyValueNode.Next        = firstProperty.LastPropertyValueNode.Next;
                            firstProperty = currentProperty;
                        }
                    }

                    if (objectRecordStack.Count == 0)
                    {
                        break;
                    }
                }
                else if (this.currentBufferedNode.NodeType == JsonNodeType.Property)
                {
                    ObjectRecordPropertyDeduplicationRecord currentObjectRecord = objectRecordStack.Peek();

                    // If there is a previous property record, mark its last value node.
                    if (currentObjectRecord.CurrentPropertyRecord != null)
                    {
                        currentObjectRecord.CurrentPropertyRecord.LastPropertyValueNode = this.currentBufferedNode.Previous;
                    }

                    // Create a new property record for this property node and add it to the object record.
                    currentObjectRecord.CurrentPropertyRecord = new PropertyDeduplicationRecord(this.currentBufferedNode);
                    string propertyName = (string)this.currentBufferedNode.Value;
                    List <PropertyDeduplicationRecord> propertyDeduplicationRecords;
                    if (!currentObjectRecord.TryGetValue(propertyName, out propertyDeduplicationRecords))
                    {
                        propertyDeduplicationRecords = new List <PropertyDeduplicationRecord>();
                        currentObjectRecord.Add(propertyName, propertyDeduplicationRecords);
                    }

                    propertyDeduplicationRecords.Add(currentObjectRecord.CurrentPropertyRecord);
                }
            }while (this.ReadInternal());
        }
Example #2
0
        private void RemoveDuplicateProperties()
        {
            Stack <ObjectRecordPropertyDeduplicationRecord> stack = new Stack <ObjectRecordPropertyDeduplicationRecord>();

            do
            {
                if (this.currentBufferedNode.NodeType == JsonNodeType.StartObject)
                {
                    stack.Push(new ObjectRecordPropertyDeduplicationRecord());
                    BufferedNode currentBufferedNode = this.currentBufferedNode;
                    this.TryReadErrorAndThrow();
                    this.currentBufferedNode = currentBufferedNode;
                }
                else if (this.currentBufferedNode.NodeType == JsonNodeType.EndObject)
                {
                    ObjectRecordPropertyDeduplicationRecord record = stack.Pop();
                    if (record.CurrentPropertyRecord != null)
                    {
                        record.CurrentPropertyRecord.LastPropertyValueNode = this.currentBufferedNode.Previous;
                    }
                    foreach (List <PropertyDeduplicationRecord> list in record.Values)
                    {
                        if (list.Count > 1)
                        {
                            PropertyDeduplicationRecord record2 = list[0];
                            for (int i = 1; i < list.Count; i++)
                            {
                                PropertyDeduplicationRecord record3 = list[i];
                                record3.PropertyNode.Previous.Next          = record3.LastPropertyValueNode.Next;
                                record3.LastPropertyValueNode.Next.Previous = record3.PropertyNode.Previous;
                                record2.PropertyNode.Previous.Next          = record3.PropertyNode;
                                record3.PropertyNode.Previous = record2.PropertyNode.Previous;
                                record2.LastPropertyValueNode.Next.Previous = record3.LastPropertyValueNode;
                                record3.LastPropertyValueNode.Next          = record2.LastPropertyValueNode.Next;
                                record2 = record3;
                            }
                        }
                    }
                    if (stack.Count == 0)
                    {
                        return;
                    }
                }
                else if (this.currentBufferedNode.NodeType == JsonNodeType.Property)
                {
                    List <PropertyDeduplicationRecord>      list2;
                    ObjectRecordPropertyDeduplicationRecord record4 = stack.Peek();
                    if (record4.CurrentPropertyRecord != null)
                    {
                        record4.CurrentPropertyRecord.LastPropertyValueNode = this.currentBufferedNode.Previous;
                    }
                    record4.CurrentPropertyRecord = new PropertyDeduplicationRecord(this.currentBufferedNode);
                    string key = (string)this.currentBufferedNode.Value;
                    if (!record4.TryGetValue(key, out list2))
                    {
                        list2 = new List <PropertyDeduplicationRecord>();
                        record4.Add(key, list2);
                    }
                    list2.Add(record4.CurrentPropertyRecord);
                }
            }while (this.ReadInternal());
        }