Skip to content

Commit

Permalink
Resolve the comments and add more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xuzhg committed Aug 28, 2018
1 parent 56ca1fc commit 12d998c
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 34 deletions.
23 changes: 16 additions & 7 deletions src/Microsoft.AspNet.OData.Shared/Builder/EdmModelHelperMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -440,13 +440,7 @@ private static Dictionary<Type, IEdmType> AddTypes(this EdmModel model, EdmTypeM
// add annotation for properties
Dictionary<PropertyInfo, IEdmProperty> edmProperties = edmTypeMap.EdmProperties;
model.AddClrPropertyInfoAnnotations(edmProperties);

// add Enum mapping annotation
if (edmTypeMap.EnumMembers != null && edmTypeMap.EnumMembers.Any())
{
model.SetAnnotationValue(model, new ClrEnumMemberAnnotation(edmTypeMap.EnumMembers));
}

model.AddClrEnumMemberInfoAnnotations(edmTypeMap);
model.AddPropertyRestrictionsAnnotations(edmTypeMap.EdmPropertiesRestrictions);
model.AddPropertiesQuerySettings(edmTypeMap.EdmPropertiesQuerySettings);
model.AddStructuredTypeQuerySettings(edmTypeMap.EdmStructuredTypeQuerySettings);
Expand Down Expand Up @@ -522,6 +516,21 @@ private static void AddClrPropertyInfoAnnotations(this EdmModel model, Dictionar
}
}

private static void AddClrEnumMemberInfoAnnotations(this EdmModel model, EdmTypeMap edmTypeMap)
{
if (edmTypeMap.EnumMembers == null || !edmTypeMap.EnumMembers.Any())
{
return;
}

var enumGroupBy = edmTypeMap.EnumMembers.GroupBy(e => e.Key.GetType(), e => e);
foreach (var enumGroup in enumGroupBy)
{
IEdmType edmType = edmTypeMap.EdmTypes[enumGroup.Key];
model.SetAnnotationValue(edmType, new ClrEnumMemberAnnotation(enumGroup.ToDictionary(e => e.Key, e => e.Value)));
}
}

private static void AddDynamicPropertyDictionaryAnnotations(this EdmModel model,
Dictionary<IEdmStructuredType, PropertyInfo> openTypes)
{
Expand Down
28 changes: 10 additions & 18 deletions src/Microsoft.AspNet.OData.Shared/ClrEnumMemberAnnotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
namespace Microsoft.AspNet.OData
{
/// <summary>
/// Represents a mapping from an <see cref="IEdmEnumMember"/> to a CLR Enum member.
/// Represents a mapping betwwen an <see cref="IEdmEnumMember"/> and a CLR Enum member.
/// </summary>
public class ClrEnumMemberAnnotation
{
private IDictionary<Enum, IEdmEnumMember> _maps;
private IDictionary<IEdmEnumMember, Enum> _reverseMaps;
private IDictionary<Enum, IEdmEnumMember> _map;
private IDictionary<IEdmEnumMember, Enum> _reverseMap;

/// <summary>
/// Initializes a new instance of <see cref="ClrEnumMemberAnnotation"/> class.
Expand All @@ -27,11 +27,11 @@ public ClrEnumMemberAnnotation(IDictionary<Enum, IEdmEnumMember> map)
throw Error.ArgumentNull("map");
}

_maps = map;
_reverseMaps = new Dictionary<IEdmEnumMember, Enum>();
_map = map;
_reverseMap = new Dictionary<IEdmEnumMember, Enum>();
foreach (var item in map)
{
_reverseMaps.Add(item.Value, item.Key);
_reverseMap.Add(item.Value, item.Key);
}
}

Expand All @@ -43,12 +43,8 @@ public ClrEnumMemberAnnotation(IDictionary<Enum, IEdmEnumMember> map)
public IEdmEnumMember GetEdmEnumMember(Enum clrEnumMemberInfo)
{
IEdmEnumMember value;
if (_maps.TryGetValue(clrEnumMemberInfo, out value))
{
return value;
}

return null;
_map.TryGetValue(clrEnumMemberInfo, out value);
return value;
}

/// <summary>
Expand All @@ -59,12 +55,8 @@ public IEdmEnumMember GetEdmEnumMember(Enum clrEnumMemberInfo)
public Enum GetClrEnumMember(IEdmEnumMember edmEnumMember)
{
Enum value;
if (_reverseMaps.TryGetValue(edmEnumMember, out value))
{
return value;
}

return null;
_reverseMap.TryGetValue(edmEnumMember, out value);
return value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public override object ReadInline(object item, IEdmTypeReference edmType, ODataD
}

IEdmEnumTypeReference enumTypeReference = (IEdmEnumTypeReference)edmType;
IEdmEnumType enumType = enumTypeReference.EnumDefinition();
ODataEnumValue enumValue = item as ODataEnumValue;
if (readContext.IsUntyped)
{
Expand All @@ -69,11 +70,9 @@ public override object ReadInline(object item, IEdmTypeReference edmType, ODataD
}

// Enum member supports model alias case. So, try to use the Edm member name to retrieve the Enum value.
var memberMapAnnotation = readContext.Model.GetClrEnumMemberAnnotation();
var memberMapAnnotation = readContext.Model.GetClrEnumMemberAnnotation(enumType);
if (memberMapAnnotation != null)
{
IEdmEnumType enumType = enumTypeReference.EnumDefinition();

if (enumValue != null)
{
IEdmEnumMember enumMember = enumType.Members.FirstOrDefault(m => m.Name == enumValue.Value);
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.AspNet.OData.Shared/Formatter/EdmLibHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -704,14 +704,14 @@ public static string GetClrPropertyName(IEdmProperty edmProperty, IEdmModel edmM
return propertyName;
}

public static ClrEnumMemberAnnotation GetClrEnumMemberAnnotation(this IEdmModel edmModel)
public static ClrEnumMemberAnnotation GetClrEnumMemberAnnotation(this IEdmModel edmModel, IEdmEnumType enumType)
{
if (edmModel == null)
{
throw Error.ArgumentNull("edmModel");
}

ClrEnumMemberAnnotation annotation = edmModel.GetAnnotationValue<ClrEnumMemberAnnotation>(edmModel);
ClrEnumMemberAnnotation annotation = edmModel.GetAnnotationValue<ClrEnumMemberAnnotation>(enumType);
if (annotation != null)
{
return annotation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public virtual ODataEnumValue CreateODataEnumValue(object graph, IEdmEnumTypeRef
}

// Enum member supports model alias case. So, try to use the Edm member name to create Enum value.
var memberMapAnnotation = writeContext.Model.GetClrEnumMemberAnnotation();
var memberMapAnnotation = writeContext.Model.GetClrEnumMemberAnnotation(enumType.EnumDefinition());
if (memberMapAnnotation != null)
{
var edmEnumMember = memberMapAnnotation.GetEdmEnumMember((Enum)graph);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,12 +1084,20 @@ public void ODataConventionModelBuilder_DataContractAttribute_WorksOnEnumType()
// Assert
IEdmEnumType enumType = model.SchemaElements.OfType<IEdmEnumType>().Single();
Assert.NotNull(enumType);
Assert.Equal(3, enumType.Members.Count());
Assert.Equal(4, enumType.Members.Count());
Assert.Equal("Feelings", enumType.Name);
Assert.Equal("Test", enumType.Namespace);
Assert.Contains(enumType.Members, (m) => m.Name.Equals("happy"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("sad"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("KeepDefaultName"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("soso"));

var annotation = model.GetClrEnumMemberAnnotation(enumType);
Assert.NotNull(annotation);

IEdmEnumMember enumMember = enumType.Members.Single(m => m.Name.Equals("soso"));
Assert.Same(enumMember, annotation.GetEdmEnumMember(Life.NotTooBad));
Assert.Equal(Life.NotTooBad, annotation.GetClrEnumMember(enumMember));
}

[Fact]
Expand Down Expand Up @@ -1118,13 +1126,14 @@ public void ODataConventionModelBuilder_DataContractAttribute_WithAddedExplicitl
// Assert
IEdmEnumType enumType = model.SchemaElements.OfType<IEdmEnumType>().Single();
Assert.NotNull(enumType);
Assert.Equal(4, enumType.Members.Count());
Assert.Equal(5, enumType.Members.Count());
Assert.Equal("Feelings", enumType.Name);
Assert.Equal("Test", enumType.Namespace);
Assert.Contains(enumType.Members, (m) => m.Name.Equals("happy"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("sad"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("JustSoSo"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("KeepDefaultName"));
Assert.Contains(enumType.Members, (m) => m.Name.Equals("soso"));
}

private IEdmStructuredType AddComplexTypeWithODataConventionModelBuilder()
Expand Down Expand Up @@ -1192,10 +1201,16 @@ public enum Life
{
[EnumMember(Value = "happy")]
Happy = 1,

[EnumMember(Value = "sad")]
Sad = 2,

JustSoSo = 3,

[EnumMember]
KeepDefaultName
KeepDefaultName = 4,

[EnumMember(Value = "soso")]
NotTooBad
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using Microsoft.AspNet.OData.Formatter.Deserialization;
using Microsoft.AspNet.OData.Test.Abstraction;
using Microsoft.OData;
Expand Down Expand Up @@ -68,6 +69,32 @@ public void ReadFromStreamAsync_ForUnType()
Assert.Equal("Blue", color.Value);
}

[Fact]
public void ReadFromStreamAsync_ModelAlias()
{
// Arrange
string content = "{\"@odata.type\":\"#NS.level\",\"value\":\"veryhigh\"}";

var builder = ODataConventionModelBuilderFactory.Create();
builder.EnumType<Level>().Namespace = "NS";
IEdmModel model = builder.GetEdmModel();

ODataEnumDeserializer deserializer = new ODataEnumDeserializer();
ODataDeserializerContext readContext = new ODataDeserializerContext
{
Model = model,
ResourceType = typeof(Level)
};

// Act
object value = deserializer.Read(GetODataMessageReader(GetODataMessage(content), model),
typeof(Level), readContext);

// Assert
Level level = Assert.IsType<Level>(value);
Assert.Equal(Level.High, level);
}

private static ODataMessageReader GetODataMessageReader(IODataRequestMessage oDataRequestMessage, IEdmModel edmModel)
{
return new ODataMessageReader(oDataRequestMessage, new ODataMessageReaderSettings(), edmModel);
Expand Down Expand Up @@ -97,5 +124,14 @@ public enum Color
Blue,
Green
}

[DataContract(Name = "level")]
public enum Level
{
[EnumMember(Value = "low")]
Low,
[EnumMember(Value = "veryhigh")]
High
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

using Microsoft.AspNet.OData.Formatter;
using Microsoft.AspNet.OData.Formatter.Serialization;
using Microsoft.AspNet.OData.Test.Abstraction;
using Microsoft.OData;
using Microsoft.OData.Edm;
using System.Linq;
using System.Runtime.Serialization;
using Xunit;

namespace Microsoft.AspNet.OData.Test.Formatter.Serialization
Expand Down Expand Up @@ -60,5 +63,39 @@ public void AddTypeNameAnnotationAsNeeded_AddsNullAnnotation_InNoMetadataMode()
Assert.NotNull(annotation);
Assert.Null(annotation.TypeName);
}

[Fact]
public void CreateODataEnumValue_ReturnsCorrectEnumMember()
{
// Arrange
var builder = ODataConventionModelBuilderFactory.Create();
builder.EnumType<BookCategory>().Namespace = "NS";
IEdmModel model = builder.GetEdmModel();
IEdmEnumType enumType = model.SchemaElements.OfType<IEdmEnumType>().Single();

var provider = new DefaultODataSerializerProvider(new MockContainer());
ODataEnumSerializer serializer = new ODataEnumSerializer(provider);
ODataSerializerContext writeContext = new ODataSerializerContext
{
Model = model
};

// Act
ODataEnumValue value = serializer.CreateODataEnumValue(BookCategory.Newspaper,
new EdmEnumTypeReference(enumType, false), writeContext);

// Assert
Assert.NotNull(value);
Assert.Equal("news", value.Value);
}
}

[DataContract(Name = "category")]
public enum BookCategory
{
[EnumMember(Value = "cartoon")]
Cartoon,
[EnumMember(Value = "news")]
Newspaper
}
}

0 comments on commit 12d998c

Please sign in to comment.