Skip to content

Commit 7dd6046

Browse files
committed
Batch 3 of MapStruct Mappers
1 parent a8f35f7 commit 7dd6046

File tree

11 files changed

+184
-80
lines changed

11 files changed

+184
-80
lines changed

client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public void testAPIKeySecurityScheme() {
7979
"session-id",
8080
APIKeySecurityScheme.API_KEY,
8181
"secret-api-key",
82-
new APIKeySecurityScheme("header", "x-api-key", "API Key authentication"),
82+
new APIKeySecurityScheme(APIKeySecurityScheme.Location.HEADER, "x-api-key", "API Key authentication"),
8383
"x-api-key",
8484
"secret-api-key"
8585
);
@@ -258,7 +258,7 @@ void testAvailableSecuritySchemeNotInAgentCardSecuritySchemes() {
258258
@Test
259259
void testNoCredentialAvailable() {
260260
String schemeName = "apikey";
261-
SecurityScheme securityScheme = new APIKeySecurityScheme("header", "X-API-Key", "API Key authentication");
261+
SecurityScheme securityScheme = new APIKeySecurityScheme(APIKeySecurityScheme.Location.HEADER, "X-API-Key", "API Key authentication");
262262
AgentCard agentCard = createAgentCard(schemeName, securityScheme);
263263

264264
Map<String, Object> requestPayload = Map.of("test", "payload");
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.APIKeySecurityScheme} and {@link io.a2a.grpc.APIKeySecurityScheme}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
13+
public interface APIKeySecuritySchemeMapper {
14+
15+
APIKeySecuritySchemeMapper INSTANCE = Mappers.getMapper(APIKeySecuritySchemeMapper.class);
16+
17+
@IgnoreProtobufInternals
18+
@Mapping(target = "descriptionBytes", ignore = true)
19+
@Mapping(target = "locationBytes", ignore = true)
20+
@Mapping(target = "nameBytes", ignore = true)
21+
// location enum is converted to string via ProtoMapperConfig.map(Location)
22+
@Mapping(target = "description", source = "description", conditionExpression = "java(domain.getDescription() != null)")
23+
io.a2a.grpc.APIKeySecurityScheme toProto(io.a2a.spec.APIKeySecurityScheme domain);
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.HTTPAuthSecurityScheme} and {@link io.a2a.grpc.HTTPAuthSecurityScheme}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
13+
public interface HTTPAuthSecuritySchemeMapper {
14+
15+
HTTPAuthSecuritySchemeMapper INSTANCE = Mappers.getMapper(HTTPAuthSecuritySchemeMapper.class);
16+
17+
@IgnoreProtobufInternals
18+
@Mapping(target = "descriptionBytes", ignore = true)
19+
@Mapping(target = "schemeBytes", ignore = true)
20+
@Mapping(target = "bearerFormatBytes", ignore = true)
21+
@Mapping(target = "bearerFormat", source = "bearerFormat", conditionExpression = "java(domain.getBearerFormat() != null)")
22+
@Mapping(target = "description", source = "description", conditionExpression = "java(domain.getDescription() != null)")
23+
io.a2a.grpc.HTTPAuthSecurityScheme toProto(io.a2a.spec.HTTPAuthSecurityScheme domain);
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.MutualTLSSecurityScheme} and {@link io.a2a.grpc.MutualTlsSecurityScheme}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
13+
public interface MutualTLSSecuritySchemeMapper {
14+
15+
MutualTLSSecuritySchemeMapper INSTANCE = Mappers.getMapper(MutualTLSSecuritySchemeMapper.class);
16+
17+
@IgnoreProtobufInternals
18+
@Mapping(target = "descriptionBytes", ignore = true)
19+
@Mapping(target = "description", source = "description", conditionExpression = "java(domain.getDescription() != null)")
20+
io.a2a.grpc.MutualTlsSecurityScheme toProto(io.a2a.spec.MutualTLSSecurityScheme domain);
21+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.OAuth2SecurityScheme} and {@link io.a2a.grpc.OAuth2SecurityScheme}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
13+
uses = {OAuthFlowsMapper.class})
14+
public interface OAuth2SecuritySchemeMapper {
15+
16+
OAuth2SecuritySchemeMapper INSTANCE = Mappers.getMapper(OAuth2SecuritySchemeMapper.class);
17+
18+
@IgnoreProtobufInternals
19+
@Mapping(target = "descriptionBytes", ignore = true)
20+
@Mapping(target = "oauth2MetadataUrlBytes", ignore = true)
21+
@Mapping(target = "mergeFlows", ignore = true)
22+
@Mapping(target = "description", source = "description", conditionExpression = "java(domain.getDescription() != null)")
23+
@Mapping(target = "oauth2MetadataUrl", source = "oauth2MetadataUrl", conditionExpression = "java(domain.getOauth2MetadataUrl() != null)")
24+
io.a2a.grpc.OAuth2SecurityScheme toProto(io.a2a.spec.OAuth2SecurityScheme domain);
25+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.OAuthFlows} and {@link io.a2a.grpc.OAuthFlows}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
13+
uses = {
14+
AuthorizationCodeOAuthFlowMapper.class,
15+
ClientCredentialsOAuthFlowMapper.class,
16+
ImplicitOAuthFlowMapper.class,
17+
PasswordOAuthFlowMapper.class
18+
})
19+
public interface OAuthFlowsMapper {
20+
21+
OAuthFlowsMapper INSTANCE = Mappers.getMapper(OAuthFlowsMapper.class);
22+
23+
@IgnoreProtobufInternals
24+
@Mapping(target = "mergeAuthorizationCode", ignore = true)
25+
@Mapping(target = "mergeClientCredentials", ignore = true)
26+
@Mapping(target = "mergeImplicit", ignore = true)
27+
@Mapping(target = "mergePassword", ignore = true)
28+
io.a2a.grpc.OAuthFlows toProto(io.a2a.spec.OAuthFlows domain);
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.CollectionMappingStrategy;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.Mapping;
6+
import org.mapstruct.factory.Mappers;
7+
8+
/**
9+
* Mapper between {@link io.a2a.spec.OpenIdConnectSecurityScheme} and {@link io.a2a.grpc.OpenIdConnectSecurityScheme}.
10+
*/
11+
@Mapper(config = ProtoMapperConfig.class,
12+
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
13+
public interface OpenIdConnectSecuritySchemeMapper {
14+
15+
OpenIdConnectSecuritySchemeMapper INSTANCE = Mappers.getMapper(OpenIdConnectSecuritySchemeMapper.class);
16+
17+
@IgnoreProtobufInternals
18+
@Mapping(target = "descriptionBytes", ignore = true)
19+
@Mapping(target = "openIdConnectUrlBytes", ignore = true)
20+
@Mapping(target = "description", source = "description", conditionExpression = "java(domain.getDescription() != null)")
21+
io.a2a.grpc.OpenIdConnectSecurityScheme toProto(io.a2a.spec.OpenIdConnectSecurityScheme domain);
22+
}

spec-grpc/src/main/java/io/a2a/grpc/mapper/ProtoMapperConfig.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@
2727
public interface ProtoMapperConfig {
2828

2929
// ========================================================================
30-
// 1. Time & Duration
30+
// 1. Enum Conversions
31+
// ========================================================================
32+
33+
default String map(io.a2a.spec.APIKeySecurityScheme.Location location) {
34+
return location == null ? null : location.asString();
35+
}
36+
37+
// ========================================================================
38+
// 2. Time & Duration
3139
// ========================================================================
3240

3341
default Instant map(Timestamp value) {
@@ -57,7 +65,7 @@ default com.google.protobuf.Duration map(java.time.Duration value) {
5765
}
5866

5967
// ========================================================================
60-
// 2. Binary Data (ByteString)
68+
// 3. Binary Data (ByteString)
6169
// ========================================================================
6270

6371
default byte[] map(ByteString value) {
@@ -77,7 +85,7 @@ default ByteString mapFromBuffer(ByteBuffer value) {
7785
}
7886

7987
// ========================================================================
80-
// 3. Nullable Wrappers (Google Wrappers)
88+
// 4. Nullable Wrappers (Google Wrappers)
8189
// ========================================================================
8290

8391
// String
@@ -113,7 +121,7 @@ default BoolValue mapBool(Boolean value) {
113121
}
114122

115123
// ========================================================================
116-
// 4. JSON-RPC Support (Struct & Value)
124+
// 5. JSON-RPC Support (Struct & Value)
117125
// Maps "Struct" -> Map<String, Object>
118126
// Maps "Value" -> Object
119127
// ========================================================================

spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java

Lines changed: 12 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@
1414
import com.google.protobuf.Struct;
1515
import com.google.protobuf.Value;
1616
import io.a2a.grpc.StreamResponse;
17+
import io.a2a.grpc.mapper.APIKeySecuritySchemeMapper;
1718
import io.a2a.grpc.mapper.AgentInterfaceMapper;
1819
import io.a2a.grpc.mapper.AgentProviderMapper;
1920
import io.a2a.grpc.mapper.AuthenticationInfoMapper;
2021
import io.a2a.grpc.mapper.AuthorizationCodeOAuthFlowMapper;
2122
import io.a2a.grpc.mapper.ClientCredentialsOAuthFlowMapper;
23+
import io.a2a.grpc.mapper.HTTPAuthSecuritySchemeMapper;
2224
import io.a2a.grpc.mapper.ImplicitOAuthFlowMapper;
25+
import io.a2a.grpc.mapper.MutualTLSSecuritySchemeMapper;
26+
import io.a2a.grpc.mapper.OAuth2SecuritySchemeMapper;
27+
import io.a2a.grpc.mapper.OAuthFlowsMapper;
28+
import io.a2a.grpc.mapper.OpenIdConnectSecuritySchemeMapper;
2329
import io.a2a.grpc.mapper.PasswordOAuthFlowMapper;
2430
import io.a2a.spec.APIKeySecurityScheme;
2531
import io.a2a.spec.AgentCapabilities;
@@ -476,62 +482,19 @@ private static io.a2a.grpc.SecurityScheme securityScheme(SecurityScheme security
476482
}
477483

478484
private static io.a2a.grpc.APIKeySecurityScheme apiKeySecurityScheme(APIKeySecurityScheme apiKeySecurityScheme) {
479-
io.a2a.grpc.APIKeySecurityScheme.Builder builder = io.a2a.grpc.APIKeySecurityScheme.newBuilder();
480-
if (apiKeySecurityScheme.getDescription() != null) {
481-
builder.setDescription(apiKeySecurityScheme.getDescription());
482-
}
483-
if (apiKeySecurityScheme.getIn() != null) {
484-
builder.setLocation(apiKeySecurityScheme.getIn());
485-
}
486-
if (apiKeySecurityScheme.getName() != null) {
487-
builder.setName(apiKeySecurityScheme.getName());
488-
}
489-
return builder.build();
485+
return APIKeySecuritySchemeMapper.INSTANCE.toProto(apiKeySecurityScheme);
490486
}
491487

492488
private static io.a2a.grpc.HTTPAuthSecurityScheme httpAuthSecurityScheme(HTTPAuthSecurityScheme httpAuthSecurityScheme) {
493-
io.a2a.grpc.HTTPAuthSecurityScheme.Builder builder = io.a2a.grpc.HTTPAuthSecurityScheme.newBuilder();
494-
if (httpAuthSecurityScheme.getBearerFormat() != null) {
495-
builder.setBearerFormat(httpAuthSecurityScheme.getBearerFormat());
496-
}
497-
if (httpAuthSecurityScheme.getDescription() != null) {
498-
builder.setDescription(httpAuthSecurityScheme.getDescription());
499-
}
500-
if (httpAuthSecurityScheme.getScheme() != null) {
501-
builder.setScheme(httpAuthSecurityScheme.getScheme());
502-
}
503-
return builder.build();
489+
return HTTPAuthSecuritySchemeMapper.INSTANCE.toProto(httpAuthSecurityScheme);
504490
}
505491

506492
private static io.a2a.grpc.OAuth2SecurityScheme oauthSecurityScheme(OAuth2SecurityScheme oauth2SecurityScheme) {
507-
io.a2a.grpc.OAuth2SecurityScheme.Builder builder = io.a2a.grpc.OAuth2SecurityScheme.newBuilder();
508-
if (oauth2SecurityScheme.getDescription() != null) {
509-
builder.setDescription(oauth2SecurityScheme.getDescription());
510-
}
511-
if (oauth2SecurityScheme.getFlows() != null) {
512-
builder.setFlows(oauthFlows(oauth2SecurityScheme.getFlows()));
513-
}
514-
if (oauth2SecurityScheme.getOauth2MetadataUrl() != null) {
515-
builder.setOauth2MetadataUrl(oauth2SecurityScheme.getOauth2MetadataUrl());
516-
}
517-
return builder.build();
493+
return OAuth2SecuritySchemeMapper.INSTANCE.toProto(oauth2SecurityScheme);
518494
}
519495

520496
private static io.a2a.grpc.OAuthFlows oauthFlows(OAuthFlows oAuthFlows) {
521-
io.a2a.grpc.OAuthFlows.Builder builder = io.a2a.grpc.OAuthFlows.newBuilder();
522-
if (oAuthFlows.authorizationCode() != null) {
523-
builder.setAuthorizationCode(authorizationCodeOAuthFlow(oAuthFlows.authorizationCode()));
524-
}
525-
if (oAuthFlows.clientCredentials() != null) {
526-
builder.setClientCredentials(clientCredentialsOAuthFlow(oAuthFlows.clientCredentials()));
527-
}
528-
if (oAuthFlows.implicit() != null) {
529-
builder.setImplicit(implicitOAuthFlow(oAuthFlows.implicit()));
530-
}
531-
if (oAuthFlows.password() != null) {
532-
builder.setPassword(passwordOAuthFlow(oAuthFlows.password()));
533-
}
534-
return builder.build();
497+
return OAuthFlowsMapper.INSTANCE.toProto(oAuthFlows);
535498
}
536499

537500
private static io.a2a.grpc.AuthorizationCodeOAuthFlow authorizationCodeOAuthFlow(AuthorizationCodeOAuthFlow authorizationCodeOAuthFlow) {
@@ -559,22 +522,11 @@ private static io.a2a.grpc.PasswordOAuthFlow passwordOAuthFlow(PasswordOAuthFlow
559522
}
560523

561524
private static io.a2a.grpc.OpenIdConnectSecurityScheme openIdConnectSecurityScheme(OpenIdConnectSecurityScheme openIdConnectSecurityScheme) {
562-
io.a2a.grpc.OpenIdConnectSecurityScheme.Builder builder = io.a2a.grpc.OpenIdConnectSecurityScheme.newBuilder();
563-
if (openIdConnectSecurityScheme.getDescription() != null) {
564-
builder.setDescription(openIdConnectSecurityScheme.getDescription());
565-
}
566-
if (openIdConnectSecurityScheme.getOpenIdConnectUrl() != null) {
567-
builder.setOpenIdConnectUrl(openIdConnectSecurityScheme.getOpenIdConnectUrl());
568-
}
569-
return builder.build();
525+
return OpenIdConnectSecuritySchemeMapper.INSTANCE.toProto(openIdConnectSecurityScheme);
570526
}
571527

572528
private static io.a2a.grpc.MutualTlsSecurityScheme mutualTlsSecurityScheme(MutualTLSSecurityScheme mutualTlsSecurityScheme) {
573-
io.a2a.grpc.MutualTlsSecurityScheme.Builder builder = io.a2a.grpc.MutualTlsSecurityScheme.newBuilder();
574-
if (mutualTlsSecurityScheme.getDescription() != null) {
575-
builder.setDescription(mutualTlsSecurityScheme.getDescription());
576-
}
577-
return builder.build();
529+
return MutualTLSSecuritySchemeMapper.INSTANCE.toProto(mutualTlsSecurityScheme);
578530
}
579531

580532
private static io.a2a.grpc.AgentInterface agentInterface(AgentInterface agentInterface) {

spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
public final class APIKeySecurityScheme implements SecurityScheme {
3030

3131
public static final String API_KEY = "apiKey";
32-
private final String in;
32+
private final Location location;
3333
private final String name;
3434
private final String type;
3535
private final String description;
@@ -70,20 +70,20 @@ public static Location fromString(String location) {
7070
}
7171
}
7272

73-
public APIKeySecurityScheme(String in, String name, String description) {
74-
this(in, name, description, API_KEY);
73+
public APIKeySecurityScheme(Location location, String name, String description) {
74+
this(location, name, description, API_KEY);
7575
}
7676

7777
@JsonCreator
78-
public APIKeySecurityScheme(@JsonProperty("in") String in, @JsonProperty("name") String name,
78+
public APIKeySecurityScheme(@JsonProperty("location") Location location, @JsonProperty("name") String name,
7979
@JsonProperty("description") String description, @JsonProperty("type") String type) {
80-
Assert.checkNotNullParam("in", in);
80+
Assert.checkNotNullParam("location", location);
8181
Assert.checkNotNullParam("name", name);
8282
Assert.checkNotNullParam("type", type);
8383
if (! type.equals(API_KEY)) {
8484
throw new IllegalArgumentException("Invalid type for APIKeySecurityScheme");
8585
}
86-
this.in = in;
86+
this.location = location;
8787
this.name = name;
8888
this.description = description;
8989
this.type = type;
@@ -94,9 +94,8 @@ public String getDescription() {
9494
return description;
9595
}
9696

97-
98-
public String getIn() {
99-
return in;
97+
public Location getLocation() {
98+
return location;
10099
}
101100

102101
public String getName() {
@@ -108,12 +107,12 @@ public String getType() {
108107
}
109108

110109
public static class Builder {
111-
private String in;
110+
private Location location;
112111
private String name;
113112
private String description;
114113

115-
public Builder in(String in) {
116-
this.in = in;
114+
public Builder location(Location location) {
115+
this.location = location;
117116
return this;
118117
}
119118

@@ -128,7 +127,7 @@ public Builder description(String description) {
128127
}
129128

130129
public APIKeySecurityScheme build() {
131-
return new APIKeySecurityScheme(in, name, description);
130+
return new APIKeySecurityScheme(location, name, description);
132131
}
133132
}
134133
}

0 commit comments

Comments
 (0)