Skip to content

Commit

Permalink
Retrieve the content type for stream property from vocabulary annotat…
Browse files Browse the repository at this point in the history
…ion by convention (#1995)

* Retrieve the content type for stream property form vocabulary annotation by default

* Address the comments

* Fix failing test cases
  • Loading branch information
xuzhg authored Feb 11, 2021
1 parent 325e283 commit a08accf
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ internal interface IODataResourceMetadataContext
/// </summary>
IODataResourceTypeContext TypeContext { get; }

/// <summary>
/// The actual structured type of the resource.
/// </summary>
IEdmStructuredType ActualResourceType { get; }

/// <summary>
/// The actual structured type of the resource, i.e. ODataResource.TypeName.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ namespace Microsoft.OData.Evaluation
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies.V1;
#endregion

/// <summary>
Expand Down Expand Up @@ -230,6 +232,19 @@ internal override ODataStreamReferenceValue GetMediaResource()
{
this.computedMediaResource = new ODataStreamReferenceValue();
this.computedMediaResource.SetMetadataBuilder(this, /*propertyName*/ null);

// from OData spec: Media entity types MAY specify a list of acceptable media types using an annotation with term Core.AcceptableMediaTypes
IEdmEntityType entityType = this.ResourceMetadataContext.ActualResourceType as IEdmEntityType;
if (entityType != null)
{
var mediaTypes = this.MetadataContext.Model.GetVocabularyStringCollection(entityType, CoreVocabularyModel.AcceptableMediaTypesTerm);
if (mediaTypes.Count() == 1)
{
// Be noted: AcceptableMediaTypes might have more than one media type,
// Convention (default) behavior only works if AcceptableMediaTypes is a collection of one.
this.computedMediaResource.ContentType = mediaTypes.ElementAt(0);
}
}
}

return this.computedMediaResource;
Expand Down Expand Up @@ -426,6 +441,17 @@ private IEnumerable<ODataProperty> GetComputedStreamProperties(IEnumerable<OData
{
ODataStreamReferenceValue streamPropertyValue = new ODataStreamReferenceValue();
streamPropertyValue.SetMetadataBuilder(this, missingStreamPropertyName);

// by default, let's retrieve the content type from vocabulary annotation
var edmProperty = projectedStreamProperties[missingStreamPropertyName];
var mediaTypes = this.MetadataContext.Model.GetVocabularyStringCollection(edmProperty, CoreVocabularyModel.AcceptableMediaTypesTerm);
if (mediaTypes.Count() == 1)
{
// Be noted: AcceptableMediaTypes might have more than one media type,
// Convention (default) behavior only works if AcceptableMediaTypes is a collection of one.
streamPropertyValue.ContentType = mediaTypes.ElementAt(0);
}

this.computedStreamProperties.Add(new ODataProperty { Name = missingStreamPropertyName, Value = streamPropertyValue });
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Microsoft.OData.Evaluation
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.OData.Edm.Vocabularies.V1;
using Microsoft.OData.JsonLight;
#endregion

Expand Down Expand Up @@ -428,13 +429,24 @@ internal override ODataProperty GetNextUnprocessedStreamProperty()
string propertyName = unprocessedStreamProperties.Current;
ODataStreamReferenceValue streamPropertyValue = new ODataStreamReferenceValue();
streamPropertyValue.SetMetadataBuilder(this, propertyName);

// by default, let's retrieve the content type from vocabulary annotation
var edmProperty = this.ResourceMetadataContext.SelectedStreamProperties[propertyName];
var mediaTypes = this.MetadataContext.Model.GetVocabularyStringCollection(edmProperty, CoreVocabularyModel.AcceptableMediaTypesTerm);
if (mediaTypes.Count() == 1)
{
// Be noted: AcceptableMediaTypes might have more than one media type,
// Convention (default) behavior only works if AcceptableMediaTypes is a collection of one.
streamPropertyValue.ContentType = mediaTypes.ElementAt(0);
}

return new ODataProperty { Name = propertyName, Value = streamPropertyValue };
}

return null;
}

//// Stream content type and ETag can't be computed from conventions.
//// Stream content type and ETag can't be computed from conventions, but it can retrieve from the vocabulary annoation?

/// <summary>
/// Gets the navigation link URI for the specified navigation property.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ public IODataResourceTypeContext TypeContext
get { return this.typeContext; }
}

/// <summary>
/// The actual structured type of the resource.
/// </summary>
public IEdmStructuredType ActualResourceType { get; set; }

/// <summary>
/// The actual structured type of the resource, i.e. ODataResource.TypeName.
/// </summary>
Expand Down Expand Up @@ -143,10 +148,16 @@ internal static ODataResourceMetadataContext Create(
{
if (serializationInfo != null)
{
return new ODataResourceMetadataContextWithoutModel(resource, typeContext, serializationInfo, requiresId);
return new ODataResourceMetadataContextWithoutModel(resource, typeContext, serializationInfo, requiresId)
{
ActualResourceType = actualResourceType
};
}

return new ODataResourceMetadataContextWithModel(resource, typeContext, actualResourceType, metadataContext, selectedProperties, metadataSelector, requiresId);
return new ODataResourceMetadataContextWithModel(resource, typeContext, actualResourceType, metadataContext, selectedProperties, metadataSelector, requiresId)
{
ActualResourceType = actualResourceType
};
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//---------------------------------------------------------------------
// <copyright file="VocabularyAnnotationExtensions.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

using System.Collections.Generic;
using System.Linq;

namespace Microsoft.OData.Edm.Vocabularies.V1
{
/// <summary>
/// Extension methods for the vocabulary annotations.
/// </summary>
public static class VocabularyAnnotationExtensions
{
/// <summary>
/// Gets the collection of string for a target annotatable.
/// </summary>
/// <param name="model">The model referenced to.</param>
/// <param name="target">The target annotatable to find annotation.</param>
/// <param name="term">The target annotatable to find annotation.</param>
/// <returns>Null or a collection string of qualified type name.</returns>
public static IEnumerable<string> GetVocabularyStringCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
{
EdmUtil.CheckArgumentNull(model, "model");
EdmUtil.CheckArgumentNull(target, "target");
EdmUtil.CheckArgumentNull(target, "term");

IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(target, term).FirstOrDefault();
if (annotation != null)
{
IEdmCollectionExpression collectionExpression = annotation.Value as IEdmCollectionExpression;
if (collectionExpression != null && collectionExpression.Elements != null)
{
return collectionExpression.Elements.OfType<IEdmStringConstantExpression>().Select(e => e.Value);
}
}

return Enumerable.Empty<string>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,8 @@ internal class TestEntryMetadataContext : IODataResourceMetadataContext
public IDictionary<string, IEdmStructuralProperty> SelectedStreamProperties { get; set; }

public IEnumerable<IEdmOperation> SelectedBindableOperations { get; set; }

public IEdmStructuredType ActualResourceType { get; set; }
}

internal class TestFeedAndEntryTypeContext : IODataResourceTypeContext
Expand Down

0 comments on commit a08accf

Please sign in to comment.