From f77e736819779512a0f39de872fe3b7c0d735a19 Mon Sep 17 00:00:00 2001
From: Dmitriy Musatkin <63878209+DmitriyMusatkin@users.noreply.github.com>
Date: Fri, 26 Jul 2024 10:41:14 -0700
Subject: [PATCH] Fix codegen for implicit event payloads with a single enum
field (#3056)
* update codegen for enums
---
.../aws/qbusiness/model/ChatInputStream.h | 5 ++-
.../C2jModelToGeneratorModelTransformer.java | 29 ++++++++++--
...jModelToGeneratorModelTransformerTest.java | 44 +++++++++++++++++--
3 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/generated/src/aws-cpp-sdk-qbusiness/include/aws/qbusiness/model/ChatInputStream.h b/generated/src/aws-cpp-sdk-qbusiness/include/aws/qbusiness/model/ChatInputStream.h
index 402293f6e92..92455dee2cb 100644
--- a/generated/src/aws-cpp-sdk-qbusiness/include/aws/qbusiness/model/ChatInputStream.h
+++ b/generated/src/aws-cpp-sdk-qbusiness/include/aws/qbusiness/model/ChatInputStream.h
@@ -23,7 +23,7 @@ namespace Model
{
/**
- *
The streaming input for the Chat
API.
See Also:
+ * The streaming input for the Chat
API.
See Also:
* AWS
* API Reference
@@ -85,7 +85,8 @@ namespace Model
Aws::Utils::Event::Message msg;
msg.InsertEventHeader(":message-type", Aws::String("event"));
msg.InsertEventHeader(":event-type", Aws::String("AuthChallengeResponseEvent"));
- AWS_UNREFERENCED_PARAM(value);
+ msg.InsertEventHeader(":content-type", Aws::String("application/json"));
+ msg.WriteEventPayload(value.Jsonize().View().WriteCompact());
WriteEvent(msg);
return *this;
}
diff --git a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java
index 050c776fcb9..0c95e6c8cc2 100644
--- a/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java
+++ b/tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java
@@ -305,9 +305,32 @@ header insertion there. So strip this out of the model (affects S3's PutObjectR
} else if (shape.hasEventPayloadMembers() || shape.getMembers().size() == 1) {
if (shape.getMembers().size() == 1) {
shape.getMembers().entrySet().stream().forEach(memberEntry -> {
- memberEntry.getValue().setEventPayload(true);
- shape.setEventPayloadMemberName(memberEntry.getKey());
- shape.setEventPayloadType(memberEntry.getValue().getShape().getType());
+ /**
+ * Note: this is complicated and potentially not completely correct.
+ * So touch at your own risk until we have protocol tests supported.
+ * In summary:
+ * - we need to determine how to serialize events in eventstream
+ * - to specify payload there is an eventpayload trait
+ * - but what happens if that trait is not specified
+ * - if there is one field and its a string, blob or struct then we assume that field is event payload
+ * (note: this might not be completely correct, spec is vague on that and other sdks do implicit struct around string and blob)
+ * - if that one field is of any other type then treat parent shape as eventpayload
+ * - if there is more than one field then parent shape is the payload
+ */
+ Shape memberShape = memberEntry.getValue().getShape();
+ if (memberShape.isString() ||
+ memberShape.isBlob() ||
+ memberShape.isStructure()) {
+ memberEntry.getValue().setEventPayload(true);
+ shape.setEventPayloadMemberName(memberEntry.getKey());
+ shape.setEventPayloadType(memberShape.getType());
+ } else {
+ if (!shape.getType().equals("structure")) {
+ throw new RuntimeException("Event shape should always has \"structure\" type if single member cannot be event payload.");
+ }
+ shape.setEventPayloadType(shape.getType());
+ }
+
});
} else {
throw new RuntimeException("Event shape used in Event Stream should only has one member if it has event payload member.");
diff --git a/tools/code-generation/generator/src/test/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformerTest.java b/tools/code-generation/generator/src/test/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformerTest.java
index 223dcc1a8a6..3fd2aa272e7 100644
--- a/tools/code-generation/generator/src/test/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformerTest.java
+++ b/tools/code-generation/generator/src/test/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformerTest.java
@@ -13,8 +13,10 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import com.google.common.collect.ImmutableList;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
public class C2jModelToGeneratorModelTransformerTest {
@@ -342,7 +344,8 @@ public void testOperationConversion() {
// "EventStreamShape":{
// "type":"structure",
// "members":{
- // "EventShape":{"shape":"EventShape"}
+ // "EventShape":{"shape":"EventShape"},
+ // "EventEnumShape":{"shape":"EventEnumShape"}
// },
// "eventstream":true
// },
@@ -353,6 +356,17 @@ public void testOperationConversion() {
// },
// "event":true
// },
+ // "EventEnumShape":{
+ // "type":"structure",
+ // "members":{
+ // "BlobShape":{"shape":"BlobShape"}
+ // },
+ // "event":true
+ // },
+ // "EnumShape":{
+ // "type":"string",
+ // "enum":[VALUE]
+ // }
// "BlobShape":{
// "type":"blob"
// }
@@ -390,6 +404,27 @@ public void testEventStreamShapeConversion() {
eventStreamShape.setMembers(new HashMap<>());
eventStreamShape.getMembers().put("EventShape", eventShapeMember);
+ C2jShape eventEnumShape = new C2jShape();
+ eventEnumShape.setType("structure");
+ eventEnumShape.setEvent(true);
+ c2jShapeMap.put("EventEnumShape", eventEnumShape);
+
+ C2jShape enumShape = new C2jShape();
+ enumShape.setType("string");
+ enumShape.setEnums(ImmutableList.of("VALUE"));
+ c2jShapeMap.put("EnumShape", enumShape);
+
+ C2jShapeMember enumShapeMember = new C2jShapeMember();
+ enumShapeMember.setShape("EnumShape");
+
+ eventEnumShape.setMembers(new HashMap<>());
+ eventEnumShape.getMembers().put("EnumShape", enumShapeMember);
+
+ C2jShapeMember eventEnumShapeMember = new C2jShapeMember();
+ eventEnumShapeMember.setShape("EventEnumShape");
+
+ eventStreamShape.getMembers().put("EvenEnumShape", eventEnumShapeMember);
+
c2jServiceModel.setShapes(c2jShapeMap);
C2jModelToGeneratorModelTransformer c2jModelToGeneratorModelTransformer = new C2jModelToGeneratorModelTransformer(c2jServiceModel, false);
@@ -397,7 +432,7 @@ public void testEventStreamShapeConversion() {
c2jModelToGeneratorModelTransformer.postProcessShapes();
Map shapes = c2jModelToGeneratorModelTransformer.shapes;
- assertEquals(3, shapes.size());
+ assertEquals(5, shapes.size());
assertEquals("EventStreamShape", shapes.get("EventStreamShape").getName());
assertTrue(shapes.get("EventStreamShape").isEventStream());
assertEquals("EventShape", shapes.get("EventShape").getName());
@@ -406,10 +441,13 @@ public void testEventStreamShapeConversion() {
assertEquals("BlobShape", shapes.get("EventShape").getEventPayloadMemberName());
assertEquals("BlobShape", shapes.get("BlobShape").getName());
assertEquals("blob", shapes.get("BlobShape").getType());
- assertEquals(1, shapes.get("EventStreamShape").getMembers().size());
+ assertEquals(2, shapes.get("EventStreamShape").getMembers().size());
assertEquals("EventShape", shapes.get("EventStreamShape").getMembers().get("EventShape").getShape().getName());
assertEquals(1, shapes.get("EventShape").getMembers().size());
assertEquals("BlobShape", shapes.get("EventShape").getMembers().get("BlobShape").getShape().getName());
assertTrue(shapes.get("EventShape").getMembers().get("BlobShape").isEventPayload());
+
+ assertFalse(shapes.get("EventEnumShape").getMembers().get("EnumShape").isEventPayload());
+ assertEquals("structure", shapes.get("EventEnumShape").getEventPayloadType());
}
}