Skip to content

Commit bc2be87

Browse files
committed
Add transform to mark required idempotency tokens client optional
1 parent bf32a87 commit bc2be87

File tree

8 files changed

+147
-0
lines changed

8 files changed

+147
-0
lines changed

docs/source-2.0/guides/smithy-build-json.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,31 @@ applied.
573573
use an :ref:`enum shape <enum>` instead to avoid needing to use this
574574
transform.
575575

576+
.. _markIdempotencyTokensClientOptional:
577+
578+
markIdempotencyTokensClientOptional
579+
-----------------------------------
580+
581+
Marks required Idempotency token members as ``@clientOptional``.
582+
583+
Idempotency tokens that are required should fail validation, but shouldn't be required to create a type,
584+
allowing for a default value to get injected when missing.
585+
586+
.. code-block:: json
587+
588+
{
589+
"version": "1.0",
590+
"projections": {
591+
"exampleProjection": {
592+
"transforms": [
593+
{
594+
"name": "markIdempotencyTokensClientOptional"
595+
}
596+
]
597+
}
598+
}
599+
}
600+
576601
.. _changeTypes:
577602

578603
changeTypes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.build.transforms;
7+
8+
import software.amazon.smithy.build.ProjectionTransformer;
9+
import software.amazon.smithy.build.TransformContext;
10+
import software.amazon.smithy.model.Model;
11+
12+
/**
13+
* {@code markIdempotencyTokensClientOptional} marks required idempotency token fields clientOptional.
14+
*/
15+
public final class MarkIdempotencyTokensClientOptional implements ProjectionTransformer {
16+
17+
@Override
18+
public String getName() {
19+
return "markIdempotencyTokensClientOptional";
20+
}
21+
22+
@Override
23+
public Model transform(TransformContext context) {
24+
Model model = context.getModel();
25+
return context.getTransformer().markIdempotencyTokensClientOptional(model);
26+
}
27+
}

smithy-build/src/main/resources/META-INF/services/software.amazon.smithy.build.ProjectionTransformer

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ software.amazon.smithy.build.transforms.IncludeShapesByTag
1818
software.amazon.smithy.build.transforms.IncludeTags
1919
software.amazon.smithy.build.transforms.IncludeTraits
2020
software.amazon.smithy.build.transforms.IncludeTraitsByTag
21+
software.amazon.smithy.build.transforms.MarkIdempotencyTokensClientOptional
22+
software.amazon.smithy.build.transforms.RemoveDeprecatedShapes
2123
software.amazon.smithy.build.transforms.RemoveTraitDefinitions
2224
software.amazon.smithy.build.transforms.RemoveUnusedShapes
2325
software.amazon.smithy.build.transforms.RenameShapes

smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/directed/CodegenDirector.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,18 @@ public void removeShapesDeprecatedBeforeVersion(String relativeVersion) {
315315
});
316316
}
317317

318+
/**
319+
* Marks idempotency token fields {@code clientOptional}.
320+
*
321+
* @see ModelTransformer#markIdempotencyTokensClientOptional(Model)
322+
*/
323+
public void markIdempotencyTokensClientOptional() {
324+
transforms.add((model, transformer) -> {
325+
LOGGER.finest("Marking Idempotency Token fields `@clientOptional`");
326+
return transformer.filterDeprecatedRelativeVersion(model);
327+
});
328+
}
329+
318330
/**
319331
* Changes each compatible string shape with the enum trait to an enum shape.
320332
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package software.amazon.smithy.model.transform;
2+
3+
4+
import software.amazon.smithy.model.Model;
5+
import software.amazon.smithy.model.shapes.Shape;
6+
import software.amazon.smithy.model.traits.ClientOptionalTrait;
7+
import software.amazon.smithy.model.traits.IdempotencyTokenTrait;
8+
import software.amazon.smithy.model.traits.RequiredTrait;
9+
10+
/**
11+
* Mark Idempotency token members as clientOptional so they can be injected if missing.
12+
*/
13+
final class MakeIdempotencyTokenClientOptional {
14+
public static Model transform(Model model) {
15+
return ModelTransformer.create().mapShapes(model, shape -> {
16+
if (shape.isMemberShape()
17+
&& shape.hasTrait(RequiredTrait.class)
18+
&& shape.hasTrait(IdempotencyTokenTrait.class)
19+
&& !shape.hasTrait(ClientOptionalTrait.class)) {
20+
return Shape.shapeToBuilder(shape).addTrait(new ClientOptionalTrait()).build();
21+
}
22+
return shape;
23+
});
24+
}
25+
}

smithy-model/src/main/java/software/amazon/smithy/model/transform/ModelTransformer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import software.amazon.smithy.model.traits.synthetic.OriginalShapeIdTrait;
4444
import software.amazon.smithy.utils.FunctionalUtils;
4545
import software.amazon.smithy.utils.ListUtils;
46+
import sun.awt.ModalityListener;
4647

4748
/**
4849
* Class used to transform {@link Model}s.
@@ -720,4 +721,17 @@ public Model filterDeprecatedRelativeDate(Model model, String relativeDate) {
720721
public Model filterDeprecatedRelativeVersion(Model model, String relativeVersion) {
721722
return new FilterDeprecatedRelativeVersion(relativeVersion).transform(this, model);
722723
}
724+
725+
/**
726+
* Marks any Idempotency token fields {@code @clientOptional} so that missing tokens can be injected.
727+
*
728+
* <p>Idempotency tokens that are required should fail validation, but shouldn't be required to create a type,
729+
* allowing for a default value to get injected when missing.
730+
*
731+
* @param model Model to transform.
732+
* @return Returns the transformed model.
733+
*/
734+
public Model markIdempotencyTokensClientOptional(Model model) {
735+
return MakeIdempotencyTokenClientOptional.transform(model);
736+
}
723737
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package software.amazon.smithy.model.transform;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import org.junit.jupiter.api.Test;
6+
import software.amazon.smithy.model.Model;
7+
import software.amazon.smithy.model.shapes.Shape;
8+
import software.amazon.smithy.model.shapes.ShapeId;
9+
import software.amazon.smithy.model.traits.ClientOptionalTrait;
10+
import software.amazon.smithy.model.traits.IdempotencyTokenTrait;
11+
import software.amazon.smithy.model.traits.RequiredTrait;
12+
13+
public class MakeIdempotencyTokenClientOptionalTest {
14+
private static final ShapeId operationInput = ShapeId.from("smithy.example#IdempotencyTokenRequiredInput");
15+
16+
@Test
17+
void compareTransform() {
18+
Model before = Model.assembler()
19+
.addImport(FlattenPaginationInfoTest.class.getResource("idempotency-token.smithy"))
20+
.assemble()
21+
.unwrap();
22+
Model result = ModelTransformer.create().markIdempotencyTokensClientOptional(before);
23+
24+
Shape input = result.expectShape(operationInput);
25+
Shape member = result.expectShape(input.getMember("token").get().getId());
26+
27+
assertTrue(member.hasTrait(ClientOptionalTrait.class));
28+
assertTrue(member.hasTrait(RequiredTrait.class));
29+
assertTrue(member.hasTrait(IdempotencyTokenTrait.class));
30+
}
31+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
$version: "2.0"
2+
3+
namespace smithy.example
4+
5+
operation IdempotencyTokenRequired {
6+
input := {
7+
@idempotencyToken
8+
@required
9+
token: String
10+
}
11+
}

0 commit comments

Comments
 (0)