public void KindIsSetCorrectly() { const string text = "(1,2,3)"; var expectedType = new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false))); object collection = ODataUriConversionUtils.ConvertFromCollectionValue("[1,2,3]", HardCodedTestModel.TestModel, expectedType); LiteralToken literalToken = new LiteralToken(collection, text, expectedType); CollectionConstantNode collectionConstantNode = new CollectionConstantNode( (literalToken.Value as ODataCollectionValue)?.Items, text, expectedType); collectionConstantNode.InternalKind.Should().Be(InternalQueryNodeKind.CollectionConstant); }
public void ItemTypeIsSetCorrectly() { const string text = "(1,2,3)"; var expectedType = new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false))); object collection = ODataUriConversionUtils.ConvertFromCollectionValue("[1,2,3]", HardCodedTestModel.TestModel, expectedType); LiteralToken literalToken = new LiteralToken(collection, text, expectedType); CollectionConstantNode collectionConstantNode = new CollectionConstantNode( (literalToken.Value as ODataCollectionValue)?.Items, text, expectedType); Assert.Equal("Edm.Int32", collectionConstantNode.ItemType.FullName()); }
public void NullableCollectionTypeSetsConstantNodeCorrectly() { const string text = "('abc','def', null)"; var expectedType = new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(true))); object collection = ODataUriConversionUtils.ConvertFromCollectionValue("['abc','def', null]", HardCodedTestModel.TestModel, expectedType); LiteralToken literalToken = new LiteralToken(collection, text, expectedType); CollectionConstantNode collectionConstantNode = new CollectionConstantNode( (literalToken.Value as ODataCollectionValue)?.Items, text, expectedType); var expectedList = new ConstantNode[] { new ConstantNode("abc", "abc", EdmCoreModel.Instance.GetString(true)), new ConstantNode("def", "def", EdmCoreModel.Instance.GetString(true)), new ConstantNode(null, "null", EdmCoreModel.Instance.GetString(true)), }; collectionConstantNode.Collection.ShouldBeEquivalentTo(expectedList); }
public void NumberCollectionThroughLiteralTokenIsSetCorrectly() { const string text = "(1,2,3)"; var expectedType = new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false))); object collection = ODataUriConversionUtils.ConvertFromCollectionValue("[1,2,3]", HardCodedTestModel.TestModel, expectedType); LiteralToken literalToken = new LiteralToken(collection, text, expectedType); CollectionConstantNode collectionConstantNode = new CollectionConstantNode( (literalToken.Value as ODataCollectionValue)?.Items, text, expectedType); var expectedList = new ConstantNode[] { new ConstantNode(1, "1", EdmCoreModel.Instance.GetInt32(false)), new ConstantNode(2, "2", EdmCoreModel.Instance.GetInt32(false)), new ConstantNode(3, "3", EdmCoreModel.Instance.GetInt32(false)), }; collectionConstantNode.Collection.ShouldBeEquivalentTo(expectedList); }
public void StringCollectionThroughLiteralTokenIsSetCorrectly() { const string text = "('abc','def','ghi')"; var expectedType = new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(true))); object collection = ODataUriConversionUtils.ConvertFromCollectionValue("['abc','def','ghi']", HardCodedTestModel.TestModel, expectedType); LiteralToken literalToken = new LiteralToken(collection, text, expectedType); CollectionConstantNode collectionConstantNode = new CollectionConstantNode( (literalToken.Value as ODataCollectionValue)?.Items, text, expectedType); var expectedList = new ConstantNode[] { new ConstantNode("abc", "abc", EdmCoreModel.Instance.GetString(true)), new ConstantNode("def", "def", EdmCoreModel.Instance.GetString(true)), new ConstantNode("ghi", "ghi", EdmCoreModel.Instance.GetString(true)), }; VerifyCollectionConstantNode(collectionConstantNode.Collection, expectedList); }
/// <summary> /// Retrieve CollectionNode bound with given query token. /// </summary> /// <param name="queryToken">The query token</param> /// <param name="expectedType">The expected type that this collection holds</param> /// <param name="model">The Edm model</param> /// <returns>The corresponding CollectionNode</returns> private CollectionNode GetCollectionOperandFromToken(QueryToken queryToken, IEdmTypeReference expectedType, IEdmModel model) { CollectionNode operand = null; LiteralToken literalToken = queryToken as LiteralToken; if (literalToken != null) { string originalLiteralText = literalToken.OriginalText; // Parentheses-based collections are not standard JSON but bracket-based ones are. // Temporarily switch our collection to bracket-based so that the JSON reader will // correctly parse the collection. Then pass the original literal text to the token. string bracketLiteralText = originalLiteralText; if (bracketLiteralText[0] == '(') { Debug.Assert(bracketLiteralText[bracketLiteralText.Length - 1] == ')', "Collection with opening '(' should have corresponding ')'"); StringBuilder replacedText = new StringBuilder(bracketLiteralText); replacedText[0] = '['; replacedText[replacedText.Length - 1] = ']'; bracketLiteralText = replacedText.ToString(); } object collection = ODataUriConversionUtils.ConvertFromCollectionValue(bracketLiteralText, model, expectedType); LiteralToken collectionLiteralToken = new LiteralToken(collection, originalLiteralText, expectedType); operand = this.bindMethod(collectionLiteralToken) as CollectionConstantNode; } else { operand = this.bindMethod(queryToken) as CollectionNode; } if (operand == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_RightOperandNotCollectionValue); } return(operand); }
/// <summary> /// Retrieve CollectionNode bound with given query token. /// </summary> /// <param name="queryToken">The query token</param> /// <param name="expectedType">The expected type that this collection holds</param> /// <param name="model">The Edm model</param> /// <returns>The corresponding CollectionNode</returns> private CollectionNode GetCollectionOperandFromToken(QueryToken queryToken, IEdmTypeReference expectedType, IEdmModel model) { CollectionNode operand = null; LiteralToken literalToken = queryToken as LiteralToken; if (literalToken != null) { string originalLiteralText = literalToken.OriginalText; // Parentheses-based collections are not standard JSON but bracket-based ones are. // Temporarily switch our collection to bracket-based so that the JSON reader will // correctly parse the collection. Then pass the original literal text to the token. string bracketLiteralText = originalLiteralText; if (bracketLiteralText[0] == '(') { Debug.Assert(bracketLiteralText[bracketLiteralText.Length - 1] == ')', "Collection with opening '(' should have corresponding ')'"); StringBuilder replacedText = new StringBuilder(bracketLiteralText); replacedText[0] = '['; replacedText[replacedText.Length - 1] = ']'; bracketLiteralText = replacedText.ToString(); Debug.Assert(expectedType.IsCollection()); string expectedTypeFullName = expectedType.Definition.AsElementType().FullTypeName(); if (expectedTypeFullName.Equals("Edm.String", StringComparison.Ordinal)) { // For collection of strings, need to convert single-quoted string to double-quoted string, // and also, per ABNF, a single quote within a string literal is "encoded" as two consecutive single quotes in either // literal or percent - encoded representation. // Sample: ['a''bc','''def','xyz'''] ==> ["a'bc","'def","xyz'"], which is legitimate Json format. bracketLiteralText = NormalizeStringCollectionItems(bracketLiteralText); } else if (expectedTypeFullName.Equals("Edm.Guid", StringComparison.Ordinal)) { // For collection of Guids, need to convert the Guid literals to single-quoted form, so that it is compatible // with the Json reader used for deserialization. // Sample: [D01663CF-EB21-4A0E-88E0-361C10ACE7FD, 492CF54A-84C9-490C-A7A4-B5010FAD8104] // ==> ['D01663CF-EB21-4A0E-88E0-361C10ACE7FD', '492CF54A-84C9-490C-A7A4-B5010FAD8104'] bracketLiteralText = NormalizeGuidCollectionItems(bracketLiteralText); } else if (expectedTypeFullName.Equals("Edm.DateTimeOffset", StringComparison.Ordinal) || expectedTypeFullName.Equals("Edm.Date", StringComparison.Ordinal) || expectedTypeFullName.Equals("Edm.TimeOfDay", StringComparison.Ordinal) || expectedTypeFullName.Equals("Edm.Duration", StringComparison.Ordinal)) { // For collection of Date/Time/Duration items, need to convert the Date/Time/Duration literals to single-quoted form, so that it is compatible // with the Json reader used for deserialization. // Sample: [1970-01-01T00:00:00Z, 1980-01-01T01:01:01+01:00] // ==> ['1970-01-01T00:00:00Z', '1980-01-01T01:01:01+01:00'] bracketLiteralText = NormalizeDateTimeCollectionItems(bracketLiteralText); } } object collection = ODataUriConversionUtils.ConvertFromCollectionValue(bracketLiteralText, model, expectedType); LiteralToken collectionLiteralToken = new LiteralToken(collection, originalLiteralText, expectedType); operand = this.bindMethod(collectionLiteralToken) as CollectionConstantNode; } else { operand = this.bindMethod(queryToken) as CollectionNode; } if (operand == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_RightOperandNotCollectionValue); } return(operand); }