Skip to content

Commit ad3af5a

Browse files
adamthom-amznmillems
authored andcommitted
Fix generation for services that contain operations with the same name as the service.
If a 'FooService' contains an operation named 'Foo', the generator will attempt to generate a 'FooRequest' that extends an abstract 'FooRequest'. This adds 'Default' to the concrete class names only in cases where there is an operation with a clashing name.
1 parent 17b47ac commit ad3af5a

File tree

7 files changed

+102
-10
lines changed

7 files changed

+102
-10
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"type": "bugfix",
4+
"description": "Fix generation for services that contain operations with the same name as the service."
5+
}

codegen/src/main/java/software/amazon/awssdk/codegen/AddEmptyInputShape.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
package software.amazon.awssdk.codegen;
1717

18-
import static software.amazon.awssdk.codegen.internal.Constant.REQUEST_CLASS_SUFFIX;
1918
import static software.amazon.awssdk.codegen.internal.Utils.createInputShapeMarshaller;
2019
import static software.amazon.awssdk.codegen.internal.Utils.unCapitalize;
2120

@@ -62,7 +61,7 @@ private Map<String, ShapeModel> addEmptyInputShapes(
6261

6362
Input input = operation.getInput();
6463
if (input == null) {
65-
String inputShape = operationName + REQUEST_CLASS_SUFFIX;
64+
String inputShape = namingStrategy.getRequestClassName(operationName);
6665
OperationModel operationModel = javaOperationMap.get(operationName);
6766

6867
operationModel.setInput(new VariableModel(unCapitalize(inputShape), inputShape));

codegen/src/main/java/software/amazon/awssdk/codegen/AddEmptyOutputShape.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
package software.amazon.awssdk.codegen;
1717

18-
import static software.amazon.awssdk.codegen.internal.Constant.RESPONSE_CLASS_SUFFIX;
19-
2018
import java.util.HashMap;
2119
import java.util.Map;
2220
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
@@ -58,7 +56,7 @@ private Map<String, ShapeModel> addEmptyOutputShapes(
5856

5957
Output output = operation.getOutput();
6058
if (output == null) {
61-
String outputShape = operationName + RESPONSE_CLASS_SUFFIX;
59+
String outputShape = namingStrategy.getResponseClassName(operationName);
6260
OperationModel operationModel = currentOperations.get(operationName);
6361

6462
operationModel.setReturnType(new ReturnTypeModel(outputShape));

codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class DefaultNamingStrategy implements NamingStrategy {
5050

5151
private static Logger log = Logger.loggerFor(DefaultNamingStrategy.class);
5252

53+
private static final String COLLISION_DISAMBIGUATION_PREFIX = "Default";
54+
5355
private static final Set<String> RESERVED_KEYWORDS;
5456

5557
private static final Set<String> RESERVED_EXCEPTION_METHOD_NAMES;
@@ -191,23 +193,39 @@ private String getCustomizedPackageName(String serviceName, String defaultPatter
191193

192194
@Override
193195
public String getExceptionName(String errorShapeName) {
196+
String baseName;
194197
if (errorShapeName.endsWith(FAULT_CLASS_SUFFIX)) {
195-
return pascalCase(errorShapeName.substring(0, errorShapeName.length() - FAULT_CLASS_SUFFIX.length())) +
198+
baseName = pascalCase(errorShapeName.substring(0, errorShapeName.length() - FAULT_CLASS_SUFFIX.length())) +
196199
EXCEPTION_CLASS_SUFFIX;
197200
} else if (errorShapeName.endsWith(EXCEPTION_CLASS_SUFFIX)) {
198-
return pascalCase(errorShapeName);
201+
baseName = pascalCase(errorShapeName);
202+
} else {
203+
baseName = pascalCase(errorShapeName) + EXCEPTION_CLASS_SUFFIX;
199204
}
200-
return pascalCase(errorShapeName) + EXCEPTION_CLASS_SUFFIX;
205+
if (baseName.equals(getServiceName() + EXCEPTION_CLASS_SUFFIX)) {
206+
return COLLISION_DISAMBIGUATION_PREFIX + baseName;
207+
}
208+
return baseName;
201209
}
202210

203211
@Override
204212
public String getRequestClassName(String operationName) {
205-
return pascalCase(operationName) + REQUEST_CLASS_SUFFIX;
213+
String baseName = pascalCase(operationName) + REQUEST_CLASS_SUFFIX;
214+
if (!operationName.equals(getServiceName())) {
215+
return baseName;
216+
}
217+
218+
return COLLISION_DISAMBIGUATION_PREFIX + baseName;
206219
}
207220

208221
@Override
209222
public String getResponseClassName(String operationName) {
210-
return pascalCase(operationName) + RESPONSE_CLASS_SUFFIX;
223+
String baseName = pascalCase(operationName) + RESPONSE_CLASS_SUFFIX;
224+
if (!operationName.equals(getServiceName())) {
225+
return baseName;
226+
}
227+
228+
return COLLISION_DISAMBIGUATION_PREFIX + baseName;
211229
}
212230

213231
@Override

codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,35 @@
1515

1616
package software.amazon.awssdk.codegen;
1717

18+
import static org.assertj.core.api.Assertions.assertThat;
1819
import static org.junit.Assert.assertEquals;
1920

2021
import java.io.File;
2122
import org.junit.Test;
2223
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
2324
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
25+
import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
2426
import software.amazon.awssdk.codegen.model.service.ServiceModel;
2527
import software.amazon.awssdk.codegen.utils.ModelLoaderUtils;
2628

2729
public class IntermediateModelBuilderTest {
2830

31+
@Test
32+
public void testServiceAndShapeNameCollisions() throws Exception {
33+
final File modelFile = new File(IntermediateModelBuilderTest.class
34+
.getResource("poet/client/c2j/collision/service-2.json").getFile());
35+
IntermediateModel testModel = new IntermediateModelBuilder(
36+
C2jModels.builder()
37+
.serviceModel(ModelLoaderUtils.loadModel(ServiceModel.class, modelFile))
38+
.customizationConfig(CustomizationConfig.create())
39+
.build())
40+
.build();
41+
42+
assertThat(testModel.getShapes().values())
43+
.extracting(ShapeModel::getShapeName)
44+
.containsExactlyInAnyOrder("DefaultCollisionException", "DefaultCollisionRequest", "DefaultCollisionResponse");
45+
}
46+
2947
@Test
3048
public void sharedOutputShapesLinkCorrectlyToOperationOutputs() {
3149
final File modelFile = new File(IntermediateModelBuilderTest.class

codegen/src/test/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategyTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ public void sharedModel_providingPackageName_shouldUseProvidedPacakgeName() {
250250

251251
@Test
252252
public void modelNameShouldHavePascalCase() {
253+
when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
254+
when(serviceMetadata.getServiceId()).thenReturn("UnitTestService");
253255
assertThat(strat.getRequestClassName("CAPSTest")).isEqualTo("CapsTestRequest");
254256
assertThat(strat.getExceptionName("CAPSTest")).isEqualTo("CapsTestException");
255257
assertThat(strat.getResponseClassName("CAPSTest")).isEqualTo("CapsTestResponse");
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"version": "2.0",
3+
"metadata": {
4+
"apiVersion": "2010-05-08",
5+
"endpointPrefix": "collision-service",
6+
"globalEndpoint": "collision-service.amazonaws.com",
7+
"protocol": "rest-json",
8+
"serviceAbbreviation": "Collision Service",
9+
"serviceFullName": "A really bizarrely modelled service",
10+
"serviceId":"CollisionService",
11+
"signatureVersion": "v4",
12+
"uid": "collision-service-2010-05-08",
13+
"xmlNamespace": "https://collision-service.amazonaws.com/doc/2010-05-08/"
14+
},
15+
"operations": {
16+
"Collision": {
17+
"name": "Collision",
18+
"http": {
19+
"method": "POST",
20+
"requestUri": "/"
21+
},
22+
"input": {
23+
"shape": "Collision"
24+
},
25+
"errors": [
26+
{
27+
"shape": "CollisionFault"
28+
}
29+
],
30+
"documentation": "<p>A very strange operation></p>"
31+
}
32+
},
33+
"shapes": {
34+
"Collision": {
35+
"type": "structure",
36+
"required": [],
37+
"members": {}
38+
},
39+
"CollisionFault" : {
40+
"type": "structure",
41+
"members": {},
42+
"documentation": "<p>A fault</p>",
43+
"error": {
44+
"code": "Collision",
45+
"httpStatusCode": 400,
46+
"senderFault": true
47+
},
48+
"exception": true
49+
}
50+
},
51+
"documentation": "Why would anyone do this?"
52+
}

0 commit comments

Comments
 (0)