Esempio n. 1
0
            public LazyCosmosArray(
                IJsonNavigator jsonNavigator,
                IJsonNavigatorNode jsonNavigatorNode)
            {
                JsonNodeType type = jsonNavigator.GetNodeType(jsonNavigatorNode);

                if (type != JsonNodeType.Array)
                {
                    throw new ArgumentOutOfRangeException($"{nameof(jsonNavigatorNode)} must be an {JsonNodeType.Array} node. Got {type} instead.");
                }

                this.jsonNavigator     = jsonNavigator;
                this.jsonNavigatorNode = jsonNavigatorNode;

                this.lazyCosmosElementArray = new Lazy <Lazy <CosmosElement>[]>(() =>
                {
                    Lazy <CosmosElement>[] lazyArray = new Lazy <CosmosElement> [this.jsonNavigator.GetArrayItemCount(this.jsonNavigatorNode)];
                    int index = 0;
                    // Using foreach instead of indexer, since the navigator doesn't support random seeks efficiently.
                    foreach (IJsonNavigatorNode arrayItem in this.jsonNavigator.GetArrayItems(this.jsonNavigatorNode))
                    {
                        lazyArray[index] = new Lazy <CosmosElement>(() => CosmosElement.Dispatch(this.jsonNavigator, arrayItem));
                        index++;
                    }

                    return(lazyArray);
                });
            }
Esempio n. 2
0
            public LazyCosmosObject(IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode)
            {
                JsonNodeType type = jsonNavigator.GetNodeType(jsonNavigatorNode);

                if (type != JsonNodeType.Object)
                {
                    throw new ArgumentOutOfRangeException($"{nameof(jsonNavigatorNode)} must be a {JsonNodeType.Object} node. Got {type} instead.");
                }

                this.jsonNavigator     = jsonNavigator;
                this.jsonNavigatorNode = jsonNavigatorNode;
                this.lazyCache         = new Lazy <Dictionary <string, CosmosElement> >(() =>
                {
                    int propertyCount = this.jsonNavigator.GetObjectPropertyCount(this.jsonNavigatorNode);
                    Dictionary <string, CosmosElement> cache = new Dictionary <string, CosmosElement>(capacity: propertyCount);
                    foreach (ObjectProperty objectProperty in this.jsonNavigator.GetObjectProperties(this.jsonNavigatorNode))
                    {
                        string key          = this.jsonNavigator.GetStringValue(objectProperty.NameNode);
                        CosmosElement value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode);
                        cache[key]          = value;
                    }

                    return(cache);
                });
            }
Esempio n. 3
0
        public static CosmosElement Create(byte[] buffer)
        {
            IJsonNavigator     jsonNavigator     = JsonNavigator.Create(buffer);
            IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode();

            return(CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode));
        }
Esempio n. 4
0
            public static TryCatch <TCosmosElement> CreateFromBuffer <TCosmosElement>(ReadOnlyMemory <byte> buffer)
                where TCosmosElement : CosmosElement
            {
                if (buffer.IsEmpty)
                {
                    TryCatch <TCosmosElement> .FromException(
                        new ArgumentException($"{nameof(buffer)} must not be empty."));
                }

                CosmosElement unTypedCosmosElement;

                try
                {
                    IJsonNavigator     jsonNavigator     = JsonNavigator.Create(buffer);
                    IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode();
                    unTypedCosmosElement = CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode);
                }
                catch (JsonParseException jpe)
                {
                    return(TryCatch <TCosmosElement> .FromException(jpe));
                }

                if (!(unTypedCosmosElement is TCosmosElement typedCosmosElement))
                {
                    return(TryCatch <TCosmosElement> .FromException(
                               new CosmosElementWrongTypeException(
                                   message : $"buffer was incorrect cosmos element type: {unTypedCosmosElement.GetType()} when {typeof(TCosmosElement)} was requested.")));
                }

                return(TryCatch <TCosmosElement> .FromResult(typedCosmosElement));
            }
Esempio n. 5
0
            public override bool TryGetValue(string key, out CosmosElement value)
            {
                if (this.cachedElements.TryGetValue(
                        key,
                        out CosmosElement cosmosElemet))
                {
                    value = cosmosElemet;
                    return(true);
                }

                if (this.jsonNavigator.TryGetObjectProperty(
                        this.jsonNavigatorNode,
                        key,
                        out ObjectProperty objectProperty))
                {
                    value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode);
                    this.cachedElements[key] = value;

                    return(true);
                }

#pragma warning disable CS8625   // Cannot convert null literal to non-nullable reference type.
                value = default; // Dictionary.TryGetValue does not use nullable references.
#pragma warning restore CS8625   // Cannot convert null literal to non-nullable reference type.
                return(false);
            }
        public static CosmosElement CreateFromBuffer(ReadOnlyMemory <byte> buffer)
        {
            IJsonNavigator     jsonNavigator     = JsonNavigator.Create(buffer);
            IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode();

            return(CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode));
        }
Esempio n. 7
0
            public override bool TryGetValue(string key, out CosmosElement value)
            {
                value = default;
                bool gotValue;

                if (this.cachedElements.TryGetValue(
                        key,
                        out CosmosElement cosmosElemet))
                {
                    value    = cosmosElemet;
                    gotValue = true;
                }
                else if (this.jsonNavigator.TryGetObjectProperty(
                             this.jsonNavigatorNode,
                             key,
                             out ObjectProperty objectProperty))
                {
                    value    = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode);
                    gotValue = true;
                    this.cachedElements[key] = value;
                }
                else
                {
                    value    = null;
                    gotValue = false;
                }

                return(gotValue);
            }
Esempio n. 8
0
 public override CosmosElement this[int index]
 {
     get
     {
         IJsonNavigatorNode arrayItemNode = this.jsonNavigator.GetArrayItemAt(this.jsonNavigatorNode, index);
         return(CosmosElement.Dispatch(this.jsonNavigator, arrayItemNode));
     }
 }
 public override IEnumerator <KeyValuePair <string, CosmosElement> > GetEnumerator() => this
 .jsonNavigator
 .GetObjectProperties(this.jsonNavigatorNode)
 .Select(
     (objectProperty) =>
     new KeyValuePair <string, CosmosElement>(
         this.jsonNavigator.GetStringValue(objectProperty.NameNode),
         CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode)))
 .GetEnumerator();
Esempio n. 10
0
            public override bool TryGetValue(string key, out CosmosElement value)
            {
                if (this.cachedElements.TryGetValue(
                        key,
                        out CosmosElement cosmosElemet))
                {
                    value = cosmosElemet;
                    return(true);
                }

                if (this.jsonNavigator.TryGetObjectProperty(
                        this.jsonNavigatorNode,
                        key,
                        out ObjectProperty objectProperty))
                {
                    value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode);
                    this.cachedElements[key] = value;

                    return(true);
                }

                value = default;
                return(false);
            }
        /// <summary>
        /// Converts a list of CosmosElements into a memory stream.
        /// </summary>
        /// <param name="memoryStream">The memory stream response from Azure Cosmos</param>
        /// <param name="resourceType">The resource type</param>
        /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param>
        /// <returns>Returns a memory stream of cosmos elements. By default the memory stream will contain JSON.</returns>
        internal static CosmosArray ToCosmosElements(
            MemoryStream memoryStream,
            ResourceType resourceType,
            CosmosSerializationFormatOptions cosmosSerializationOptions = null)
        {
            if (!memoryStream.CanRead)
            {
                throw new InvalidDataException("Stream can not be read");
            }

            // Execute the callback an each element of the page
            // For example just could get a response like this
            // {
            //    "_rid": "qHVdAImeKAQ=",
            //    "Documents": [{
            //        "id": "03230",
            //        "_rid": "qHVdAImeKAQBAAAAAAAAAA==",
            //        "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/",
            //        "_etag": "\"410000b0-0000-0000-0000-597916b00000\"",
            //        "_attachments": "attachments\/",
            //        "_ts": 1501107886
            //    }],
            //    "_count": 1
            // }
            // And you should execute the callback on each document in "Documents".

            long responseLengthBytes = memoryStream.Length;
            ReadOnlyMemory <byte> content;

            if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer))
            {
                content = buffer;
            }
            else
            {
                content = memoryStream.ToArray();
            }

            IJsonNavigator jsonNavigator;

            // Use the users custom navigator
            if (cosmosSerializationOptions != null)
            {
                jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content);
                if (jsonNavigator == null)
                {
                    throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator.");
                }
            }
            else
            {
                jsonNavigator = JsonNavigator.Create(content);
            }

            string resourceName = CosmosElementSerializer.GetRootNodeName(resourceType);

            CosmosArray documents;

            if ((jsonNavigator.SerializationFormat == JsonSerializationFormat.Binary) && jsonNavigator.TryGetObjectProperty(
                    jsonNavigator.GetRootNode(),
                    "stringDictionary",
                    out ObjectProperty stringDictionaryProperty))
            {
                // Payload is string dictionary encode so we have to decode using the string dictionary.
                IJsonNavigatorNode   stringDictionaryNode = stringDictionaryProperty.ValueNode;
                JsonStringDictionary jsonStringDictionary = JsonStringDictionary.CreateFromStringArray(
                    jsonNavigator
                    .GetArrayItems(stringDictionaryNode)
                    .Select(item => jsonNavigator.GetStringValue(item))
                    .ToList());

                if (!jsonNavigator.TryGetObjectProperty(
                        jsonNavigator.GetRootNode(),
                        resourceName,
                        out ObjectProperty resourceProperty))
                {
                    throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}");
                }

                IJsonNavigatorNode resources = resourceProperty.ValueNode;

                if (!jsonNavigator.TryGetBufferedBinaryValue(resources, out ReadOnlyMemory <byte> resourceBinary))
                {
                    resourceBinary = jsonNavigator.GetBinaryValue(resources);
                }

                IJsonNavigator navigatorWithStringDictionary = JsonNavigator.Create(resourceBinary, jsonStringDictionary);

                if (!(CosmosElement.Dispatch(
                          navigatorWithStringDictionary,
                          navigatorWithStringDictionary.GetRootNode()) is CosmosArray cosmosArray))
                {
                    throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}");
                }

                documents = cosmosArray;
            }
            else
            {
                // Payload is not string dictionary encoded so we can just do for the documents as is.
                if (!jsonNavigator.TryGetObjectProperty(
                        jsonNavigator.GetRootNode(),
                        resourceName,
                        out ObjectProperty objectProperty))
                {
                    throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}");
                }

                if (!(CosmosElement.Dispatch(
                          jsonNavigator,
                          objectProperty.ValueNode) is CosmosArray cosmosArray))
                {
                    throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}");
                }

                documents = cosmosArray;
            }

            return(documents);
        }
Esempio n. 12
0
        /// <summary>
        /// Converts a list of CosmosElements into a memory stream.
        /// </summary>
        /// <param name="memoryStream">The memory stream response from Azure Cosmos</param>
        /// <param name="resourceType">The resource type</param>
        /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param>
        /// <returns>Returns a memory stream of cosmos elements. By default the memory stream will contain JSON.</returns>
        internal static CosmosArray ToCosmosElements(
            MemoryStream memoryStream,
            ResourceType resourceType,
            CosmosSerializationOptions cosmosSerializationOptions = null)
        {
            if (!memoryStream.CanRead)
            {
                throw new InvalidDataException("Stream can not be read");
            }

            // Execute the callback an each element of the page
            // For example just could get a response like this
            // {
            //    "_rid": "qHVdAImeKAQ=",
            //    "Documents": [{
            //        "id": "03230",
            //        "_rid": "qHVdAImeKAQBAAAAAAAAAA==",
            //        "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/",
            //        "_etag": "\"410000b0-0000-0000-0000-597916b00000\"",
            //        "_attachments": "attachments\/",
            //        "_ts": 1501107886
            //    }],
            //    "_count": 1
            // }
            // And you should execute the callback on each document in "Documents".

            long responseLengthBytes = memoryStream.Length;

            byte[]         content       = memoryStream.ToArray();
            IJsonNavigator jsonNavigator = null;

            // Use the users custom navigator
            if (cosmosSerializationOptions != null)
            {
                jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content);
                if (jsonNavigator == null)
                {
                    throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator.");
                }
            }
            else
            {
                jsonNavigator = JsonNavigator.Create(content);
            }

            string resourceName = CosmosElementSerializer.GetRootNodeName(resourceType);

            if (!jsonNavigator.TryGetObjectProperty(
                    jsonNavigator.GetRootNode(),
                    resourceName,
                    out ObjectProperty objectProperty))
            {
                throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}");
            }

            IJsonNavigatorNode cosmosElements = objectProperty.ValueNode;

            if (!(CosmosElement.Dispatch(
                      jsonNavigator,
                      cosmosElements) is CosmosArray cosmosArray))
            {
                throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}");
            }

            return(cosmosArray);
        }
Esempio n. 13
0
 public override IEnumerator <CosmosElement> GetEnumerator() => this
 .jsonNavigator
 .GetArrayItems(this.jsonNavigatorNode)
 .Select((arrayItem) => CosmosElement.Dispatch(this.jsonNavigator, arrayItem))
 .GetEnumerator();