Skip to content

Commit 39820d8

Browse files
committed
Done away with contract duplication.
Body will now be only a pointer to downstream contract. Later we can make it so that developers can have their own contract version to manipulate and map as they see fit.
1 parent 2d3211e commit 39820d8

File tree

16 files changed

+277
-864
lines changed

16 files changed

+277
-864
lines changed

DesignerMacros/src/api-gateway/_common/isFieldFromBody.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function isFieldFromBody(downStreamOperation: MacroApi.Context.IElementApi , dto
1010
let httpSettingsRoute = httpSpecifiedElement.getStereotype("Http Settings")?.getProperty("Route")?.getValue() as string;
1111
let paramSource = dtoField.getStereotype("Parameter Settings")?.getProperty("Source")?.getValue();
1212
if (!paramSource || paramSource == "Default") {
13-
return httpSettingsRoute.toLowerCase().indexOf(`{${dtoField.getName().toLowerCase()}}`) < 0;
13+
return httpSettingsRoute?.toLowerCase().indexOf(`{${dtoField.getName().toLowerCase()}}`) < 0;
1414
}
1515
return paramSource == "Body";
1616
}

DesignerMacros/src/api-gateway/_common/syncApiGatewayRouteWithVariables.ts

+5-15
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ function syncApiGatewayRouteWithVariables(
1616
throw Error(`Element "${apiGatewayRoute.id}, ${apiGatewayRoute.getName()}" is not of type Api Gateway Route`);
1717
}
1818

19-
const downstreamOperation = downstreamAssociationEnd.typeReference.getType();
19+
const downstreamOperation = downstreamAssociationEnd?.typeReference.getType();
2020
const customRoute = getHttpRouteFromOperation(apiGatewayRoute);
21-
const httpRoute = getHttpRouteFromOperation(downstreamOperation);
21+
const httpRoute = downstreamOperation ? getHttpRouteFromOperation(downstreamOperation) : null;
2222

2323
let upstreamRoute = customRoute || httpRoute;
2424

2525
if (!upstreamRoute) {
26-
apiGatewayRoute.getChildren("DTO-Field").filter(field => field.getName() !== "Body").forEach(x => x.delete());
26+
apiGatewayRoute.getChildren("DTO-Field").forEach(x => x.delete());
2727
return;
2828
}
2929

3030
let routeVars = extractRouteVariables(upstreamRoute);
31-
apiGatewayRoute.getChildren("DTO-Field").filter(field => field.getName() !== "Body")
31+
apiGatewayRoute.getChildren("DTO-Field")
3232
.forEach(field => {
3333
let routeVar = field.getMetadata("routeVar");
3434
if (routeVars.indexOf(routeVar) < 0) {
@@ -39,17 +39,7 @@ function syncApiGatewayRouteWithVariables(
3939
let field = apiGatewayRoute.getChildren("DTO-Field").filter(x => x.getMetadata("routeVar") === routeVar)[0]
4040
?? createElement("DTO-Field", toPascalCase(routeVar), apiGatewayRoute.id);
4141
field.setMetadata("routeVar", routeVar);
42-
43-
let downstreamField = downstreamOperation.getChildren()
44-
.filter(x => isParamOrFieldFromRoute(downstreamOperation, x) && extractRouteVariables(getHttpRouteFromOperation(downstreamOperation).toLowerCase()).indexOf(routeVar) >= 0)[0];
4542

46-
if (downstreamField) {
47-
const routeMappingId = "48776d2f-ee28-4738-844f-d2ee610b516f";
48-
let mapping = downstreamAssociationEnd.getMapping(routeMappingId);
49-
if (!mapping) {
50-
mapping = downstreamAssociationEnd.createAdvancedMapping(apiGatewayRoute.id, downstreamOperation.id, routeMappingId);
51-
}
52-
mapping.addMappedEnd("Data Mapping", [apiGatewayRoute.id, field.id], [downstreamOperation.id, downstreamField.id]);
53-
}
43+
// Go back to commit [755e8b97d879661be312ae7cb0e22cd0c5bf1d2c] when you need the Mappings
5444
});
5545
}

DesignerMacros/src/api-gateway/_common/syncDownstreamContract.ts

+15-33
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,26 @@ function syncDownstreamContract(apiGatewayRoute: MacroApi.Context.IElementApi, d
55
if (apiGatewayRoute.specialization !== "Api Gateway Route") {
66
throw Error(`Element "${apiGatewayRoute.id}, ${apiGatewayRoute.getName()}" is not of type Api Gateway Route`);
77
}
8-
9-
let downstreamFields = downstreamService.getChildren("DTO-Field").filter(x => isFieldFromBody(downstreamService, x));
8+
9+
let downstreamContract = downstreamService.specialization === "Operation"
10+
? downstreamService.getChildren("Parameter")
11+
.map(x => x.typeReference?.getType())
12+
.filter(x => x && x.specialization === "DTO")[0]
13+
: downstreamService;
14+
15+
let downstreamFields = downstreamService.specialization === "Operation"
16+
? downstreamContract?.getChildren("DTO-Field")
17+
: downstreamContract.getChildren("DTO-Field").filter(x => isFieldFromBody(downstreamService, x));
1018

1119
if (!downstreamFields || downstreamFields.length === 0) {
20+
apiGatewayRoute.getChildren("Body Field")[0]?.delete();
1221
return;
1322
}
14-
15-
const sourceParent = apiGatewayRoute.getParent();
16-
17-
let existingDto = sourceParent
18-
.getChildren()
19-
.filter(child => child.hasMetadata("upstream") && child.getMetadata("upstream") === apiGatewayRoute.id)[0];
20-
21-
let dto = existingDto;
22-
if (!dto) {
23-
const dtoName = downstreamService.getName();
24-
dto = createElement("DTO", dtoName, sourceParent.id);
25-
dto.addMetadata("upstream", apiGatewayRoute.id);
26-
}
2723

28-
for (let downstreamField of downstreamFields) {
29-
let field = dto.getChildren("DTO-Field").filter(field => field.getName() === downstreamField.getName())[0];
30-
if (!field) {
31-
field = createElement("DTO-Field", downstreamField.getName(), dto.id);
32-
field.typeReference?.setType(downstreamField.typeReference.getTypeId());
33-
}
34-
}
35-
36-
for (let upstreamField of dto.getChildren("DTO-Field")) {
37-
if (!downstreamFields.some(field => upstreamField.getName() === field.getName())) {
38-
upstreamField.delete();
39-
}
40-
}
41-
42-
let bodyField = apiGatewayRoute.getChildren("DTO-Field").filter(x => x.getName() === "Body")[0];
24+
let bodyField = apiGatewayRoute.getChildren("Body Field")[0];
4325
if (!bodyField) {
44-
bodyField = createElement("DTO-Field", "Body", apiGatewayRoute.id);
26+
bodyField = createElement("Body Field", "Body", apiGatewayRoute.id);
4527
}
46-
47-
bodyField.typeReference?.setType(dto.id);
28+
29+
bodyField.typeReference?.setType(downstreamContract.id);
4830
}

DesignerMacros/src/api-gateway/api-gateway-route-on-changed/api-gateway-route-on-changed.ts

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ function applyOnChangedApiGatewayRouteBehavior(): void {
88
syncDownstreamContract(element, targetEnd.typeReference.getType());
99
syncApiGatewayRouteWithVariables(element, targetEnd);
1010
}
11+
12+
const HttpSettings = "b4581ed2-42ec-4ae2-83dd-dcdd5f0837b6";
13+
if (!element.hasStereotype(HttpSettings)) {
14+
syncApiGatewayRouteWithVariables(element, null);
15+
}
1116
}
1217

1318
applyOnChangedApiGatewayRouteBehavior();

DesignerMacros/src/api-gateway/route-association-on-deleted/route-association-on-deleted.ts

+2-11
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,8 @@ function applyRouteAssociationOnDeletedBehavior(): void {
1717
source.removeStereotype(HttpSettings);
1818
}
1919

20-
const sourceParent = source.getParent();
21-
22-
let existingDtos = sourceParent
23-
.getChildren()
24-
.filter(child => child.hasMetadata("upstream") && child.getMetadata("upstream") === source.id);
25-
26-
source.getChildren("DTO-Field").filter(field => field.getName() === "Body")[0]?.delete();
27-
28-
for (let dto of existingDtos) {
29-
dto.delete();
30-
}
20+
let bodyField = source.getChildren("Body Field")[0];
21+
bodyField?.delete();
3122
}
3223

3324
applyRouteAssociationOnDeletedBehavior();

Modules/Intent.Modules.Metadata.ApiGateway/Api/ApiGatewayRouteModel.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public UpstreamRouteInfo GetUpstreamRouteInfo()
5353
{
5454
var downstreamRoute = downstreamOperation?.GetStereotype("Http Settings")?.GetProperty("Route")?.Value;
5555
var downstreamServiceRoute = downstreamOperation?.ParentElement?.GetStereotype("Http Service Settings")?.GetProperty("Route")?.Value;
56-
var separator = string.IsNullOrWhiteSpace(downstreamServiceRoute) || downstreamServiceRoute.EndsWith("/")
57-
? string.Empty
58-
: !string.IsNullOrWhiteSpace(downstreamRoute)
59-
? "/"
56+
var separator = string.IsNullOrWhiteSpace(downstreamServiceRoute) || downstreamServiceRoute.EndsWith("/")
57+
? string.Empty
58+
: !string.IsNullOrWhiteSpace(downstreamRoute)
59+
? "/"
6060
: string.Empty;
6161
upstreamRoute = $"{downstreamServiceRoute}{separator}{downstreamRoute}";
6262
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Intent.Metadata.Models;
5+
using Intent.Modules.Common;
6+
using Intent.RoslynWeaver.Attributes;
7+
8+
[assembly: DefaultIntentManaged(Mode.Fully)]
9+
[assembly: IntentTemplate("Intent.ModuleBuilder.Templates.Api.ApiElementModel", Version = "1.0")]
10+
11+
namespace Intent.Metadata.ApiGateway.Api
12+
{
13+
[IntentManaged(Mode.Fully, Signature = Mode.Fully)]
14+
public class BodyFieldModel : IMetadataModel, IHasStereotypes, IHasName, IElementWrapper, IHasTypeReference
15+
{
16+
public const string SpecializationType = "Body Field";
17+
public const string SpecializationTypeId = "6b201f1e-03e3-4a9d-923f-ca3976c998c5";
18+
protected readonly IElement _element;
19+
20+
[IntentManaged(Mode.Fully)]
21+
public BodyFieldModel(IElement element, string requiredType = SpecializationType)
22+
{
23+
if (!requiredType.Equals(element.SpecializationType, StringComparison.InvariantCultureIgnoreCase))
24+
{
25+
throw new Exception($"Cannot create a '{GetType().Name}' from element with specialization type '{element.SpecializationType}'. Must be of type '{SpecializationType}'");
26+
}
27+
_element = element;
28+
}
29+
30+
public string Id => _element.Id;
31+
32+
public string Name => _element.Name;
33+
34+
public string Comment => _element.Comment;
35+
36+
public IEnumerable<IStereotype> Stereotypes => _element.Stereotypes;
37+
38+
public ITypeReference TypeReference => _element.TypeReference;
39+
40+
41+
public IElement InternalElement => _element;
42+
43+
public override string ToString()
44+
{
45+
return _element.ToString();
46+
}
47+
48+
public bool Equals(BodyFieldModel other)
49+
{
50+
return Equals(_element, other?._element);
51+
}
52+
53+
public override bool Equals(object obj)
54+
{
55+
if (ReferenceEquals(null, obj)) return false;
56+
if (ReferenceEquals(this, obj)) return true;
57+
if (obj.GetType() != this.GetType()) return false;
58+
return Equals((BodyFieldModel)obj);
59+
}
60+
61+
public override int GetHashCode()
62+
{
63+
return (_element != null ? _element.GetHashCode() : 0);
64+
}
65+
}
66+
67+
[IntentManaged(Mode.Fully)]
68+
public static class BodyFieldModelExtensions
69+
{
70+
71+
public static bool IsBodyFieldModel(this ICanBeReferencedType type)
72+
{
73+
return type != null && type is IElement element && element.SpecializationTypeId == BodyFieldModel.SpecializationTypeId;
74+
}
75+
76+
public static BodyFieldModel AsBodyFieldModel(this ICanBeReferencedType type)
77+
{
78+
return type.IsBodyFieldModel() ? new BodyFieldModel((IElement)type) : null;
79+
}
80+
}
81+
}

Modules/Intent.Modules.Metadata.ApiGateway/Api/RouteAssociationModel.cs

-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ public class DownstreamEndModel : RouteAssociationEndModel
8686
public DownstreamEndModel(IAssociationEnd associationEnd, RouteAssociationModel association) : base(associationEnd, association)
8787
{
8888
}
89-
90-
public IEnumerable<IElementToElementMapping> Mappings => _associationEnd.Mappings;
9189
}
9290

9391
[IntentManaged(Mode.Fully)]

0 commit comments

Comments
 (0)