/// <summary>
        /// Asynchronously reads data into the current
        /// <see cref="SearchResultStream"/>.
        /// </summary>
        /// <param name="reader">
        /// The <see cref="XmlReader"/> from which to read.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> representing the operation.
        /// </returns>
        public async Task ReadXmlAsync(XmlReader reader)
        {
            var fieldNames = new List<string>();

            this.FieldNames = new ReadOnlyCollection<string>(fieldNames);
            this.IsFinal = true;

            if (!await reader.MoveToDocumentElementAsync("results").ConfigureAwait(false))
            {
                return;
            }

            string preview = reader.GetRequiredAttribute("preview");
            this.IsFinal = !BooleanConverter.Instance.Convert(preview);

            if (!await reader.ReadAsync().ConfigureAwait(false))
            {
                return;
            }

            reader.EnsureMarkup(XmlNodeType.Element, "meta");
            await reader.ReadAsync().ConfigureAwait(false);
            reader.EnsureMarkup(XmlNodeType.Element, "fieldOrder");

            if (!reader.IsEmptyElement)
            {
                await reader.ReadEachDescendantAsync("field", async (r) =>
                {
                    await r.ReadAsync().ConfigureAwait(false);
                    var fieldName = await r.ReadContentAsStringAsync().ConfigureAwait(false);
                    fieldNames.Add(fieldName);
                }).ConfigureAwait(false);

                await reader.ReadEndElementSequenceAsync("fieldOrder", "meta").ConfigureAwait(false);
            }

            if (reader.NodeType == XmlNodeType.Element && reader.Name == "messages")
            {
                //// Skip messages

                await reader.ReadEachDescendantAsync("msg", (r) =>
                {
                    return Task.FromResult(true);
                }).ConfigureAwait(false);

                reader.EnsureMarkup(XmlNodeType.EndElement, "messages");
                await reader.ReadAsync().ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Asynchronously reads data into the current <see cref="SearchResult"/>.
        /// </summary>
        /// <param name="reader">
        /// The <see cref="XmlReader"/> from which to read.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> representing the operation.
        /// </returns>
        public async Task ReadXmlAsync(XmlReader reader)
        {
            Contract.Requires<ArgumentNullException>(reader != null, "reader");

            reader.MoveToElement();
            reader.EnsureMarkup(XmlNodeType.Element, "result");

            this.Object = new ExpandoObject();
            var dictionary = (IDictionary<string, object>)this.Object;

            this.SegmentedRaw = null;

            await reader.ReadEachDescendantAsync("field", async (r) =>
            {
                var key = r.GetRequiredAttribute("k");
                var values = new List<string>();
                var fieldDepth = r.Depth;

                while (await r.ReadAsync().ConfigureAwait(false))
                {
                    if (r.Depth == fieldDepth)
                    {
                        break;
                    }

                    Debug.Assert(r.Depth > fieldDepth, "This loop should have exited earlier.");
                    r.EnsureMarkup(XmlNodeType.Element, "value", "v");

                    if (r.Name == "value")
                    {
                        if (await r.ReadToDescendantAsync("text").ConfigureAwait(false))
                        {
                            values.Add(await r.ReadElementContentAsStringAsync().ConfigureAwait(false));
                        }
                    }
                    else if (r.Name == "v")
                    {
                        Debug.Assert(this.SegmentedRaw == null);
                        Debug.Assert(key == "_raw");

                        string value = await r.ReadOuterXmlAsync().ConfigureAwait(false);
                        this.SegmentedRaw = XElement.Parse(value);
                        values.Add(this.SegmentedRaw.Value);
                    }
                }

                switch (values.Count)
                {
                    case 0: 
                        dictionary.Add(key, null);
                        break;
                    case 1:
                        dictionary.Add(key, values[0]);
                        break;
                    default:
                        dictionary.Add(key, new ReadOnlyCollection<string>(values));
                        break;
                }
            }).ConfigureAwait(false);
        }
Example #3
0
        /// <summary>
        /// Asynchronously reads data into the current <see cref="SearchResult"/>.
        /// </summary>
        /// <param name="reader">
        /// The <see cref="XmlReader"/> from which to read.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> representing the operation.
        /// </returns>
        public async Task ReadXmlAsync(XmlReader reader)
        {
            Contract.Requires<ArgumentNullException>(reader != null, "reader");

            reader.MoveToElement();
            reader.EnsureMarkup(XmlNodeType.Element, "result");

            this.Object = new ExpandoObject();
            var dictionary = (IDictionary<string, object>)this.Object;

            this.tagsObject = new ExpandoObject();
            var tagsDictionary = (IDictionary<string, object>)this.tagsObject;

            this.SegmentedRaw = null;

            await reader.ReadEachDescendantAsync("field", async (r) =>
            {
                ImmutableSortedSet<string>.Builder tags = null;

                var key = r.GetRequiredAttribute("k");
                var values = new List<object>();

                var fieldDepth = r.Depth;

                while (await r.ReadAsync().ConfigureAwait(false))
                {
                    if (r.Depth == fieldDepth)
                    {
                        break;
                    }

                    Debug.Assert(r.Depth > fieldDepth, "This loop should have exited earlier.");
                    r.EnsureMarkup(XmlNodeType.Element, "value", "v");

                    if (r.Name == "value")
                    {
                        string value = null;

                        while (await r.ReadAsync().ConfigureAwait(false))
                        {
                            if (r.NodeType == XmlNodeType.EndElement)
                            {
                                r.EnsureMarkup(XmlNodeType.EndElement, "value");
                                break;
                            }

                            r.EnsureMarkup(XmlNodeType.Element, "text", "tag");
                            var isEmptyElement = r.IsEmptyElement;
                            var elementName = r.Name;
                            string content;

                            if (isEmptyElement)
                            {
                                content = string.Empty;
                            }
                            else
                            {
                                await r.ReadAsync().ConfigureAwait(false);
                                content = r.Value;
                            }

                            if (elementName == "tag")
                            {
                                if (tags == null)
                                {
                                    tags = ImmutableSortedSet.CreateBuilder<string>();
                                }
                                tags.Add(content);
                            }
                            else
                            {
                                value = content;
                            }

                            if (!isEmptyElement)
                            {
                                await r.ReadAsync().ConfigureAwait(false);
                                r.EnsureMarkup(XmlNodeType.EndElement, elementName);
                            }
                        }

                        if (tags != null && tags.Count > 0)
                        {
                            values.Add(new TaggedFieldValue(value ?? string.Empty, tags.ToImmutable()));
                            tags.Clear();
                        }
                        else
                        {
                            values.Add(value ?? string.Empty);
                        }
                    }
                    else
                    {
                        Debug.Assert(this.SegmentedRaw == null);
                        Debug.Assert(key == "_raw");

                        string value = await r.ReadOuterXmlAsync().ConfigureAwait(false);
                        this.SegmentedRaw = XElement.Parse(value);
                        values.Add(this.SegmentedRaw.Value);
                    }
                }

                if (key.StartsWith("tag::"))
                {
                    var valueSet = ImmutableSortedSet.ToImmutableSortedSet<string>(values.Cast<string>());
                    tagsDictionary.Add(key.Substring("tag::".Length), valueSet);
                    dictionary.Add(key, valueSet);
                }
                else
                {
                    switch (values.Count)
                    {
                        case 0:
                            dictionary.Add(key, string.Empty);
                            break;
                        case 1:
                            dictionary.Add(key, values[0]);
                            break;
                        default:
                            dictionary.Add(key, new ReadOnlyCollection<object>(values));
                            break;
                    }
                }

            }).ConfigureAwait(false);
        }