Skip to content

Commit

Permalink
Merge pull request #1647 from json-api-dotnet/merge-master-into-openapi
Browse files Browse the repository at this point in the history
Merge master into openapi
  • Loading branch information
bkoelman authored Nov 27, 2024
2 parents 9010f16 + 11aafa4 commit 68cad58
Show file tree
Hide file tree
Showing 20 changed files with 404 additions and 225 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public RelationshipAttribute GetRelationshipByPropertyName(string propertyName)
}

/// <summary>
/// Returns all directly and indirectly non-abstract resource types that derive from this resource type.
/// Returns all non-abstract resource types that directly or indirectly derive from this resource type.
/// </summary>
public IReadOnlySet<ResourceType> GetAllConcreteDerivedTypes()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private static List<ActionDescriptor> Expand(ActionDescriptor genericEndpoint, N

ActionDescriptor expandedEndpoint = Clone(genericEndpoint);

RemovePathParameter(expandedEndpoint.Parameters, JsonApiPathParameter.RelationshipName);
RemovePathParameter(expandedEndpoint.Parameters, "relationshipName");

ExpandTemplate(expandedEndpoint.AttributeRouteInfo!, relationshipName);

Expand Down Expand Up @@ -212,12 +212,12 @@ private static FilterDescriptor Clone(FilterDescriptor descriptor)

private static void RemovePathParameter(ICollection<ParameterDescriptor> parameters, string parameterName)
{
ParameterDescriptor relationshipName = parameters.Single(parameterDescriptor => parameterDescriptor.Name == parameterName);
parameters.Remove(relationshipName);
ParameterDescriptor descriptor = parameters.Single(parameterDescriptor => parameterDescriptor.Name == parameterName);
parameters.Remove(descriptor);
}

private static void ExpandTemplate(AttributeRouteInfo route, string expansionParameter)
{
route.Template = route.Template!.Replace(JsonApiRoutingTemplate.RelationshipNameRoutePlaceholder, expansionParameter);
route.Template = route.Template!.Replace("{relationshipName}", expansionParameter);
}
}
16 changes: 0 additions & 16 deletions src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiEndpoint.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,72 +1,38 @@
using System.Reflection;
using JsonApiDotNetCore.Controllers;
using Microsoft.AspNetCore.Mvc;
using JsonApiDotNetCore.Middleware;
using Microsoft.AspNetCore.Mvc.Routing;

namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata;

internal sealed class EndpointResolver
{
public JsonApiEndpoint? Get(MethodInfo controllerAction)
public static EndpointResolver Instance { get; } = new();

private EndpointResolver()
{
}

public JsonApiEndpoints GetEndpoint(MethodInfo controllerAction)
{
ArgumentGuard.NotNull(controllerAction);

if (!IsJsonApiController(controllerAction))
{
return null;
}

if (IsAtomicOperationsController(controllerAction))
{
return JsonApiEndpoint.PostOperations;
return JsonApiEndpoints.None;
}

HttpMethodAttribute? method = Attribute.GetCustomAttributes(controllerAction, true).OfType<HttpMethodAttribute>().FirstOrDefault();

return ResolveJsonApiEndpoint(method);
IEnumerable<HttpMethodAttribute> httpMethodAttributes = controllerAction.GetCustomAttributes<HttpMethodAttribute>(true);
return httpMethodAttributes.GetJsonApiEndpoint();
}

private static bool IsJsonApiController(MethodInfo controllerAction)
private bool IsJsonApiController(MethodInfo controllerAction)
{
return typeof(CoreJsonApiController).IsAssignableFrom(controllerAction.ReflectedType);
}

private static bool IsAtomicOperationsController(MethodInfo controllerAction)
public bool IsAtomicOperationsController(MethodInfo controllerAction)
{
return typeof(BaseJsonApiOperationsController).IsAssignableFrom(controllerAction.ReflectedType);
}

private static JsonApiEndpoint? ResolveJsonApiEndpoint(HttpMethodAttribute? httpMethod)
{
return httpMethod switch
{
HttpGetAttribute attr => attr.Template switch
{
null => JsonApiEndpoint.GetCollection,
JsonApiRoutingTemplate.PrimaryEndpoint => JsonApiEndpoint.GetSingle,
JsonApiRoutingTemplate.SecondaryEndpoint => JsonApiEndpoint.GetSecondary,
JsonApiRoutingTemplate.RelationshipEndpoint => JsonApiEndpoint.GetRelationship,
_ => null
},
HttpPostAttribute attr => attr.Template switch
{
null => JsonApiEndpoint.PostResource,
JsonApiRoutingTemplate.RelationshipEndpoint => JsonApiEndpoint.PostRelationship,
_ => null
},
HttpPatchAttribute attr => attr.Template switch
{
JsonApiRoutingTemplate.PrimaryEndpoint => JsonApiEndpoint.PatchResource,
JsonApiRoutingTemplate.RelationshipEndpoint => JsonApiEndpoint.PatchRelationship,
_ => null
},
HttpDeleteAttribute attr => attr.Template switch
{
JsonApiRoutingTemplate.PrimaryEndpoint => JsonApiEndpoint.DeleteResource,
JsonApiRoutingTemplate.RelationshipEndpoint => JsonApiEndpoint.DeleteRelationship,
_ => null
},
_ => null
};
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Middleware;
using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents;
using JsonApiDotNetCore.Resources.Annotations;
Expand All @@ -12,18 +13,14 @@ namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata;
/// </summary>
internal sealed class JsonApiEndpointMetadataProvider
{
private readonly EndpointResolver _endpointResolver;
private readonly IControllerResourceMapping _controllerResourceMapping;
private readonly NonPrimaryDocumentTypeFactory _nonPrimaryDocumentTypeFactory;

public JsonApiEndpointMetadataProvider(EndpointResolver endpointResolver, IControllerResourceMapping controllerResourceMapping,
NonPrimaryDocumentTypeFactory nonPrimaryDocumentTypeFactory)
public JsonApiEndpointMetadataProvider(IControllerResourceMapping controllerResourceMapping, NonPrimaryDocumentTypeFactory nonPrimaryDocumentTypeFactory)
{
ArgumentGuard.NotNull(endpointResolver);
ArgumentGuard.NotNull(controllerResourceMapping);
ArgumentGuard.NotNull(nonPrimaryDocumentTypeFactory);

_endpointResolver = endpointResolver;
_controllerResourceMapping = controllerResourceMapping;
_nonPrimaryDocumentTypeFactory = nonPrimaryDocumentTypeFactory;
}
Expand All @@ -32,16 +29,16 @@ public JsonApiEndpointMetadataContainer Get(MethodInfo controllerAction)
{
ArgumentGuard.NotNull(controllerAction);

JsonApiEndpoint? endpoint = _endpointResolver.Get(controllerAction);

if (endpoint == null)
if (EndpointResolver.Instance.IsAtomicOperationsController(controllerAction))
{
throw new NotSupportedException($"Unable to provide metadata for non-JSON:API endpoint '{controllerAction.ReflectedType!.FullName}'.");
return new JsonApiEndpointMetadataContainer(AtomicOperationsRequestMetadata.Instance, AtomicOperationsResponseMetadata.Instance);
}

if (endpoint == JsonApiEndpoint.PostOperations)
JsonApiEndpoints endpoint = EndpointResolver.Instance.GetEndpoint(controllerAction);

if (endpoint == JsonApiEndpoints.None)
{
return new JsonApiEndpointMetadataContainer(AtomicOperationsRequestMetadata.Instance, AtomicOperationsResponseMetadata.Instance);
throw new NotSupportedException($"Unable to provide metadata for non-JSON:API endpoint '{controllerAction.ReflectedType!.FullName}'.");
}

ResourceType? primaryResourceType = _controllerResourceMapping.GetResourceTypeForController(controllerAction.ReflectedType);
Expand All @@ -51,19 +48,19 @@ public JsonApiEndpointMetadataContainer Get(MethodInfo controllerAction)
throw new UnreachableCodeException();
}

IJsonApiRequestMetadata? requestMetadata = GetRequestMetadata(endpoint.Value, primaryResourceType);
IJsonApiResponseMetadata? responseMetadata = GetResponseMetadata(endpoint.Value, primaryResourceType);
IJsonApiRequestMetadata? requestMetadata = GetRequestMetadata(endpoint, primaryResourceType);
IJsonApiResponseMetadata? responseMetadata = GetResponseMetadata(endpoint, primaryResourceType);
return new JsonApiEndpointMetadataContainer(requestMetadata, responseMetadata);
}

private IJsonApiRequestMetadata? GetRequestMetadata(JsonApiEndpoint endpoint, ResourceType primaryResourceType)
private IJsonApiRequestMetadata? GetRequestMetadata(JsonApiEndpoints endpoint, ResourceType primaryResourceType)
{
return endpoint switch
{
JsonApiEndpoint.PostResource => GetPostResourceRequestMetadata(primaryResourceType.ClrType),
JsonApiEndpoint.PatchResource => GetPatchResourceRequestMetadata(primaryResourceType.ClrType),
JsonApiEndpoint.PostRelationship or JsonApiEndpoint.PatchRelationship or JsonApiEndpoint.DeleteRelationship => GetRelationshipRequestMetadata(
primaryResourceType.Relationships, endpoint != JsonApiEndpoint.PatchRelationship),
JsonApiEndpoints.Post => GetPostResourceRequestMetadata(primaryResourceType.ClrType),
JsonApiEndpoints.Patch => GetPatchResourceRequestMetadata(primaryResourceType.ClrType),
JsonApiEndpoints.PostRelationship or JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship => GetRelationshipRequestMetadata(
primaryResourceType.Relationships, endpoint != JsonApiEndpoints.PatchRelationship),
_ => null
};
}
Expand Down Expand Up @@ -92,14 +89,14 @@ private RelationshipRequestMetadata GetRelationshipRequestMetadata(IEnumerable<R
return new RelationshipRequestMetadata(requestDocumentTypesByRelationshipName);
}

private IJsonApiResponseMetadata? GetResponseMetadata(JsonApiEndpoint endpoint, ResourceType primaryResourceType)
private IJsonApiResponseMetadata? GetResponseMetadata(JsonApiEndpoints endpoint, ResourceType primaryResourceType)
{
return endpoint switch
{
JsonApiEndpoint.GetCollection or JsonApiEndpoint.GetSingle or JsonApiEndpoint.PostResource or JsonApiEndpoint.PatchResource =>
GetPrimaryResponseMetadata(primaryResourceType.ClrType, endpoint == JsonApiEndpoint.GetCollection),
JsonApiEndpoint.GetSecondary => GetSecondaryResponseMetadata(primaryResourceType.Relationships),
JsonApiEndpoint.GetRelationship => GetRelationshipResponseMetadata(primaryResourceType.Relationships),
JsonApiEndpoints.GetCollection or JsonApiEndpoints.GetSingle or JsonApiEndpoints.Post or JsonApiEndpoints.Patch => GetPrimaryResponseMetadata(
primaryResourceType.ClrType, endpoint == JsonApiEndpoints.GetCollection),
JsonApiEndpoints.GetSecondary => GetSecondaryResponseMetadata(primaryResourceType.Relationships),
JsonApiEndpoints.GetRelationship => GetRelationshipResponseMetadata(primaryResourceType.Relationships),
_ => null
};
}
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 68cad58

Please sign in to comment.