Skip to content

Commit f800486

Browse files
committed
Move to CBOR trait from configured formats
This commit refactors the trait implementation to be specific to the CBOR wire format instead of taking a collection of possible wire formats, simplifying the process of resolving the protocol to use for generated code. It also moves the package to `smithy-protocol-traits`, removing the pluralization on `protocols`.
1 parent a043f24 commit f800486

File tree

24 files changed

+301
-459
lines changed

24 files changed

+301
-459
lines changed

settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ include ":smithy-smoke-test-traits"
3434
include ":smithy-syntax"
3535
include ":smithy-aws-endpoints"
3636
include ":smithy-aws-smoke-test-model"
37-
include ":smithy-protocols-traits"
37+
include ":smithy-protocol-traits"
File renamed without changes.

smithy-protocol-traits/build.gradle

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
description = "This module provides the implementation of protocol traits for Smithy."
7+
8+
ext {
9+
displayName = "Smithy :: Protocol Traits"
10+
moduleName = "software.amazon.smithy.protocol.traits"
11+
}
12+
13+
dependencies {
14+
api project(":smithy-utils")
15+
api project(":smithy-model")
16+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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.protocol.traits;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import software.amazon.smithy.model.node.Node;
11+
import software.amazon.smithy.model.node.ObjectNode;
12+
import software.amazon.smithy.model.shapes.ShapeId;
13+
import software.amazon.smithy.model.traits.AbstractTrait;
14+
import software.amazon.smithy.model.traits.AbstractTraitBuilder;
15+
import software.amazon.smithy.model.traits.Trait;
16+
import software.amazon.smithy.utils.ListUtils;
17+
import software.amazon.smithy.utils.ToSmithyBuilder;
18+
19+
public final class Rpcv2CborTrait extends AbstractTrait implements ToSmithyBuilder<Rpcv2CborTrait> {
20+
21+
public static final ShapeId ID = ShapeId.from("smithy.protocols#rpcv2Cbor");
22+
23+
private static final String HTTP = "http";
24+
private static final String EVENT_STREAM_HTTP = "eventStreamHttp";
25+
26+
private final List<String> http;
27+
private final List<String> eventStreamHttp;
28+
29+
private Rpcv2CborTrait(Builder builder) {
30+
super(ID, builder.getSourceLocation());
31+
http = ListUtils.copyOf(builder.http);
32+
eventStreamHttp = ListUtils.copyOf(builder.eventStreamHttp);
33+
}
34+
35+
/**
36+
* Creates a new {@code Builder}.
37+
*/
38+
public static Builder builder() {
39+
return new Builder();
40+
}
41+
42+
/**
43+
* Updates the builder from a Node.
44+
*
45+
* @param node Node object that must be a valid {@code ObjectNode}.
46+
* @return Returns the updated builder.
47+
*/
48+
public static Rpcv2CborTrait fromNode(Node node) {
49+
Builder builder = builder().sourceLocation(node);
50+
ObjectNode objectNode = node.expectObjectNode();
51+
objectNode.getArrayMember(HTTP).map(values -> Node.loadArrayOfString(HTTP, values))
52+
.ifPresent(builder::http);
53+
objectNode.getArrayMember(EVENT_STREAM_HTTP).map(values -> Node.loadArrayOfString(EVENT_STREAM_HTTP, values))
54+
.ifPresent(builder::eventStreamHttp);
55+
return builder.build();
56+
}
57+
58+
/**
59+
* Gets the priority ordered list of supported HTTP protocol versions.
60+
*
61+
* @return Returns the supported HTTP protocol versions.
62+
*/
63+
public List<String> getHttp() {
64+
return http;
65+
}
66+
67+
/**
68+
* Gets the priority ordered list of supported HTTP protocol versions that are required when
69+
* using event streams.
70+
*
71+
* @return Returns the supported event stream HTTP protocol versions.
72+
*/
73+
public List<String> getEventStreamHttp() {
74+
return eventStreamHttp;
75+
}
76+
77+
@Override
78+
protected Node createNode() {
79+
ObjectNode.Builder builder = Node.objectNodeBuilder().sourceLocation(getSourceLocation());
80+
if (!getHttp().isEmpty()) {
81+
builder.withMember(HTTP, Node.fromStrings(getHttp()));
82+
}
83+
if (!getEventStreamHttp().isEmpty()) {
84+
builder.withMember(EVENT_STREAM_HTTP, Node.fromStrings(getEventStreamHttp()));
85+
}
86+
return builder.build();
87+
}
88+
89+
@Override
90+
public Builder toBuilder() {
91+
return builder().http(http).eventStreamHttp(eventStreamHttp);
92+
}
93+
94+
/**
95+
* Builder for creating a {@code Rpcv2CborTrait}.
96+
*/
97+
public static final class Builder extends AbstractTraitBuilder<Rpcv2CborTrait, Builder> {
98+
99+
private final List<String> http = new ArrayList<>();
100+
private final List<String> eventStreamHttp = new ArrayList<>();
101+
102+
@Override
103+
public Rpcv2CborTrait build() {
104+
return new Rpcv2CborTrait(this);
105+
}
106+
107+
/**
108+
* Sets the list of supported HTTP protocols.
109+
*
110+
* @param http HTTP protocols to set and replace.
111+
* @return Returns the builder.
112+
*/
113+
public Builder http(List<String> http) {
114+
this.http.clear();
115+
this.http.addAll(http);
116+
return this;
117+
}
118+
119+
/**
120+
* Sets the list of supported event stream HTTP protocols.
121+
*
122+
* @param eventStreamHttp Event stream HTTP protocols to set and replace.
123+
* @return Returns the builder.
124+
*/
125+
public Builder eventStreamHttp(List<String> eventStreamHttp) {
126+
this.eventStreamHttp.clear();
127+
this.eventStreamHttp.addAll(eventStreamHttp);
128+
return this;
129+
}
130+
}
131+
132+
/**
133+
* Implements the {@code AbstractTrait.Provider}.
134+
*/
135+
public static final class Provider extends AbstractTrait.Provider {
136+
137+
public Provider() {
138+
super(ID);
139+
}
140+
141+
@Override
142+
public Trait createTrait(ShapeId target, Node value) {
143+
Rpcv2CborTrait result = fromNode(value);
144+
result.setNodeCache(value);
145+
return result;
146+
}
147+
}
148+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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.protocol.traits;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import software.amazon.smithy.model.Model;
11+
import software.amazon.smithy.model.shapes.ServiceShape;
12+
import software.amazon.smithy.model.validation.AbstractValidator;
13+
import software.amazon.smithy.model.validation.ValidationEvent;
14+
import software.amazon.smithy.utils.SmithyInternalApi;
15+
16+
/**
17+
* Validates models implementing the {@code Rpcv2CborTrait} against its constraints by:
18+
*
19+
* - Ensuring that every entry in {@code eventStreamHttp} also appears in the {@code http} property
20+
* of a protocol trait.
21+
*/
22+
@SmithyInternalApi
23+
public final class Rpcv2CborTraitValidator extends AbstractValidator {
24+
25+
@Override
26+
public List<ValidationEvent> validate(Model model) {
27+
List<ValidationEvent> events = new ArrayList<>();
28+
for (ServiceShape serviceShape : model.getServiceShapesWithTrait(Rpcv2CborTrait.class)) {
29+
Rpcv2CborTrait protocolTrait = serviceShape.expectTrait(Rpcv2CborTrait.class);
30+
31+
List<String> invalid = new ArrayList<>(protocolTrait.getEventStreamHttp());
32+
invalid.removeAll(protocolTrait.getHttp());
33+
if (!invalid.isEmpty()) {
34+
events.add(error(serviceShape, protocolTrait,
35+
String.format("The following values of the `eventStreamHttp` property do "
36+
+ "not also appear in the `http` property of the %s protocol "
37+
+ "trait: %s", protocolTrait.toShapeId(), invalid)));
38+
}
39+
}
40+
return events;
41+
}
42+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
/**
7+
* Defines protocols for Smithy.
8+
*/
9+
@SmithyUnstableApi
10+
package software.amazon.smithy.protocol.traits;
11+
12+
import software.amazon.smithy.utils.SmithyUnstableApi;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
software.amazon.smithy.protocol.traits.Rpcv2CborTrait$Provider
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
software.amazon.smithy.protocol.traits.Rpcv2CborTraitValidator

smithy-protocols-traits/src/main/resources/META-INF/smithy/smithy.protocols.rpcv2.smithy renamed to smithy-protocol-traits/src/main/resources/META-INF/smithy/smithy.protocols.rpcv2.smithy

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,26 @@ $version: "2.0"
22

33
namespace smithy.protocols
44

5-
use smithy.api#httpError
65
use smithy.api#cors
76
use smithy.api#endpoint
87
use smithy.api#hostLabel
8+
use smithy.api#httpError
99

10-
/// An RPC protocol with support for multiple wire formats.
10+
/// An RPC-based protocol that serializes CBOR payloads.
1111
@trait(selector: "service")
1212
@protocolDefinition(traits: [
13-
httpError
1413
cors
1514
endpoint
1615
hostLabel
16+
httpError
1717
])
18-
structure rpcv2 {
18+
structure rpcv2Cbor {
1919
/// Priority ordered list of supported HTTP protocol versions.
2020
http: StringList
21+
2122
/// Priority ordered list of supported HTTP protocol versions
2223
/// that are required when using event streams.
2324
eventStreamHttp: StringList
24-
25-
/// Priority ordered list of supported wire formats.
26-
@required
27-
format: StringList
2825
}
2926

3027
/// A list of String shapes.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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.protocol.traits;
7+
8+
import org.junit.jupiter.api.Assertions;
9+
import org.junit.jupiter.api.Test;
10+
import software.amazon.smithy.model.node.Node;
11+
import software.amazon.smithy.model.shapes.ShapeId;
12+
import software.amazon.smithy.model.traits.Trait;
13+
import software.amazon.smithy.model.traits.TraitFactory;
14+
import java.util.Optional;
15+
16+
public class Rpcv2CborTraitTest {
17+
18+
@Test
19+
public void loadsTraitWithDefaults() {
20+
Node node = Node.objectNode();
21+
TraitFactory provider = TraitFactory.createServiceFactory();
22+
Optional<Trait> trait = provider.createTrait(Rpcv2CborTrait.ID, ShapeId.from("ns.foo#foo"), node);
23+
24+
Assertions.assertTrue(trait.isPresent());
25+
Assertions.assertTrue(trait.get() instanceof Rpcv2CborTrait);
26+
Rpcv2CborTrait smithyRpcV2Trait = (Rpcv2CborTrait) trait.get();
27+
Assertions.assertEquals(smithyRpcV2Trait.toNode(), node);
28+
}
29+
}

smithy-protocols-traits/src/test/java/software/amazon/smithy/protocols/traits/TestRunnerTest.java renamed to smithy-protocol-traits/src/test/java/software/amazon/smithy/protocol/traits/TestRunnerTest.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
/*
2-
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5-
* in compliance with the License. A copy of the License is located at
6-
*
7-
* http://aws.amazon.com/apache2.0
8-
*
9-
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
10-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11-
* specific language governing permissions and limitations under the License.
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
124
*/
135

14-
package software.amazon.smithy.protocols.traits;
6+
package software.amazon.smithy.protocol.traits;
157

168
import java.util.concurrent.Callable;
179
import java.util.stream.Stream;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[ERROR] smithy.example#InvalidService1: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2 protocol trait: [http/1.1] | Rpcv2Trait
2-
[ERROR] smithy.example#InvalidService2: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2 protocol trait: [http/1.1] | Rpcv2Trait
3-
[ERROR] smithy.example#InvalidService3: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2 protocol trait: [http/1.1, h2c] | Rpcv2Trait
1+
[ERROR] smithy.example#InvalidService1: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2Cbor protocol trait: [http/1.1] | Rpcv2CborTrait
2+
[ERROR] smithy.example#InvalidService2: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2Cbor protocol trait: [http/1.1] | Rpcv2CborTrait
3+
[ERROR] smithy.example#InvalidService3: The following values of the `eventStreamHttp` property do not also appear in the `http` property of the smithy.protocols#rpcv2Cbor protocol trait: [http/1.1, h2c] | Rpcv2CborTrait
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
$version: "2.0"
2+
3+
namespace smithy.example
4+
5+
use smithy.protocols#rpcv2Cbor
6+
7+
@rpcv2Cbor(http: ["h2", "http/1.1"], eventStreamHttp: ["h2"])
8+
service ValidService1 {
9+
version: "2023-02-10"
10+
}
11+
12+
@rpcv2Cbor(http: ["h2"], eventStreamHttp: ["h2"])
13+
service ValidService2 {
14+
version: "2023-02-10"
15+
}
16+
17+
@rpcv2Cbor(http: [], eventStreamHttp: [])
18+
service ValidService3 {
19+
version: "2023-02-10"
20+
}
21+
22+
@rpcv2Cbor(http: ["http/1.1"], eventStreamHttp: [])
23+
service ValidService4 {
24+
version: "2023-02-10"
25+
}
26+
27+
@rpcv2Cbor(eventStreamHttp: ["http/1.1"])
28+
service InvalidService1 {
29+
version: "2023-02-10"
30+
}
31+
32+
@rpcv2Cbor(http: ["h2"], eventStreamHttp: ["http/1.1"])
33+
service InvalidService2 {
34+
version: "2023-02-10"
35+
}
36+
37+
@rpcv2Cbor(http: ["h2"], eventStreamHttp: ["h2", "http/1.1", "h2c"])
38+
service InvalidService3 {
39+
version: "2023-02-10"
40+
}

smithy-protocols-traits/build.gradle

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)