From 5909bccc0b8dfc5b75a9225abeb836389b2b85a1 Mon Sep 17 00:00:00 2001 From: Brecht Debaere Date: Thu, 31 Oct 2019 23:49:47 +0100 Subject: [PATCH 1/5] Implement Dictionary converter. --- .../DictionaryOfStringStringConverter.cs | 60 +++++++++++++++++++ .../ODataJsonLightValueSerializer.cs | 2 +- .../Metadata/EdmLibraryExtensions.cs | 8 ++- .../Microsoft.OData.Core.csproj | 1 + .../PrimitiveConverter.cs | 8 +++ .../ExtensionMethods/EdmTypeSemantics.cs | 46 ++++++++++++++ .../Microsoft.OData.Edm.csproj | 1 + .../Schema/CoreModel/EdmCoreModel.cs | 1 + ...dmDictionaryOfStringStringTypeReference.cs | 25 ++++++++ .../Schema/Interfaces/IEdmPrimitiveType.cs | 5 ++ 10 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs create mode 100644 src/Microsoft.OData.Edm/Schema/EdmDictionaryOfStringStringTypeReference.cs diff --git a/src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs b/src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs new file mode 100644 index 0000000000..912906f606 --- /dev/null +++ b/src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs @@ -0,0 +1,60 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using Microsoft.OData.Json; + +namespace Microsoft.OData +{ + /// + /// Handles serialization and deserialization for Dictionary of String, String. + /// + internal sealed class DictionaryOfStringStringTypeConverter : IPrimitiveTypeConverter + { + /// + /// Write the Atom representation of an instance of a primitive type to an XmlWriter. + /// + /// The instance to write. + /// The Xml writer to use to write the instance. + public void WriteAtom(object instance, XmlWriter writer) + { + throw new NotImplementedException(); + } + + /// + /// Write the Atom representation of an instance of a primitive type to an TextWriter. + /// + /// The instance to write. + /// The text writer to use to write the instance. + public void WriteAtom(object instance, TextWriter writer) + { + throw new NotImplementedException(); + } + + /// + /// Write the Json Lite representation of an instance of a primitive type to a json writer. + /// + /// The instance to write. + /// Instance of JsonWriter. + public void WriteJsonLight(object instance, IJsonWriter jsonWriter) + { + var dictionary = (Dictionary)instance; + + jsonWriter.StartObjectScope(); + + foreach(var item in dictionary) + { + jsonWriter.WriteName(item.Key); + jsonWriter.WriteValue(item.Value); + } + + jsonWriter.EndObjectScope(); + } + } +} diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs index a7220b2a05..0950ab33e8 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs @@ -337,7 +337,7 @@ public virtual void WritePrimitiveValue( value = converter.ConvertToPayloadValue(value, expectedTypeReference); - if (actualTypeReference != null && actualTypeReference.IsSpatial()) + if (actualTypeReference != null && (actualTypeReference.IsSpatial() || actualTypeReference.IsDictionary())) { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter); } diff --git a/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs b/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs index 90a991b5ae..03326b059b 100644 --- a/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs +++ b/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs @@ -509,7 +509,7 @@ internal static bool IsPrimitiveType(Type clrType) return true; } - return PrimitiveTypeReferenceMap.ContainsKey(clrType) || typeof(ISpatial).IsAssignableFrom(clrType); + return PrimitiveTypeReferenceMap.ContainsKey(clrType) || typeof(ISpatial).IsAssignableFrom(clrType) || typeof(IDictionary).IsAssignableFrom(clrType); } /// @@ -1446,6 +1446,10 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(Type clrTyp { primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Geometry); } + else if (typeof(IDictionary).IsAssignableFrom(clrType)) + { + primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString); + } if (primitiveType == null) { @@ -1923,6 +1927,8 @@ private static EdmPrimitiveTypeReference ToTypeReference(IEdmPrimitiveType primi case EdmPrimitiveTypeKind.GeometryMultiPoint: case EdmPrimitiveTypeKind.GeometryCollection: return new EdmSpatialTypeReference(primitiveType, nullable); + case EdmPrimitiveTypeKind.DictionaryOfStringString: + return new EdmDictionaryOfStringStringTypeReference(primitiveType, nullable); default: throw new ODataException(ErrorStrings.General_InternalError(InternalErrorCodesCommon.EdmLibraryExtensions_PrimitiveTypeReference)); } diff --git a/src/Microsoft.OData.Core/Microsoft.OData.Core.csproj b/src/Microsoft.OData.Core/Microsoft.OData.Core.csproj index 4f0a7e89a6..85f3af3458 100644 --- a/src/Microsoft.OData.Core/Microsoft.OData.Core.csproj +++ b/src/Microsoft.OData.Core/Microsoft.OData.Core.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Microsoft.OData.Core/PrimitiveConverter.cs b/src/Microsoft.OData.Core/PrimitiveConverter.cs index b1fff304a7..81ef8eaaa6 100644 --- a/src/Microsoft.OData.Core/PrimitiveConverter.cs +++ b/src/Microsoft.OData.Core/PrimitiveConverter.cs @@ -27,6 +27,9 @@ internal sealed class PrimitiveConverter /// Instance of GeographyTypeConverter to register for all Geography types. private static readonly IPrimitiveTypeConverter geometryTypeConverter = new GeometryTypeConverter(); + /// Instance of DictionaryTypeConverter to register for all Dictionary types. + private static readonly IPrimitiveTypeConverter dictionaryStringStringTypeConverter = new DictionaryOfStringStringTypeConverter(); + /// Set of type converters that implement their own conversion using IPrimitiveTypeConverter. private static readonly PrimitiveConverter primitiveConverter = new PrimitiveConverter( @@ -118,6 +121,11 @@ private bool TryGetConverter(Type type, out IPrimitiveTypeConverter primitiveTyp primitiveTypeConverter = bestMatch.Value; return bestMatch.Value != null; } + else if (typeof(IDictionary).IsAssignableFrom(type)) + { + primitiveTypeConverter = dictionaryStringStringTypeConverter; + return true; + } else { primitiveTypeConverter = null; diff --git a/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs b/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs index 98b8b8d37b..0d8b6083c2 100644 --- a/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs +++ b/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs @@ -702,6 +702,50 @@ public static bool IsGeometry(this EdmPrimitiveTypeKind typeKind) return false; } + /// + /// Returns true if this reference refers to a dictionary type. + /// + /// Type reference. + /// This reference refers to a dictionary type. + public static bool IsDictionary(this IEdmTypeReference type) + { + EdmUtil.CheckArgumentNull(type, "type"); + return type.Definition.IsDictionary(); + } + + /// + /// Returns true if this definition refers to a dictionary type. + /// + /// Type reference. + /// This definition refers to a dictionary type. + public static bool IsDictionary(this IEdmType type) + { + EdmUtil.CheckArgumentNull(type, "type"); + IEdmPrimitiveType primitiveType = type as IEdmPrimitiveType; + if (primitiveType == null) + { + return false; + } + + return primitiveType.PrimitiveKind.IsDictionary(); + } + + /// + /// Returns true if this type kind represents a dictionary type. + /// + /// Type reference. + /// This kind refers to a dictionary type. + public static bool IsDictionary(this EdmPrimitiveTypeKind typeKind) + { + switch (typeKind) + { + case EdmPrimitiveTypeKind.DictionaryOfStringString: + return true; + } + + return false; + } + #endregion // The As*** functions never return null -- if the supplied type does not have the appropriate shape, an encoding of a bad type is returned. @@ -1327,6 +1371,8 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(this IEdmPr case EdmPrimitiveTypeKind.GeometryMultiLineString: case EdmPrimitiveTypeKind.GeometryMultiPoint: return new EdmSpatialTypeReference(type, isNullable); + case EdmPrimitiveTypeKind.DictionaryOfStringString: + return new EdmDictionaryOfStringStringTypeReference(type, isNullable); default: throw new InvalidOperationException(Edm.Strings.EdmPrimitive_UnexpectedKind); } diff --git a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj index b98c5985af..126ed59487 100644 --- a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj +++ b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj @@ -152,6 +152,7 @@ + diff --git a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs index c5f487f9a8..fb37b5286c 100644 --- a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs +++ b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs @@ -76,6 +76,7 @@ private EdmCoreModel() new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPolygon), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiLineString), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPoint), + new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString), primitiveType, // Edm.PrimitiveType }; diff --git a/src/Microsoft.OData.Edm/Schema/EdmDictionaryOfStringStringTypeReference.cs b/src/Microsoft.OData.Edm/Schema/EdmDictionaryOfStringStringTypeReference.cs new file mode 100644 index 0000000000..523efe9631 --- /dev/null +++ b/src/Microsoft.OData.Edm/Schema/EdmDictionaryOfStringStringTypeReference.cs @@ -0,0 +1,25 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +namespace Microsoft.OData.Edm +{ + /// + /// Represents a reference to an EDM dictionary of string string type. + /// + public class EdmDictionaryOfStringStringTypeReference : EdmPrimitiveTypeReference + { + /// + /// Initializes a new instance of the class. + /// + /// The type this reference refers to. + /// Denotes whether the type can be nullable. + public EdmDictionaryOfStringStringTypeReference(IEdmPrimitiveType definition, bool isNullable) + : base(definition, isNullable) + { + EdmUtil.CheckArgumentNull(definition, "definition"); + } + } +} diff --git a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs index b67e95d7fc..d52927ab40 100644 --- a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs +++ b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs @@ -185,6 +185,11 @@ public enum EdmPrimitiveTypeKind /// Represents a Primitive type /// PrimitiveType, + + /// + /// Represents a Dictionary of String, String + /// + DictionaryOfStringString, } /// From bc7d3caaa9adaaf91db508f3606b27b15f7a36c1 Mon Sep 17 00:00:00 2001 From: Brecht Debaere Date: Fri, 1 Nov 2019 00:40:36 +0100 Subject: [PATCH 2/5] Implement deserialization of Dictionary. --- .../Json/ODataJsonReaderCoreUtils.cs | 39 +++++++++++++++++++ ...taJsonLightPropertyAndValueDeserializer.cs | 11 ++++++ .../Microsoft.OData.Core.cs | 1 + .../Microsoft.OData.Core.txt | 2 + .../Parameterized.Microsoft.OData.Core.cs | 11 ++++++ 5 files changed, 64 insertions(+) diff --git a/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs b/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs index 3747ed7438..8db3f3e4ed 100644 --- a/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs +++ b/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs @@ -80,6 +80,45 @@ internal static ISpatial ReadSpatialValue( return spatialValue; } + internal static IDictionary ReadDictionaryOfStringStringValue( + IJsonReader jsonReader, + bool insideJsonObjectValue, + ODataInputContext inputContext, + IEdmPrimitiveTypeReference expectedValueTypeReference, + bool validateNullValue, + int recursionDepth, + string propertyName) + { + Debug.Assert(jsonReader != null, "jsonReader != null"); + Debug.Assert(inputContext != null, "inputContext != null"); + Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); + Debug.Assert(expectedValueTypeReference.IsDictionary(), "ReadDictionaryOfStringStringValue must be called only with dictionary types"); + + // Dictionary of String, String value can be either null constant or a JSON object + // If it's a null primitive value, report a null value. + if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)) + { + return null; + } + + IDictionary dictionaryOfStringStringValue = new Dictionary(); + if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) + { + IDictionary jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); + foreach(var item in jsonObject) + { + dictionaryOfStringStringValue[item.Key] = (string)item.Value; + } + } + + if (dictionaryOfStringStringValue == null) + { + throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue); + } + + return dictionaryOfStringStringValue; + } + /// /// Tries to read a null value from the JSON reader. /// diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs index 65afb9b87c..f47864df08 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs @@ -1461,6 +1461,17 @@ private object ReadPrimitiveValue(bool insideJsonObjectValue, IEdmPrimitiveTypeR this.recursionDepth, propertyName); } + else if (expectedValueTypeReference != null && expectedValueTypeReference.IsDictionary()) + { + result = ODataJsonReaderCoreUtils.ReadDictionaryOfStringStringValue( + this.JsonReader, + insideJsonObjectValue, + this.JsonLightInputContext, + expectedValueTypeReference, + validateNullValue, + this.recursionDepth, + propertyName); + } else { if (insideJsonObjectValue) diff --git a/src/Microsoft.OData.Core/Microsoft.OData.Core.cs b/src/Microsoft.OData.Core/Microsoft.OData.Core.cs index 412a8d7dfe..bc432612d5 100644 --- a/src/Microsoft.OData.Core/Microsoft.OData.Core.cs +++ b/src/Microsoft.OData.Core/Microsoft.OData.Core.cs @@ -513,6 +513,7 @@ internal sealed class TextRes { internal const string ODataJsonLightPropertyAndValueDeserializer_CollectionTypeNotExpected = "ODataJsonLightPropertyAndValueDeserializer_CollectionTypeNotExpected"; internal const string ODataJsonLightPropertyAndValueDeserializer_CollectionTypeExpected = "ODataJsonLightPropertyAndValueDeserializer_CollectionTypeExpected"; internal const string ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue = "ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue"; + internal const string ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue = "ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue"; internal const string ODataJsonLightReader_UnexpectedPrimitiveValueForODataResource = "ODataJsonLightReader_UnexpectedPrimitiveValueForODataResource"; internal const string ODataJsonLightReaderUtils_AnnotationWithNullValue = "ODataJsonLightReaderUtils_AnnotationWithNullValue"; internal const string ODataJsonLightReaderUtils_InvalidValueForODataNullAnnotation = "ODataJsonLightReaderUtils_InvalidValueForODataNullAnnotation"; diff --git a/src/Microsoft.OData.Core/Microsoft.OData.Core.txt b/src/Microsoft.OData.Core/Microsoft.OData.Core.txt index 67e150b775..7f695fd945 100644 --- a/src/Microsoft.OData.Core/Microsoft.OData.Core.txt +++ b/src/Microsoft.OData.Core/Microsoft.OData.Core.txt @@ -532,6 +532,8 @@ ODataJsonLightPropertyAndValueDeserializer_CollectionTypeExpected=A non-collecti ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue=The value specified for the spatial property was not valid. You must specify a valid spatial value. +ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue=The value specified for the dictionary property was not valid. You must specify a valid dictionary value. + ODataJsonLightReader_UnexpectedPrimitiveValueForODataResource=If a primitive value is representing a resource, the resource must be null. ODataJsonLightReaderUtils_AnnotationWithNullValue=The '{0}' instance or property annotation has a null value. In OData, the '{0}' instance or property annotation must have a non-null string value. ODataJsonLightReaderUtils_InvalidValueForODataNullAnnotation=An '{0}' annotation was found with an invalid value. In OData, the only valid value for the '{0}' annotation is '{1}'. diff --git a/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs b/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs index 2b67c92498..178e60bdb8 100644 --- a/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs +++ b/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs @@ -3472,6 +3472,17 @@ internal static string ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue { } } + /// + /// A string like "The value specified for the dictionary property was not valid. You must specify a valid dictionary value." + /// + internal static string ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue + { + get + { + return Microsoft.OData.TextRes.GetString(Microsoft.OData.TextRes.ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue); + } + } + /// /// A string like "If a primitive value is representing a resource, the resource must be null." /// From 34ab004a304d6112a96a97a9bc421a71641147be Mon Sep 17 00:00:00 2001 From: Brecht Debaere Date: Fri, 1 Nov 2019 07:38:56 +0100 Subject: [PATCH 3/5] Extend EdmModelVisitor to allow $metadata output. --- src/Microsoft.OData.Edm/EdmModelVisitor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.OData.Edm/EdmModelVisitor.cs b/src/Microsoft.OData.Edm/EdmModelVisitor.cs index eb89e36111..0acb35dc00 100644 --- a/src/Microsoft.OData.Edm/EdmModelVisitor.cs +++ b/src/Microsoft.OData.Edm/EdmModelVisitor.cs @@ -314,6 +314,7 @@ public void VisitPrimitiveTypeReference(IEdmPrimitiveTypeReference reference) case EdmPrimitiveTypeKind.Date: case EdmPrimitiveTypeKind.PrimitiveType: case EdmPrimitiveTypeKind.None: + case EdmPrimitiveTypeKind.DictionaryOfStringString: this.ProcessPrimitiveTypeReference(reference); break; default: From 5843f274553590b4fb15deb8f7b92ed8c2abb6e4 Mon Sep 17 00:00:00 2001 From: Brecht Debaere Date: Sat, 13 Jun 2020 22:24:23 +0200 Subject: [PATCH 4/5] Update count to 41. --- .../Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs index 11b570c9a8..2f727d0aec 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs @@ -26,7 +26,7 @@ public void NamespacePropertyShouldReturnCorrectNamespaceString() [Fact] public void SchemaElementsShouldReturnCorrectSchemaElementCount() { - Assert.Equal(40, EdmCoreModel.Instance.SchemaElements.Count()); + Assert.Equal(41, EdmCoreModel.Instance.SchemaElements.Count()); } [Theory] From 70eaa47d056039e4d7efacac0d99c4079f76193d Mon Sep 17 00:00:00 2001 From: Brecht Debaere Date: Thu, 18 Jun 2020 18:23:54 +0200 Subject: [PATCH 5/5] Add Dictionary implementation. --- .../DictionaryOfStringObjectTypeConverter.cs | 109 ++++++++++++++ ... DictionaryOfStringStringTypeConverter.cs} | 7 +- .../Json/JsonWriterExtensions.cs | 6 + .../Json/ODataJsonReaderCoreUtils.cs | 43 +++++- ...taJsonLightPropertyAndValueDeserializer.cs | 13 +- .../ODataJsonLightValueSerializer.cs | 2 +- .../Metadata/EdmLibraryExtensions.cs | 30 ++-- .../PrimitiveConverter.cs | 14 +- src/Microsoft.OData.Edm/EdmModelVisitor.cs | 3 +- .../ExtensionMethods/EdmTypeSemantics.cs | 138 ++++++++++++------ .../Schema/CoreModel/EdmCoreModel.cs | 3 +- .../Schema/Interfaces/IEdmPrimitiveType.cs | 15 +- .../Schema/EdmCoreModelTests.cs | 2 +- 13 files changed, 312 insertions(+), 73 deletions(-) create mode 100644 src/Microsoft.OData.Core/DictionaryOfStringObjectTypeConverter.cs rename src/Microsoft.OData.Core/{DictionaryOfStringStringConverter.cs => DictionaryOfStringStringTypeConverter.cs} (88%) diff --git a/src/Microsoft.OData.Core/DictionaryOfStringObjectTypeConverter.cs b/src/Microsoft.OData.Core/DictionaryOfStringObjectTypeConverter.cs new file mode 100644 index 0000000000..492b49d146 --- /dev/null +++ b/src/Microsoft.OData.Core/DictionaryOfStringObjectTypeConverter.cs @@ -0,0 +1,109 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using Microsoft.OData.Edm; +using Microsoft.OData.Json; + +namespace Microsoft.OData +{ + /// + /// Handles serialization and deserialization for types derived from Geography. + /// + internal sealed class DictionaryOfStringObjectTypeConverter : IPrimitiveTypeConverter + { + /// + /// Write the Atom representation of an instance of a primitive type to an XmlWriter. + /// + /// The instance to write. + /// The Xml writer to use to write the instance. + public void WriteAtom(object instance, XmlWriter writer) + { + throw new NotImplementedException(); + } + + /// + /// Write the Atom representation of an instance of a primitive type to an TextWriter. + /// + /// The instance to write. + /// The text writer to use to write the instance. + public void WriteAtom(object instance, TextWriter writer) + { + throw new NotImplementedException(); + } + + /// + /// Write the Json Lite representation of an instance of a primitive type to a json writer. + /// + /// The instance to write. + /// Instance of JsonWriter. + public void WriteJsonLight(object instance, IJsonWriter jsonWriter) + { + var dictionary = (IDictionary)instance; + + jsonWriter.StartObjectScope(); + + foreach (var item in dictionary) + { + jsonWriter.WriteName(item.Key); + + switch (item.Value) + { + case bool boolValue: + jsonWriter.WriteValue(boolValue); + break; + case float floatValue: + jsonWriter.WriteValue(floatValue); + break; + case short shortValue: + jsonWriter.WriteValue(shortValue); + break; + case long longValue: + jsonWriter.WriteValue(longValue); + break; + case double doubleValue: + jsonWriter.WriteValue(doubleValue); + break; + case Guid guidValue: + jsonWriter.WriteValue(guidValue); + break; + case decimal decimalValue: + jsonWriter.WriteValue(decimalValue); + break; + case DateTimeOffset dateTimeOffsetValue: + jsonWriter.WriteValue(dateTimeOffsetValue); + break; + case TimeSpan timeSpanValue: + jsonWriter.WriteValue(timeSpanValue); + break; + case byte byteValue: + jsonWriter.WriteValue(byteValue); + break; + case sbyte sbyteValue: + jsonWriter.WriteValue(sbyteValue); + break; + case byte[] byteArrayValue: + jsonWriter.WriteValue(byteArrayValue); + break; + case int intValue: + jsonWriter.WriteValue(intValue); + break; + case string stringValue: + jsonWriter.WriteValue(stringValue); + break; + case IDictionary dictionaryOfStringObjectValue: + WriteJsonLight(dictionaryOfStringObjectValue, jsonWriter); + break; + } + } + + jsonWriter.EndObjectScope(); + } + } +} diff --git a/src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs b/src/Microsoft.OData.Core/DictionaryOfStringStringTypeConverter.cs similarity index 88% rename from src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs rename to src/Microsoft.OData.Core/DictionaryOfStringStringTypeConverter.cs index 912906f606..498657845a 100644 --- a/src/Microsoft.OData.Core/DictionaryOfStringStringConverter.cs +++ b/src/Microsoft.OData.Core/DictionaryOfStringStringTypeConverter.cs @@ -8,12 +8,13 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using Microsoft.OData.Edm; using Microsoft.OData.Json; namespace Microsoft.OData { /// - /// Handles serialization and deserialization for Dictionary of String, String. + /// Handles serialization and deserialization for types derived from Geography. /// internal sealed class DictionaryOfStringStringTypeConverter : IPrimitiveTypeConverter { @@ -44,11 +45,11 @@ public void WriteAtom(object instance, TextWriter writer) /// Instance of JsonWriter. public void WriteJsonLight(object instance, IJsonWriter jsonWriter) { - var dictionary = (Dictionary)instance; + var dictionary = (IDictionary)instance; jsonWriter.StartObjectScope(); - foreach(var item in dictionary) + foreach (var item in dictionary) { jsonWriter.WriteName(item.Key); jsonWriter.WriteValue(item.Value); diff --git a/src/Microsoft.OData.Core/Json/JsonWriterExtensions.cs b/src/Microsoft.OData.Core/Json/JsonWriterExtensions.cs index 8f3499488a..d1aea508dd 100644 --- a/src/Microsoft.OData.Core/Json/JsonWriterExtensions.cs +++ b/src/Microsoft.OData.Core/Json/JsonWriterExtensions.cs @@ -153,6 +153,12 @@ internal static void WritePrimitiveValue(this IJsonWriter jsonWriter, object val return; } + if (value is Dictionary) + { + jsonWriter.WriteJsonObjectValue((Dictionary)value, null); + return; + } + throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(value.GetType().FullName)); } diff --git a/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs b/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs index 8db3f3e4ed..f7ec6c6fbd 100644 --- a/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs +++ b/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs @@ -80,6 +80,45 @@ internal static ISpatial ReadSpatialValue( return spatialValue; } + internal static IDictionary ReadDictionaryOfStringObjectValue( + IJsonReader jsonReader, + bool insideJsonObjectValue, + ODataInputContext inputContext, + IEdmPrimitiveTypeReference expectedValueTypeReference, + bool validateNullValue, + int recursionDepth, + string propertyName) + { + Debug.Assert(jsonReader != null, "jsonReader != null"); + Debug.Assert(inputContext != null, "inputContext != null"); + Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); + Debug.Assert(expectedValueTypeReference.IsDictionaryOfStringObject(), "ReadDictionaryOfStringObjectValue must be called only with dictionary types"); + + // Dictionary of String, Object value can be either null constant or a JSON object + // If it's a null primitive value, report a null value. + if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)) + { + return null; + } + + IDictionary dictionaryOfStringObjectValue = new Dictionary(); + if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) + { + IDictionary jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); + foreach (var item in jsonObject) + { + dictionaryOfStringObjectValue[item.Key] = item.Value; + } + } + + if (dictionaryOfStringObjectValue == null) + { + throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadDictionaryPropertyValue); + } + + return dictionaryOfStringObjectValue; + } + internal static IDictionary ReadDictionaryOfStringStringValue( IJsonReader jsonReader, bool insideJsonObjectValue, @@ -92,7 +131,7 @@ internal static IDictionary ReadDictionaryOfStringStringValue( Debug.Assert(jsonReader != null, "jsonReader != null"); Debug.Assert(inputContext != null, "inputContext != null"); Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); - Debug.Assert(expectedValueTypeReference.IsDictionary(), "ReadDictionaryOfStringStringValue must be called only with dictionary types"); + Debug.Assert(expectedValueTypeReference.IsDictionaryOfStringString(), "ReadDictionaryOfStringStringValue must be called only with dictionary types"); // Dictionary of String, String value can be either null constant or a JSON object // If it's a null primitive value, report a null value. @@ -105,7 +144,7 @@ internal static IDictionary ReadDictionaryOfStringStringValue( if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) { IDictionary jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); - foreach(var item in jsonObject) + foreach (var item in jsonObject) { dictionaryOfStringStringValue[item.Key] = (string)item.Value; } diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs index 3d3e90b763..b72909553e 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs @@ -1457,7 +1457,18 @@ private object ReadPrimitiveValue(bool insideJsonObjectValue, IEdmPrimitiveTypeR this.recursionDepth, propertyName); } - else if (expectedValueTypeReference != null && expectedValueTypeReference.IsDictionary()) + else if (expectedValueTypeReference != null && expectedValueTypeReference.IsDictionaryOfStringObject()) + { + result = ODataJsonReaderCoreUtils.ReadDictionaryOfStringObjectValue( + this.JsonReader, + insideJsonObjectValue, + this.JsonLightInputContext, + expectedValueTypeReference, + validateNullValue, + this.recursionDepth, + propertyName); + } + else if (expectedValueTypeReference != null && expectedValueTypeReference.IsDictionaryOfStringString()) { result = ODataJsonReaderCoreUtils.ReadDictionaryOfStringStringValue( this.JsonReader, diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs index 0950ab33e8..bdfb2adcd1 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs @@ -337,7 +337,7 @@ public virtual void WritePrimitiveValue( value = converter.ConvertToPayloadValue(value, expectedTypeReference); - if (actualTypeReference != null && (actualTypeReference.IsSpatial() || actualTypeReference.IsDictionary())) + if (actualTypeReference != null && actualTypeReference.IsSpatial() || actualTypeReference.IsDictionaryOfStringObject() || actualTypeReference.IsDictionaryOfStringString()) { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter); } diff --git a/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs b/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs index 3d0ccba9f1..59575727c1 100644 --- a/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs +++ b/src/Microsoft.OData.Core/Metadata/EdmLibraryExtensions.cs @@ -54,6 +54,12 @@ internal static class EdmLibraryExtensions /// Type reference for Edm.Decimal. private static readonly EdmPrimitiveTypeReference DecimalTypeReference = ToTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Decimal), false); + /// Type reference for Edm.DictionaryOfStringObject. + private static readonly EdmPrimitiveTypeReference DictionaryOfStringObjectTypeReference = ToTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringObject), true); + + /// Type reference for Edm.DictionaryOfStringString. + private static readonly EdmPrimitiveTypeReference DictionaryOfStringStringTypeReference = ToTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString), true); + /// Type reference for Edm.Double. private static readonly EdmPrimitiveTypeReference DoubleTypeReference = ToTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Double), false); @@ -94,6 +100,8 @@ static EdmLibraryExtensions() PrimitiveTypeReferenceMap.Add(typeof(Boolean), BooleanTypeReference); PrimitiveTypeReferenceMap.Add(typeof(Byte), ByteTypeReference); PrimitiveTypeReferenceMap.Add(typeof(Decimal), DecimalTypeReference); + PrimitiveTypeReferenceMap.Add(typeof(Dictionary), DictionaryOfStringObjectTypeReference); + PrimitiveTypeReferenceMap.Add(typeof(Dictionary), DictionaryOfStringStringTypeReference); PrimitiveTypeReferenceMap.Add(typeof(Double), DoubleTypeReference); PrimitiveTypeReferenceMap.Add(typeof(Int16), Int16TypeReference); PrimitiveTypeReferenceMap.Add(typeof(Int32), Int32TypeReference); @@ -601,7 +609,7 @@ internal static bool IsPrimitiveType(Type clrType) return true; } - return PrimitiveTypeReferenceMap.ContainsKey(clrType) || typeof(ISpatial).IsAssignableFrom(clrType) || typeof(IDictionary).IsAssignableFrom(clrType); + return PrimitiveTypeReferenceMap.ContainsKey(clrType) || typeof(ISpatial).IsAssignableFrom(clrType) || typeof(IDictionary).IsAssignableFrom(clrType); } /// @@ -1474,7 +1482,15 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(Type clrTyp // If it didn't work, try spatial types which need assignability. IEdmPrimitiveType primitiveType = null; - if (typeof(GeographyPoint).IsAssignableFrom(clrType)) + if (typeof(IDictionary).IsAssignableFrom(clrType)) + { + primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringObject); + } + else if (typeof(IDictionary).IsAssignableFrom(clrType)) + { + primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString); + } + else if (typeof(GeographyPoint).IsAssignableFrom(clrType)) { primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.GeographyPoint); } @@ -1538,10 +1554,6 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(Type clrTyp { primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Geometry); } - else if (typeof(IDictionary).IsAssignableFrom(clrType)) - { - primitiveType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString); - } if (primitiveType == null) { @@ -2005,6 +2017,9 @@ private static EdmPrimitiveTypeReference ToTypeReference(IEdmPrimitiveType primi { case EdmPrimitiveTypeKind.Boolean: case EdmPrimitiveTypeKind.Byte: + case EdmPrimitiveTypeKind.Date: + case EdmPrimitiveTypeKind.DictionaryOfStringObject: + case EdmPrimitiveTypeKind.DictionaryOfStringString: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Guid: case EdmPrimitiveTypeKind.Int16: @@ -2013,7 +2028,6 @@ private static EdmPrimitiveTypeReference ToTypeReference(IEdmPrimitiveType primi case EdmPrimitiveTypeKind.SByte: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Stream: - case EdmPrimitiveTypeKind.Date: case EdmPrimitiveTypeKind.PrimitiveType: return new EdmPrimitiveTypeReference(primitiveType, nullable); case EdmPrimitiveTypeKind.Binary: @@ -2043,8 +2057,6 @@ private static EdmPrimitiveTypeReference ToTypeReference(IEdmPrimitiveType primi case EdmPrimitiveTypeKind.GeometryMultiPoint: case EdmPrimitiveTypeKind.GeometryCollection: return new EdmSpatialTypeReference(primitiveType, nullable); - case EdmPrimitiveTypeKind.DictionaryOfStringString: - return new EdmDictionaryOfStringStringTypeReference(primitiveType, nullable); default: throw new ODataException(ErrorStrings.General_InternalError(InternalErrorCodesCommon.EdmLibraryExtensions_PrimitiveTypeReference)); } diff --git a/src/Microsoft.OData.Core/PrimitiveConverter.cs b/src/Microsoft.OData.Core/PrimitiveConverter.cs index 81ef8eaaa6..b0b56c5d0d 100644 --- a/src/Microsoft.OData.Core/PrimitiveConverter.cs +++ b/src/Microsoft.OData.Core/PrimitiveConverter.cs @@ -21,15 +21,18 @@ namespace Microsoft.OData /// internal sealed class PrimitiveConverter { + /// Instance of DictionaryStringObject to register for Dictionary of String, Object types. + private static readonly IPrimitiveTypeConverter dictionaryStringObjectTypeConverter = new DictionaryOfStringObjectTypeConverter(); + + /// Instance of DictionaryStringObject to register for Dictionary of String, String types. + private static readonly IPrimitiveTypeConverter dictionaryStringStringTypeConverter = new DictionaryOfStringStringTypeConverter(); + /// Instance of GeographyTypeConverter to register for all Geography types. private static readonly IPrimitiveTypeConverter geographyTypeConverter = new GeographyTypeConverter(); /// Instance of GeographyTypeConverter to register for all Geography types. private static readonly IPrimitiveTypeConverter geometryTypeConverter = new GeometryTypeConverter(); - /// Instance of DictionaryTypeConverter to register for all Dictionary types. - private static readonly IPrimitiveTypeConverter dictionaryStringStringTypeConverter = new DictionaryOfStringStringTypeConverter(); - /// Set of type converters that implement their own conversion using IPrimitiveTypeConverter. private static readonly PrimitiveConverter primitiveConverter = new PrimitiveConverter( @@ -121,6 +124,11 @@ private bool TryGetConverter(Type type, out IPrimitiveTypeConverter primitiveTyp primitiveTypeConverter = bestMatch.Value; return bestMatch.Value != null; } + else if (typeof(IDictionary).IsAssignableFrom(type)) + { + primitiveTypeConverter = dictionaryStringObjectTypeConverter; + return true; + } else if (typeof(IDictionary).IsAssignableFrom(type)) { primitiveTypeConverter = dictionaryStringStringTypeConverter; diff --git a/src/Microsoft.OData.Edm/EdmModelVisitor.cs b/src/Microsoft.OData.Edm/EdmModelVisitor.cs index 7bd8c75a89..49f6103544 100644 --- a/src/Microsoft.OData.Edm/EdmModelVisitor.cs +++ b/src/Microsoft.OData.Edm/EdmModelVisitor.cs @@ -306,6 +306,8 @@ public void VisitPrimitiveTypeReference(IEdmPrimitiveTypeReference reference) break; case EdmPrimitiveTypeKind.Boolean: case EdmPrimitiveTypeKind.Byte: + case EdmPrimitiveTypeKind.DictionaryOfStringObject: + case EdmPrimitiveTypeKind.DictionaryOfStringString: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Guid: case EdmPrimitiveTypeKind.Int16: @@ -317,7 +319,6 @@ public void VisitPrimitiveTypeReference(IEdmPrimitiveTypeReference reference) case EdmPrimitiveTypeKind.Date: case EdmPrimitiveTypeKind.PrimitiveType: case EdmPrimitiveTypeKind.None: - case EdmPrimitiveTypeKind.DictionaryOfStringString: this.ProcessPrimitiveTypeReference(reference); break; default: diff --git a/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs b/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs index 0d8b6083c2..152e06b0b6 100644 --- a/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs +++ b/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs @@ -541,6 +541,94 @@ public static bool IsStream(this IEdmType type) return primitiveType.PrimitiveKind == EdmPrimitiveTypeKind.Stream; } + /// + /// Returns true if this reference refers to a dictionary type. + /// + /// Type reference. + /// This reference refers to a dictionary type. + public static bool IsDictionaryOfStringObject(this IEdmTypeReference type) + { + EdmUtil.CheckArgumentNull(type, "type"); + return type.Definition.IsDictionaryOfStringObject(); + } + + /// + /// Returns true if this definition refers to a dictionary type. + /// + /// Type reference. + /// This definition refers to a dictionary type. + public static bool IsDictionaryOfStringObject(this IEdmType type) + { + EdmUtil.CheckArgumentNull(type, "type"); + IEdmPrimitiveType primitiveType = type as IEdmPrimitiveType; + if (primitiveType == null) + { + return false; + } + + return primitiveType.PrimitiveKind.IsDictionaryOfStringObject(); + } + + /// + /// Returns true if this type kind represents a dictionary type. + /// + /// Type reference. + /// This kind refers to a dictionary type. + public static bool IsDictionaryOfStringObject(this EdmPrimitiveTypeKind typeKind) + { + switch (typeKind) + { + case EdmPrimitiveTypeKind.DictionaryOfStringObject: + return true; + } + + return false; + } + + /// + /// Returns true if this reference refers to a dictionary type. + /// + /// Type reference. + /// This reference refers to a dictionary type. + public static bool IsDictionaryOfStringString(this IEdmTypeReference type) + { + EdmUtil.CheckArgumentNull(type, "type"); + return type.Definition.IsDictionaryOfStringString(); + } + + /// + /// Returns true if this definition refers to a dictionary type. + /// + /// Type reference. + /// This definition refers to a dictionary type. + public static bool IsDictionaryOfStringString(this IEdmType type) + { + EdmUtil.CheckArgumentNull(type, "type"); + IEdmPrimitiveType primitiveType = type as IEdmPrimitiveType; + if (primitiveType == null) + { + return false; + } + + return primitiveType.PrimitiveKind.IsDictionaryOfStringString(); + } + + /// + /// Returns true if this type kind represents a dictionary type. + /// + /// Type reference. + /// This kind refers to a dictionary type. + public static bool IsDictionaryOfStringString(this EdmPrimitiveTypeKind typeKind) + { + switch (typeKind) + { + case EdmPrimitiveTypeKind.DictionaryOfStringString: + return true; + } + + return false; + } + /// /// Returns true if this reference refers to a spatial type. /// @@ -702,50 +790,6 @@ public static bool IsGeometry(this EdmPrimitiveTypeKind typeKind) return false; } - /// - /// Returns true if this reference refers to a dictionary type. - /// - /// Type reference. - /// This reference refers to a dictionary type. - public static bool IsDictionary(this IEdmTypeReference type) - { - EdmUtil.CheckArgumentNull(type, "type"); - return type.Definition.IsDictionary(); - } - - /// - /// Returns true if this definition refers to a dictionary type. - /// - /// Type reference. - /// This definition refers to a dictionary type. - public static bool IsDictionary(this IEdmType type) - { - EdmUtil.CheckArgumentNull(type, "type"); - IEdmPrimitiveType primitiveType = type as IEdmPrimitiveType; - if (primitiveType == null) - { - return false; - } - - return primitiveType.PrimitiveKind.IsDictionary(); - } - - /// - /// Returns true if this type kind represents a dictionary type. - /// - /// Type reference. - /// This kind refers to a dictionary type. - public static bool IsDictionary(this EdmPrimitiveTypeKind typeKind) - { - switch (typeKind) - { - case EdmPrimitiveTypeKind.DictionaryOfStringString: - return true; - } - - return false; - } - #endregion // The As*** functions never return null -- if the supplied type does not have the appropriate shape, an encoding of a bad type is returned. @@ -775,6 +819,8 @@ public static IEdmPrimitiveTypeReference AsPrimitive(this IEdmTypeReference type case EdmPrimitiveTypeKind.Boolean: case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Date: + case EdmPrimitiveTypeKind.DictionaryOfStringObject: + case EdmPrimitiveTypeKind.DictionaryOfStringString: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Guid: case EdmPrimitiveTypeKind.Int16: @@ -1334,6 +1380,8 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(this IEdmPr case EdmPrimitiveTypeKind.Boolean: case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Date: + case EdmPrimitiveTypeKind.DictionaryOfStringObject: + case EdmPrimitiveTypeKind.DictionaryOfStringString: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Guid: case EdmPrimitiveTypeKind.Int16: @@ -1371,8 +1419,6 @@ internal static IEdmPrimitiveTypeReference GetPrimitiveTypeReference(this IEdmPr case EdmPrimitiveTypeKind.GeometryMultiLineString: case EdmPrimitiveTypeKind.GeometryMultiPoint: return new EdmSpatialTypeReference(type, isNullable); - case EdmPrimitiveTypeKind.DictionaryOfStringString: - return new EdmDictionaryOfStringStringTypeReference(type, isNullable); default: throw new InvalidOperationException(Edm.Strings.EdmPrimitive_UnexpectedKind); } diff --git a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs index f13c27d988..f1b84ba0ce 100644 --- a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs +++ b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs @@ -56,6 +56,8 @@ private EdmCoreModel() new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.Date), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.Decimal), + new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringObject), + new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.Binary), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.String), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.Stream), @@ -76,7 +78,6 @@ private EdmCoreModel() new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPolygon), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiLineString), new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPoint), - new EdmCoreModelPrimitiveType(EdmPrimitiveTypeKind.DictionaryOfStringString), primitiveType, // Edm.PrimitiveType }; diff --git a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs index d52927ab40..d5fd7876fe 100644 --- a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs +++ b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPrimitiveType.cs @@ -176,6 +176,16 @@ public enum EdmPrimitiveTypeKind /// Date, + /// + /// Represents a Dictionary of String, Object type. + /// + DictionaryOfStringObject, + + /// + /// Represents a Dictionary of String, String type. + /// + DictionaryOfStringString, + /// /// Represents a TimeOfDay type /// @@ -185,11 +195,6 @@ public enum EdmPrimitiveTypeKind /// Represents a Primitive type /// PrimitiveType, - - /// - /// Represents a Dictionary of String, String - /// - DictionaryOfStringString, } /// diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs index 2f727d0aec..c9c4bf98bb 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs @@ -26,7 +26,7 @@ public void NamespacePropertyShouldReturnCorrectNamespaceString() [Fact] public void SchemaElementsShouldReturnCorrectSchemaElementCount() { - Assert.Equal(41, EdmCoreModel.Instance.SchemaElements.Count()); + Assert.Equal(42, EdmCoreModel.Instance.SchemaElements.Count()); } [Theory]