in codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java [108:233]
public Model preprocessModel(Model model, TypeScriptSettings settings) {
ServiceShape serviceShape = settings.getService(model);
if (!isS3(serviceShape)) {
return model;
}
Model.Builder modelBuilder = model.toBuilder();
boolean hasRuleset = !model.getServiceShapesWithTrait(EndpointRuleSetTrait.class).isEmpty();
TopDownIndex topDownIndex = TopDownIndex.of(model);
Set<StructureShape> inputShapes = new HashSet<>();
for (OperationShape operationShape : topDownIndex.getContainedOperations(serviceShape)) {
if (NON_BUCKET_ENDPOINT_OPERATIONS.contains(operationShape.getId().getName(serviceShape))) {
continue;
}
operationShape.getInput().ifPresent(inputShapeId -> {
StructureShape inputShape = model.expectShape(inputShapeId, StructureShape.class);
inputShape.getMember("Bucket").ifPresent(bucketMember -> {
bucketMember.getTrait(DocumentationTrait.class).ifPresent(documentationTrait -> {
StructureShape.Builder inputShapeBuilder = inputShape.toBuilder();
MemberShape.Builder builder = MemberShape.shapeToBuilder(bucketMember);
String newDocString = documentationTrait.getValue() + "\n" + CRT_NOTIFICATION;
MemberShape newMemberShape = builder.addTrait(new DocumentationTrait(newDocString)).build();
inputShapeBuilder.addMember(newMemberShape);
inputShapes.add(inputShapeBuilder.build());
});
});
});
}
LOGGER.info("Patching " + inputShapes.size() + " input shapes with CRT notification");
boolean expiresShapeIsPresent = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).isPresent();
if (expiresShapeIsPresent) {
// ExpiresString customization part 1:
// enforce that "com.amazonaws.s3#Expires" retains type=timestamp.
// add a shape "com.amazonaws.s3#ExpiresString" of type=string.
Shape expiresShape = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).get();
TimestampShape expiresTimestampShape = TimestampShape.builder()
.id(expiresShape.getId())
.build();
StringShape expiresStringShape = StringShape.builder()
.id("com.amazonaws.s3#ExpiresString")
.build();
modelBuilder
.removeShape(expiresShape.getId())
.addShapes(expiresTimestampShape, expiresStringShape);
// ExpiresString customization part 2:
// for any output shape member targeting Expires, add a member ExpiresString targeting ExpiresString.
// and mark Expires deprecated in favor of ExpiresString.
// move Expires documentation trait to ExpiresString.
// set the httpHeader trait of ExpiresString to be ExpiresString.
// SDK middleware will take care of copying expires header to expiresstring header prior to deserialization.
for (OperationShape operationShape : topDownIndex.getContainedOperations(serviceShape)) {
if (operationShape.getOutput().isEmpty()) {
continue;
}
StructureShape structureShape = model.expectShape(
operationShape.getOutputShape(), StructureShape.class
);
Set<Map.Entry<String, MemberShape>> memberEntries = structureShape
.getAllMembers()
.entrySet();
StructureShape.Builder structureShapeBuilder = structureShape.toBuilder();
boolean isTargetingExpires = structureShape
.getAllMembers()
.values()
.stream()
.anyMatch(memberShape -> memberShape.getTarget().equals(expiresShape.getId()));
if (isTargetingExpires) {
for (Map.Entry<String, MemberShape> entry : memberEntries) {
String memberName = entry.getKey();
MemberShape memberShape = entry.getValue();
Optional<HttpHeaderTrait> httpHeader = memberShape.getTrait(HttpHeaderTrait.class);
Optional<DocumentationTrait> doc = memberShape.getTrait(DocumentationTrait.class);
if (memberShape.getTarget().equals(expiresShape.getId())
&& httpHeader.isPresent()) {
structureShapeBuilder
.removeMember(memberName)
.addMember(
memberName,
expiresTimestampShape.getId(),
(m) -> {
m
.addTrait(new DocumentationTrait("Deprecated in favor of ExpiresString."))
.addTrait(httpHeader.get())
.addTrait(DeprecatedTrait.builder().build());
}
)
.addMember(
"ExpiresString",
expiresStringShape.getId(),
(m) -> {
m.addTrait(new HttpHeaderTrait("ExpiresString"));
doc.ifPresent(m::addTrait);
}
);
} else {
// This is done to preserve the member order
// and insert ExpiresString adjacent to Expires.
structureShapeBuilder
.removeMember(memberName)
.addMember(memberName, memberShape.getTarget(), (m) -> {
m.addTraits(memberShape.getAllTraits().values());
});
}
}
modelBuilder
.addShape(structureShapeBuilder.build());
}
}
}
Model builtModel = modelBuilder.addShapes(inputShapes).build();
if (hasRuleset) {
ModelTransformer.create().mapShapes(
builtModel, AddS3Config::removeHostPrefixTrait
);
}
return builtModel;
}