Skip to content
This repository was archived by the owner on Jun 20, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9e35332
Generate stream paths for navigation properties
irvinesunday Sep 2, 2020
bf234c9
Refactor out stream path generation into separate function
irvinesunday Sep 2, 2020
da8a2d2
Create base class for media entity operations handler
irvinesunday Sep 2, 2020
39645b1
Add new stream segments conditional checks when creating a NavPropPath
irvinesunday Sep 2, 2020
df4ac10
Add Get and Put operation ids for single-valued nav. prop. paths
irvinesunday Sep 2, 2020
1deb55d
Update handler with support for both Entityset/Singleton stream paths
irvinesunday Sep 2, 2020
468bf78
Update tests to validate the stream paths updates
irvinesunday Sep 2, 2020
654ba30
Revert removed modifier
irvinesunday Sep 2, 2020
4b0a872
Add support for creating a media entity
irvinesunday Sep 7, 2020
b8c74b3
Update tests to validate POST operation for creating media entity
irvinesunday Sep 7, 2020
323ae20
Comment update
irvinesunday Sep 7, 2020
d6dc0a3
Refactor out common code into private methods
irvinesunday Sep 9, 2020
e3ba126
Remove unnecessary schema definition
irvinesunday Sep 9, 2020
4308909
Add application/json content type for RequestBody in media entity POST
irvinesunday Sep 9, 2020
77333d7
Add application/json content in RequestBody
irvinesunday Sep 9, 2020
15fa8d5
Merge branch 'is/nav-prop-stream-paths' into is/media-entity-post
irvinesunday Sep 9, 2020
c3e4e0d
Nitpick: format code
irvinesunday Sep 9, 2020
da22a62
Merge branch 'is/nav-prop-stream-paths' into is/media-entity-post
irvinesunday Sep 9, 2020
1889069
Add application/json content type for media entities RequestBody/Resp…
irvinesunday Sep 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 40 additions & 23 deletions src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,44 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource
}

// media entity
RetrieveMediaEntityStreamPaths(entityType, path);

// navigation property
foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties())
{
if (CanFilter(np))
{
RetrieveNavigationPropertyPaths(np, path);
}
}

if (entitySet != null)
{
path.Pop(); // end of entity
}

path.Pop(); // end of navigation source.
Debug.Assert(path.Any() == false);
}

/// <summary>
/// Retrieves the paths for a media entity stream.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="currentPath">The current OData path.</param>
private void RetrieveMediaEntityStreamPaths(IEdmEntityType entityType, ODataPath currentPath)
{
Debug.Assert(entityType != null);
Debug.Assert(currentPath != null);

bool createValuePath = true;
foreach (IEdmStructuralProperty sp in entityType.DeclaredStructuralProperties())
{
if (sp.Type.AsPrimitive().IsStream())
{
path.Push(new ODataStreamPropertySegment(sp.Name));
AppendPath(path.Clone());
path.Pop();
currentPath.Push(new ODataStreamPropertySegment(sp.Name));
AppendPath(currentPath.Clone());
currentPath.Pop();
}

if (sp.Name.Equals("content", System.StringComparison.OrdinalIgnoreCase))
Expand All @@ -205,27 +235,10 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource
*/
if (createValuePath && entityType.HasStream)
{
path.Push(new ODataStreamContentSegment());
AppendPath(path.Clone());
path.Pop();
currentPath.Push(new ODataStreamContentSegment());
AppendPath(currentPath.Clone());
currentPath.Pop();
}

// navigation property
foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties())
{
if (CanFilter(np))
{
RetrieveNavigationPropertyPaths(np, path);
}
}

if (entitySet != null)
{
path.Pop(); // end of entity
}

path.Pop(); // end of navigation source.
Debug.Assert(path.Any() == false);
}

/// <summary>
Expand Down Expand Up @@ -284,6 +297,10 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr
}
}
}

// Get possible navigation property stream paths
RetrieveMediaEntityStreamPaths(navEntityType, currentPath);

if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
currentPath.Pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,40 +43,13 @@ protected override void SetBasicInfo(OpenApiOperation operation)
/// <inheritdoc/>
protected override void SetRequestBody(OpenApiOperation operation)
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = EntitySet.EntityType().FullName()
}
};
}

// The requestBody field contains a Request Body Object for the request body
// that references the schema of the entity set’s entity type in the global schemas.
operation.RequestBody = new OpenApiRequestBody
{
Required = true,
Description = "New entity",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
}
}
}
Content = GetContentDescription()
};

base.SetRequestBody(operation);
Expand All @@ -85,42 +58,14 @@ protected override void SetRequestBody(OpenApiOperation operation)
/// <inheritdoc/>
protected override void SetResponses(OpenApiOperation operation)
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = EntitySet.EntityType().FullName()
}
};
}

operation.Responses = new OpenApiResponses
{
{
Constants.StatusCode201,
new OpenApiResponse
{
Description = "Created entity",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType,
new OpenApiMediaType
{
Schema = schema
}
}
}
Content = GetContentDescription()
}
}
};
Expand Down Expand Up @@ -159,5 +104,63 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
AppendCustomParameters(operation, insert.CustomHeaders, ParameterLocation.Header);
}
}

/// <summary>
/// Get the entity content description.
/// </summary>
/// <returns>The entity content description.</returns>
private IDictionary<string, OpenApiMediaType> GetContentDescription()
{
OpenApiSchema schema = GetEntitySchema();
var content = new Dictionary<string, OpenApiMediaType>();

if (EntitySet.EntityType().HasStream)
{
// TODO: Read the AcceptableMediaType annotation from model
content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
}
});
}

content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
});

return content;
}

/// <summary>
/// Get the entity schema.
/// </summary>
/// <returns>The entity schema.</returns>
private OpenApiSchema GetEntitySchema()
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = EntitySet.EntityType().FullName()
}
};
}

return schema;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,39 @@ namespace Microsoft.OpenApi.OData.Operation
/// <summary>
/// Retrieve a media content for an Entity
/// </summary>
internal class MediaEntityGetOperationHandler : EntitySetOperationHandler
internal class MediaEntityGetOperationHandler : MediaEntityOperationalHandler
{
/// <inheritdoc/>
public override OperationType OperationType => OperationType.Get;

/// <inheritdoc/>
protected override void SetBasicInfo(OpenApiOperation operation)
{
string typeName = EntitySet.EntityType().Name;

// Summary
operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}";
if (EntitySet != null)
{
string typeName = EntitySet.EntityType().Name;
operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}";
}
else
{
operation.Summary = $"Get media content for the navigation property {NavigationProperty.Name} from {NavigationSource.Name}";
}

// OperationId
if (Context.Settings.EnableOperationId)
{
string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier;
operation.OperationId = EntitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(identifier);

if (EntitySet != null)
{
string typeName = EntitySet.EntityType().Name;
operation.OperationId = $"{EntitySet.Name}.{typeName}.Get{Utils.UpperFirstChar(identifier)}";
}
else // Singleton
{
operation.OperationId = GetOperationId("Get", identifier);
}
}

base.SetBasicInfo(operation);
Expand All @@ -43,22 +58,6 @@ protected override void SetBasicInfo(OpenApiOperation operation)
/// <inheritdoc/>
protected override void SetResponses(OpenApiOperation operation)
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
};
}

operation.Responses = new OpenApiResponses
{
{
Expand All @@ -72,7 +71,11 @@ protected override void SetResponses(OpenApiOperation operation)
Constants.ApplicationOctetStreamMediaType,
new OpenApiMediaType
{
Schema = schema
Schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
}
}
}
}
Expand All @@ -86,7 +89,9 @@ protected override void SetResponses(OpenApiOperation operation)
/// <inheritdoc/>
protected override void SetSecurity(OpenApiOperation operation)
{
ReadRestrictionsType read = Context.Model.GetRecord<ReadRestrictionsType>(EntitySet, CapabilitiesConstants.ReadRestrictions);
ReadRestrictionsType read = EntitySet != null
? Context.Model.GetRecord<ReadRestrictionsType>(EntitySet, CapabilitiesConstants.ReadRestrictions)
: Context.Model.GetRecord<ReadRestrictionsType>(Singleton, CapabilitiesConstants.ReadRestrictions);
if (read == null)
{
return;
Expand Down
Loading