Skip to content

Commit 325b58e

Browse files
ehsavoieclaude
andcommitted
feat: Add SubscribeToTaskRequest mapper and ProtoUtils method
Added bidirectional mapping support for SubscribeToTaskRequest: 1. Created SubscribeToTaskRequestMapper: - toProto(): Converts domain SubscribeToTaskRequest to proto format - fromProto(): Converts proto SubscribeToTaskRequest to domain format - Handles conversion between TaskIdParams and "tasks/{task_id}" format - Uses ResourceNameParser for resource name formatting 2. Updated TaskIdParamsMapper: - Added toProtoSubscribeToTaskRequest() method to convert TaskIdParams to proto SubscribeToTaskRequest - Complements existing fromProtoSubscribeToTaskRequest() method - Uses ResourceNameParser.defineTaskName() for resource name creation 3. Updated ProtoUtils.ToProto: - Added subscribeToTaskRequest(TaskIdParams) method - Delegates to TaskIdParamsMapper.toProtoSubscribeToTaskRequest() - Follows existing pattern for cancelTaskRequest() This enables proper handling of SubscribeToTaskRequest in the JSONRPC transport layer, converting between domain JSONRPC requests and proto gRPC requests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2b29f36 commit 325b58e

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.a2a.grpc.mapper;
2+
3+
import org.mapstruct.Mapper;
4+
5+
/**
6+
* Mapper between {@link io.a2a.spec.SubscribeToTaskRequest} and {@link io.a2a.grpc.SubscribeToTaskRequest}.
7+
* <p>
8+
* The mapping handles the structural difference between domain and proto representations:
9+
* <ul>
10+
* <li>Domain: Full JSONRPC request with id, jsonrpc, method, and params (TaskIdParams)</li>
11+
* <li>Proto: Simple request with name field in format "tasks/{task_id}"</li>
12+
* </ul>
13+
* <p>
14+
* Note: The domain object is a complete JSONRPC request, while the proto is just the gRPC
15+
* request parameters. The JSONRPC envelope (id, jsonrpc, method) is handled separately
16+
* by the transport layer.
17+
*/
18+
@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskIdParamsMapper.class})
19+
public interface SubscribeToTaskRequestMapper {
20+
21+
SubscribeToTaskRequestMapper INSTANCE = A2AMappers.getMapper(SubscribeToTaskRequestMapper.class);
22+
23+
/**
24+
* Converts domain SubscribeToTaskRequest to proto SubscribeToTaskRequest.
25+
* Extracts the task ID from params and formats it as "tasks/{task_id}".
26+
*
27+
* @param domain the domain SubscribeToTaskRequest
28+
* @return the proto SubscribeToTaskRequest
29+
*/
30+
default io.a2a.grpc.SubscribeToTaskRequest toProto(io.a2a.spec.SubscribeToTaskRequest domain) {
31+
if (domain == null || domain.getParams() == null || domain.getParams().id() == null) {
32+
return null;
33+
}
34+
return io.a2a.grpc.SubscribeToTaskRequest.newBuilder()
35+
.setName(ResourceNameParser.defineTaskName(domain.getParams().id()))
36+
.build();
37+
}
38+
39+
/**
40+
* Converts proto SubscribeToTaskRequest to domain SubscribeToTaskRequest.
41+
* Extracts the task ID from the name field and creates a TaskIdParams.
42+
*
43+
* @param proto the proto SubscribeToTaskRequest
44+
* @return the domain SubscribeToTaskRequest
45+
*/
46+
default io.a2a.spec.SubscribeToTaskRequest fromProto(io.a2a.grpc.SubscribeToTaskRequest proto) {
47+
if (proto == null || proto.getName() == null) {
48+
return null;
49+
}
50+
return new io.a2a.spec.SubscribeToTaskRequest.Builder()
51+
.params(new io.a2a.spec.TaskIdParams(ResourceNameParser.extractTaskId(proto.getName())))
52+
.build();
53+
}
54+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,12 @@ public interface TaskIdParamsMapper {
4242
@Mapping(target = "id", expression = "java(ResourceNameParser.extractTaskId(proto.getName()))")
4343
@Mapping(target = "metadata", ignore = true)
4444
TaskIdParams fromProtoSubscribeToTaskRequest(io.a2a.grpc.SubscribeToTaskRequest proto);
45+
46+
/**
47+
* Converts domain TaskIdParams to proto SubscribeToTaskRequest.
48+
* Creates resource name from task ID.
49+
*/
50+
@BeanMapping(builder = @Builder(buildMethod = "build"))
51+
@Mapping(target = "name", expression = "java(ResourceNameParser.defineTaskName(domain.id()))")
52+
io.a2a.grpc.SubscribeToTaskRequest toProtoSubscribeToTaskRequest(TaskIdParams domain);
4553
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.a2a.grpc.mapper.MessageSendParamsMapper;
1818
import io.a2a.grpc.mapper.SetTaskPushNotificationConfigMapper;
1919
import io.a2a.grpc.mapper.StreamResponseMapper;
20+
import io.a2a.grpc.mapper.SubscribeToTaskRequestMapper;
2021
import io.a2a.grpc.mapper.TaskArtifactUpdateEventMapper;
2122
import io.a2a.grpc.mapper.TaskIdParamsMapper;
2223
import io.a2a.grpc.mapper.TaskMapper;
@@ -66,6 +67,10 @@ public static io.a2a.grpc.CancelTaskRequest cancelTaskRequest(TaskIdParams param
6667
return TaskIdParamsMapper.INSTANCE.toProtoCancelTaskRequest(params);
6768
}
6869

70+
public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdParams params) {
71+
return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params);
72+
}
73+
6974
public static io.a2a.grpc.SetTaskPushNotificationConfigRequest setTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) {
7075
return SetTaskPushNotificationConfigMapper.INSTANCE.toProto(config);
7176
}
@@ -162,6 +167,10 @@ public static io.a2a.grpc.StreamResponse taskOrMessageStream(StreamingEventKind
162167
}
163168
}
164169

170+
public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(io.a2a.spec.SubscribeToTaskRequest request) {
171+
return SubscribeToTaskRequestMapper.INSTANCE.toProto(request);
172+
}
173+
165174
}
166175

167176
public static class FromProto {

0 commit comments

Comments
 (0)