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/DictionaryOfStringStringTypeConverter.cs b/src/Microsoft.OData.Core/DictionaryOfStringStringTypeConverter.cs new file mode 100644 index 0000000000..498657845a --- /dev/null +++ b/src/Microsoft.OData.Core/DictionaryOfStringStringTypeConverter.cs @@ -0,0 +1,61 @@ +//--------------------------------------------------------------------- +// +// 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 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 = (IDictionary)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/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 3747ed7438..f7ec6c6fbd 100644 --- a/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs +++ b/src/Microsoft.OData.Core/Json/ODataJsonReaderCoreUtils.cs @@ -80,6 +80,84 @@ 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, + 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.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. + 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 fd26779c8e..b72909553e 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightPropertyAndValueDeserializer.cs @@ -1457,6 +1457,28 @@ private object ReadPrimitiveValue(bool insideJsonObjectValue, IEdmPrimitiveTypeR this.recursionDepth, propertyName); } + 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, + insideJsonObjectValue, + this.JsonLightInputContext, + expectedValueTypeReference, + validateNullValue, + this.recursionDepth, + propertyName); + } else { if (insideJsonObjectValue) diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightValueSerializer.cs index a7220b2a05..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()) + 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 affaa69bbc..85490612bf 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); + 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); } @@ -2001,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: @@ -2009,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: diff --git a/src/Microsoft.OData.Core/Microsoft.OData.Core.cs b/src/Microsoft.OData.Core/Microsoft.OData.Core.cs index aed89093c2..6c13bd7b07 100644 --- a/src/Microsoft.OData.Core/Microsoft.OData.Core.cs +++ b/src/Microsoft.OData.Core/Microsoft.OData.Core.cs @@ -469,6 +469,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 adfc4101aa..e41f0353d7 100644 --- a/src/Microsoft.OData.Core/Microsoft.OData.Core.txt +++ b/src/Microsoft.OData.Core/Microsoft.OData.Core.txt @@ -535,6 +535,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 4ef227f7e9..56c08e2a4f 100644 --- a/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs +++ b/src/Microsoft.OData.Core/Parameterized.Microsoft.OData.Core.cs @@ -4107,6 +4107,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." /// diff --git a/src/Microsoft.OData.Core/PrimitiveConverter.cs b/src/Microsoft.OData.Core/PrimitiveConverter.cs index b1fff304a7..b0b56c5d0d 100644 --- a/src/Microsoft.OData.Core/PrimitiveConverter.cs +++ b/src/Microsoft.OData.Core/PrimitiveConverter.cs @@ -21,6 +21,12 @@ 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(); @@ -118,6 +124,16 @@ 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; + return true; + } else { primitiveTypeConverter = null; diff --git a/src/Microsoft.OData.Edm/EdmModelVisitor.cs b/src/Microsoft.OData.Edm/EdmModelVisitor.cs index a69f276d40..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: diff --git a/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs b/src/Microsoft.OData.Edm/ExtensionMethods/EdmTypeSemantics.cs index 98b8b8d37b..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. /// @@ -731,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: @@ -1290,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: diff --git a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModel.cs index 3fe2228bed..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), 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..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 /// diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Schema/EdmCoreModelTests.cs index 11b570c9a8..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(40, EdmCoreModel.Instance.SchemaElements.Count()); + Assert.Equal(42, EdmCoreModel.Instance.SchemaElements.Count()); } [Theory]