Skip to content

Commit

Permalink
Support collection parameters in functions. Fixes #999
Browse files Browse the repository at this point in the history
  • Loading branch information
commonsensesoftware committed Mar 26, 2024
1 parent be7021c commit 42607c5
Showing 1 changed file with 70 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public virtual void OnProvidersExecuted( ApiDescriptionProviderContext context )
else
{
UpdateModelTypes( result, matched );
UpdateFunctionCollectionParameters( result, matched );
}
}

Expand Down Expand Up @@ -456,6 +457,75 @@ private void UpdateModelTypes( ApiDescription description, IODataRoutingMetadata
}
}

private static void UpdateFunctionCollectionParameters( ApiDescription description, IODataRoutingMetadata metadata )
{
var parameters = description.ParameterDescriptions;

if ( parameters.Count == 0 )
{
return;
}

var function = default( IEdmFunction );
var mapping = default( IDictionary<string, string> );

for ( var i = 0; i < metadata.Template.Count; i++ )
{
var segment = metadata.Template[i];

if ( segment is FunctionSegmentTemplate func )
{
function = func.Function;
mapping = func.ParameterMappings;
break;
}
else if ( segment is FunctionImportSegmentTemplate import )
{
function = import.FunctionImport.Function;
mapping = import.ParameterMappings;
break;
}
}

if ( function is null || mapping is null )
{
return;
}

var name = default( string );

foreach ( var parameter in function.Parameters )
{
if ( parameter.Type.IsCollection() &&
mapping.TryGetValue( parameter.Name, out name ) &&
parameters.SingleOrDefault( p => p.Name == name ) is { } param )
{
param.Source = BindingSource.Path;
break;
}
}

var path = description.RelativePath;

if ( string.IsNullOrEmpty( name ) || string.IsNullOrEmpty( path ) )
{
return;
}

var span = name.AsSpan();
Span<char> oldValue = stackalloc char[name.Length + 2];
Span<char> newValue = stackalloc char[name.Length + 4];

newValue[1] = oldValue[0] = '{';
newValue[^2] = oldValue[^1] = '}';
newValue[0] = '[';
newValue[^1] = ']';
span.CopyTo( oldValue.Slice( 1, name.Length ) );
span.CopyTo( newValue.Slice( 2, name.Length ) );

description.RelativePath = path.Replace( oldValue.ToString(), newValue.ToString(), Ordinal );
}

private sealed class ApiDescriptionComparer : IEqualityComparer<ApiDescription>
{
private readonly IEqualityComparer<string?> comparer = StringComparer.OrdinalIgnoreCase;
Expand Down

0 comments on commit 42607c5

Please sign in to comment.