Skip to content

Commit f885df4

Browse files
committed
Add support for eventheader trait
1 parent 955e21b commit f885df4

File tree

4 files changed

+75
-30
lines changed

4 files changed

+75
-30
lines changed

tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/domainmodels/codegeneration/Shape.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class Shape {
5454
private String eventPayloadMemberName;
5555
private String eventPayloadType;
5656
private boolean isOutgoingEventStream;
57+
private Map<String, Shape> eventStreamHeaders;
5758
private boolean exception;
5859
private boolean sensitive;
5960
private boolean hasPreSignedUrl;

tools/code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/transform/C2jModelToGeneratorModelTransformer.java

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.stream.Collectors;
2828

2929
import org.apache.commons.lang3.StringUtils;
30+
import org.apache.commons.lang3.tuple.Pair;
3031
import software.amazon.smithy.jmespath.JmespathExpression;
3132

3233
public class C2jModelToGeneratorModelTransformer {
@@ -336,38 +337,46 @@ header insertion there. So strip this out of the model (affects S3's PutObjectR
336337
// Header only event
337338
shape.setEventPayloadType(null);
338339
} else if (shape.hasEventPayloadMembers() || shape.getMembers().size() == 1) {
339-
if (shape.getMembers().size() == 1) {
340-
shape.getMembers().entrySet().stream().forEach(memberEntry -> {
341-
/**
342-
* Note: this is complicated and potentially not completely correct.
343-
* So touch at your own risk until we have protocol tests supported.
344-
* In summary:
345-
* - we need to determine how to serialize events in eventstream
346-
* - to specify payload there is an eventpayload trait
347-
* - but what happens if that trait is not specified
348-
* - if there is one field and its a string or struct then we assume that field is event payload
349-
* - if there is one field and its a blob within structure and not explicitly marked as eventpayload then parent shape is eventpayload
350-
* - if that one field is of any other type then treat parent shape as eventpayload
351-
* - if there is more than one field then parent shape is the payload
352-
*/
353-
Shape memberShape = memberEntry.getValue().getShape();
354-
if (memberShape.isString() ||
355-
memberShape.isBlob() && !shape.isStructure() ||
356-
memberShape.isBlob() && memberEntry.getValue().isEventPayload() ||
357-
memberShape.isStructure()) {
358-
memberEntry.getValue().setEventPayload(true);
359-
shape.setEventPayloadMemberName(memberEntry.getKey());
360-
shape.setEventPayloadType(memberShape.getType());
361-
} else {
362-
if (!shape.getType().equals("structure")) {
363-
throw new RuntimeException("Event shape should always has \"structure\" type if single member cannot be event payload.");
364-
}
365-
shape.setEventPayloadType(shape.getType());
340+
if (shape.getMembers().values().stream().filter(member -> !member.isEventHeader()).count() == 1) {
341+
final List<Map.Entry<String, ShapeMember>> memberEntries = shape.getMembers().entrySet().stream()
342+
.filter(member -> !member.getValue().isEventHeader())
343+
.collect(Collectors.toList());
344+
if (memberEntries.size() != 1) {
345+
throw new RuntimeException("Event shape should have exactly one payload member for event payload.");
346+
}
347+
/**
348+
* Note: this is complicated and potentially not completely correct.
349+
* So touch at your own risk until we have protocol tests supported.
350+
* In summary:
351+
* - we need to determine how to serialize events in eventstream
352+
* - to specify payload there is an eventpayload trait
353+
* - but what happens if that trait is not specified
354+
* - if there is one field and its a string or struct then we assume that field is event payload
355+
* - if there is one field and its a blob within structure and not explicitly marked as eventpayload then parent shape is eventpayload
356+
* - if that one field is of any other type then treat parent shape as eventpayload
357+
* - if there is more than one field then parent shape is the payload
358+
*/
359+
final Map.Entry<String, ShapeMember> memberEntry = memberEntries.get(0);
360+
final Shape memberShape = memberEntry.getValue().getShape();
361+
if (memberShape.isString() ||
362+
memberShape.isBlob() && !shape.isStructure() ||
363+
memberShape.isBlob() && memberEntry.getValue().isEventPayload() ||
364+
memberShape.isStructure()) {
365+
memberEntry.getValue().setEventPayload(true);
366+
shape.setEventPayloadMemberName(memberEntry.getKey());
367+
shape.setEventPayloadType(memberShape.getType());
368+
} else {
369+
if (!shape.getType().equals("structure")) {
370+
throw new RuntimeException("Event shape should always has \"structure\" type if single member cannot be event payload.");
366371
}
367-
368-
});
372+
shape.setEventPayloadType(shape.getType());
373+
}
374+
shape.setEventStreamHeaders(shape.getMembers().entrySet().stream()
375+
.filter(headerEntry -> headerEntry.getValue().isEventHeader())
376+
.map(headerEntry -> Pair.of(headerEntry.getKey(), headerEntry.getValue().getShape()))
377+
.collect(Collectors.toMap(Pair::getKey, Pair::getValue)));
369378
} else {
370-
throw new RuntimeException("Event shape used in Event Stream should only has one member if it has event payload member.");
379+
throw new RuntimeException("Event shape used in Event Stream should only has one non header member if it has event payload member.");
371380
}
372381
} else if (shape.getMembers().size() > 1) {
373382
if (!shape.getType().equals("structure")) {

tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/EventHeader.vm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,32 @@ namespace Model
4949
inline ${classNameRef} With${memberKeyWithFirstLetterCapitalized}(${moveType} value) { Set${memberKeyWithFirstLetterCapitalized}(std::move(value)); return *this;}
5050
///@}
5151

52+
#foreach($eventHeaderMapping in $shape.getEventStreamHeaders().entrySet())
53+
#set($eventHeader = $eventHeaderMapping.getValue())
54+
#set($eventHeaderMemberName = $CppViewHelper.computeMemberVariableName($eventHeader.getName()))
55+
#set($eventHeaderMemberNameWithFirstLetterCapitalized = $CppViewHelper.capitalizeFirstChar($eventHeader.getName()))
56+
#set($eventHeaderMemberHaseBeenSetName = $CppViewHelper.computeVariableHasBeenSetName($eventHeader.getName()))
57+
#set($eventHeaderMemberType = $CppViewHelper.computeCppType($eventHeader))
58+
inline const $eventHeaderMemberType Get${eventHeaderMemberNameWithFirstLetterCapitalized}() const { return $eventHeaderMemberName; }
59+
inline bool ${eventHeaderMemberNameWithFirstLetterCapitalized}HasBeenSet() const { return $eventHeaderMemberHaseBeenSetName; }
60+
template<typename T = $eventHeaderMemberType>
61+
void Set${eventHeaderMemberNameWithFirstLetterCapitalized}(T&& value) { $eventHeaderMemberHaseBeenSetName = true; $eventHeaderMemberName = std::forward<T>(value); }
62+
template<typename T = $eventHeaderMemberType>
63+
${classNameRef} With${eventHeaderMemberNameWithFirstLetterCapitalized}(T&& value) { Set${eventHeaderMemberNameWithFirstLetterCapitalized}(value); return *this; }
64+
65+
#end
5266
private:
5367

5468
Aws::Vector<unsigned char> $memberVariableName;
5569
bool ${CppViewHelper.computeVariableHasBeenSetName($blobMember.key)} = false;
70+
#foreach($eventHeaderMapping in $shape.getEventStreamHeaders().entrySet())
71+
#set($eventHeader = $eventHeaderMapping.getValue())
72+
#set($eventHeaderMemberName = $CppViewHelper.computeMemberVariableName($eventHeader.getName()))
73+
#set($eventHeaderMemberHaseBeenSetName = $CppViewHelper.computeVariableHasBeenSetName($eventHeader.getName()))
74+
#set($eventHeaderMemberType = $CppViewHelper.computeCppType($eventHeader))
75+
$eventHeaderMemberType $eventHeaderMemberName;
76+
bool $eventHeaderMemberHaseBeenSetName;
77+
#end
5678
};
5779

5880
} // namespace Model

tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/JsonEventStreamHandlerSource.vm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ namespace Model
134134
${eventShape.name} event(GetEventPayloadWithOwnership());
135135
m_on${eventShape.name}(event);
136136
break;
137+
#elseif($eventShape.getEventStreamHeaders().size() > 0)
138+
${eventShape.name} event(GetEventPayloadWithOwnership());
139+
#foreach($eventStreamHeaderMapping in $eventShape.getEventStreamHeaders().entrySet())
140+
#set($eventStreamHeader = $eventStreamHeaderMapping.getValue())
141+
#set($eventHeaderMemberNameWithFirstLetterCapitalized = $CppViewHelper.capitalizeFirstChar($eventStreamHeader.getName()))
142+
#set($headerVarName = $CppViewHelper.lowercasesFirstChar("${eventStreamHeader.getName()}Header"))
143+
const auto $headerVarName = headers.find("${eventStreamHeaderMapping.getKey()}");
144+
if ($headerVarName != headers.end()) {
145+
event.Set$eventHeaderMemberNameWithFirstLetterCapitalized($headerVarName->second.GetEventHeaderValueAsString());
146+
}
147+
#end
148+
m_on${eventShape.name}(event);
149+
break;
137150
##multiple members or the only one member is structure
138151
#elseif(!$eventShape.members.isEmpty())
139152
JsonValue json(GetEventPayloadAsString());

0 commit comments

Comments
 (0)