Skip to content

Commit 8dc4ce1

Browse files
v4 model override parent setter (#765)
* add model-override-setter-from-superclass option to enable override superclass setter method * move getting parent model to template to avoid circular call * regen test
1 parent f369b4f commit 8dc4ce1

File tree

29 files changed

+411
-46
lines changed

29 files changed

+411
-46
lines changed

extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public static JavaSettings getInstance()
7373
boolean clientLoggerDefault = false;
7474
boolean generateClientInterfacesDefault = false;
7575
boolean requiredParameterClientMethodsDefault = false;
76+
boolean modelOverrideSetterFromSuperclassDefault = false;
7677

7778
String fluentSetting = host.getStringValue("fluent");
7879
if (fluentSetting != null) {
@@ -83,6 +84,7 @@ public static JavaSettings getInstance()
8384
clientLoggerDefault = true;
8485
generateClientInterfacesDefault = true;
8586
requiredParameterClientMethodsDefault = true;
87+
modelOverrideSetterFromSuperclassDefault = true;
8688
}
8789

8890
setHeader(host.getStringValue("license-header"));
@@ -114,7 +116,8 @@ public static JavaSettings getInstance()
114116
host.getBooleanValue("required-fields-as-ctor-args", false),
115117
host.getBooleanValue("service-interface-as-public", false),
116118
host.getStringValue("artifact-id", ""),
117-
host.getStringValue("credential-types", "none"));
119+
host.getStringValue("credential-types", "none"),
120+
host.getBooleanValue("model-override-setter-from-superclass", modelOverrideSetterFromSuperclassDefault));
118121
}
119122
return _instance;
120123
}
@@ -164,7 +167,8 @@ private JavaSettings(boolean azure,
164167
boolean requiredFieldsAsConstructorArgs,
165168
boolean serviceInterfaceAsPublic,
166169
String artifactId,
167-
String credentialType)
170+
String credentialType,
171+
boolean overrideSetterFromSuperclass)
168172
{
169173
this.azure = azure;
170174
this.fluent = fluent == null ? Fluent.NONE : (fluent.isEmpty() || fluent.equalsIgnoreCase("true") ? Fluent.PREMIUM : Fluent.valueOf(fluent.toUpperCase(Locale.ROOT)));
@@ -193,6 +197,7 @@ private JavaSettings(boolean azure,
193197
this.requiredFieldsAsConstructorArgs = requiredFieldsAsConstructorArgs;
194198
this.serviceInterfaceAsPublic = serviceInterfaceAsPublic;
195199
this.artifactId = artifactId;
200+
this.overrideSetterFromParent = overrideSetterFromSuperclass;
196201

197202
if (credentialType != null) {
198203
String[] splits = credentialType.split(",");
@@ -458,6 +463,15 @@ public final boolean shouldClientLogger() {
458463
return clientLogger;
459464
}
460465

466+
boolean overrideSetterFromParent;
467+
468+
/**
469+
* @return whether to override superclass setter method in model.
470+
*/
471+
public boolean isOverrideSetterFromSuperclass() {
472+
return overrideSetterFromParent;
473+
}
474+
461475
public static final String DefaultCodeGenerationHeader = "Code generated by Microsoft (R) AutoRest Code Generator %s" + "\r\n" +
462476
"Changes may cause incorrect behavior and will be lost if the code is regenerated.";
463477

fluentgen/src/main/java/com/azure/autorest/fluent/mapper/FluentMapperFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.azure.autorest.mapper.DefaultMapperFactory;
1010
import com.azure.autorest.mapper.ExceptionMapper;
1111
import com.azure.autorest.mapper.MethodGroupMapper;
12+
import com.azure.autorest.mapper.ModelMapper;
1213
import com.azure.autorest.mapper.ObjectMapper;
1314
import com.azure.autorest.mapper.PrimitiveMapper;
1415
import com.azure.autorest.mapper.ProxyMethodMapper;
@@ -44,4 +45,9 @@ public ClientMethodMapper getClientMethodMapper() {
4445
public PrimitiveMapper getPrimitiveMapper() {
4546
return FluentPrimitiveMapper.getInstance();
4647
}
48+
49+
@Override
50+
public ModelMapper getModelMapper() {
51+
return FluentModelMapper.getInstance();
52+
}
4753
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
6+
package com.azure.autorest.fluent.mapper;
7+
8+
import com.azure.autorest.fluent.model.FluentType;
9+
import com.azure.autorest.mapper.ModelMapper;
10+
import com.azure.autorest.model.clientmodel.ClassType;
11+
12+
public class FluentModelMapper extends ModelMapper {
13+
14+
private static final FluentModelMapper INSTANCE = new FluentModelMapper();
15+
16+
public static FluentModelMapper getInstance() {
17+
return INSTANCE;
18+
}
19+
20+
@Override
21+
protected boolean isPredefinedModel(ClassType modelType) {
22+
return !FluentType.nonResourceType(modelType) || !FluentType.nonManagementError(modelType);
23+
}
24+
}

fluentgen/src/main/java/com/azure/autorest/fluent/mapper/FluentObjectMapper.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.azure.autorest.fluent.util.Utils;
1111
import com.azure.autorest.mapper.ObjectMapper;
1212
import com.azure.autorest.model.clientmodel.ClassType;
13-
import com.azure.core.util.FluxUtil;
1413

1514
import java.util.Collection;
1615
import java.util.HashSet;
@@ -34,12 +33,7 @@ protected boolean isInnerModel(ObjectSchema compositeType) {
3433
}
3534

3635
@Override
37-
protected boolean isImplementedModel(ClassType modelType) {
38-
return !FluentType.nonResourceType(modelType) || !FluentType.nonManagementError(modelType);
39-
}
40-
41-
@Override
42-
protected ClassType mapImplementedModel(ObjectSchema compositeType) {
36+
protected ClassType mapPredefinedModel(ObjectSchema compositeType) {
4337
ClassType result = null;
4438
if (compositeType.getLanguage().getJava().getName().equals(FluentType.Resource.getName())) {
4539
result = FluentType.Resource;

fluentgen/src/main/java/com/azure/autorest/fluent/model/clientmodel/fluentmodel/ResourceOperation.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ private Map<String, ClientModelProperty> getRequestBodyModelPropertiesMap() {
254254
return this.requestBodyModelPropertiesMap;
255255
}
256256

257+
protected boolean isIdProperty(ClientModelProperty property) {
258+
return property.getName().equals(ResourceTypeName.FIELD_ID);
259+
}
260+
257261
protected boolean isLocationProperty(ClientModelProperty property) {
258262
return FluentUtils.modelHasLocationProperty(resourceModel) && property.getName().equals(ResourceTypeName.FIELD_LOCATION);
259263
}

fluentgen/src/main/java/com/azure/autorest/fluent/model/clientmodel/fluentmodel/create/ResourceCreate.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,6 @@ private FluentMethod getCreateMethod(boolean hasContextParameter) {
300300
}
301301
}
302302

303-
private boolean isIdProperty(ClientModelProperty property) {
304-
return property.getName().equals(ResourceTypeName.FIELD_ID);
305-
}
306-
307303
public void addImportsTo(Set<String> imports, boolean includeImplementationImports) {
308304
getDefinitionStages().forEach(s -> s.addImportsTo(imports, includeImplementationImports));
309305
}

fluentgen/src/main/java/com/azure/autorest/fluent/model/clientmodel/fluentmodel/update/ResourceUpdate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public String getLocalVariablePrefix() {
101101
protected List<ClientModelProperty> getProperties() {
102102
return super.getProperties().stream()
103103
.filter(p -> !p.getIsReadOnlyForUpdate())
104-
.filter(p -> !isLocationProperty(p)) // update should not be able to change location
104+
.filter(p -> !isIdProperty(p) && !isLocationProperty(p)) // update should not be able to change id or location
105105
.collect(Collectors.toList());
106106
}
107107

fluentgen/src/main/java/com/azure/autorest/fluent/template/FluentModelTemplate.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,21 @@
55

66
package com.azure.autorest.fluent.template;
77

8+
import com.azure.autorest.extension.base.plugin.JavaSettings;
89
import com.azure.autorest.fluent.model.FluentType;
10+
import com.azure.autorest.fluent.model.arm.ResourceClientModel;
911
import com.azure.autorest.model.clientmodel.ClientModel;
1012
import com.azure.autorest.model.clientmodel.ClientModelProperty;
13+
import com.azure.autorest.model.clientmodel.ClientModelPropertyReference;
14+
import com.azure.autorest.model.clientmodel.ClientModels;
1115
import com.azure.autorest.template.ModelTemplate;
1216
import com.azure.autorest.util.ModelNamer;
1317

18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.Optional;
21+
import java.util.stream.Collectors;
22+
1423
public class FluentModelTemplate extends ModelTemplate {
1524

1625
private static final FluentModelTemplate INSTANCE = new FluentModelTemplate();
@@ -44,4 +53,30 @@ protected String getGetterName(ClientModel model, ClientModelProperty property)
4453
return super.getGetterName(model, property);
4554
}
4655
}
56+
57+
@Override
58+
protected List<ClientModelPropertyReference> getClientModelPropertyReferences(ClientModel model) {
59+
List<ClientModelPropertyReference> propertyReferences = new ArrayList<>();
60+
if (JavaSettings.getInstance().isOverrideSetterFromSuperclass()) {
61+
String parentModelName = model.getParentModelName();
62+
while (parentModelName != null) {
63+
ClientModel parentModel = ClientModels.Instance.getModel(parentModelName);
64+
if (parentModel == null) {
65+
parentModel = getPredefinedModel(parentModelName).orElse(null);
66+
}
67+
if (parentModel != null) {
68+
if (parentModel.getProperties() != null) {
69+
propertyReferences.addAll(parentModel.getProperties().stream().map(ClientModelPropertyReference::new).collect(Collectors.toList()));
70+
}
71+
}
72+
73+
parentModelName = parentModel == null ? null : parentModel.getParentModelName();
74+
}
75+
}
76+
return propertyReferences;
77+
}
78+
79+
private Optional<ClientModel> getPredefinedModel(String modelName) {
80+
return ResourceClientModel.getResourceClientModel(modelName);
81+
}
4782
}

generate

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure
88
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-array.json --namespace=fixtures.bodyarray
99
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-boolean.json --namespace=fixtures.bodyboolean --context-client-method-parameter
1010
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-boolean.quirks.json --namespace=fixtures.bodyboolean.quirks
11-
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-complex.json --namespace=fixtures.bodycomplex --required-fields-as-ctor-args=true
11+
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-complex.json --namespace=fixtures.bodycomplex --required-fields-as-ctor-args --model-override-setter-from-superclass
1212
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-file.json --namespace=fixtures.bodyfile --context-client-method-parameter
1313
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-string.json --namespace=fixtures.bodystring --generate-client-interfaces
1414
autorest $VANILLA_ARGUMENTS --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/custom-baseUrl.json --namespace=fixtures.custombaseuri

generate.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com
55
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-array.json --namespace=fixtures.bodyarray
66
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-boolean.json --namespace=fixtures.bodyboolean --context-client-method-parameter
77
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-boolean.quirks.json --namespace=fixtures.bodyboolean.quirks
8-
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-complex.json --namespace=fixtures.bodycomplex --required-fields-as-ctor-args=true
8+
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-complex.json --namespace=fixtures.bodycomplex --required-fields-as-ctor-args --model-override-setter-from-superclass
99
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-file.json --namespace=fixtures.bodyfile --context-client-method-parameter
1010
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/body-string.json --namespace=fixtures.bodystring --generate-client-interfaces
1111
call autorest %VANILLA_ARGUMENTS% --input-file=https://raw.githubusercontent.com/Azure/autorest.testserver/master/swagger/custom-baseUrl.json --namespace=fixtures.custombaseuri

javagen/src/main/java/com/azure/autorest/mapper/ModelMapper.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
14
package com.azure.autorest.mapper;
25

36
import com.azure.autorest.extension.base.model.codemodel.ArraySchema;
@@ -29,7 +32,7 @@ public class ModelMapper implements IMapper<ObjectSchema, ClientModel> {
2932
private static ModelMapper instance = new ModelMapper();
3033
private ClientModels serviceModels = ClientModels.Instance;
3134

32-
private ModelMapper() {
35+
protected ModelMapper() {
3336
}
3437

3538
public static ModelMapper getInstance() {
@@ -44,7 +47,7 @@ public ClientModel map(ObjectSchema compositeType) {
4447
ClassType modelType = objectMapper.map(compositeType);
4548
String modelName = modelType.getName();
4649
ClientModel result = serviceModels.getModel(modelType.getName());
47-
if (result == null && !ObjectMapper.isPlainObject(compositeType) && (!settings.isFluent() || !Mappers.getObjectMapper().isImplementedModel(modelType))) {
50+
if (result == null && !ObjectMapper.isPlainObject(compositeType) && (!settings.isFluent() || !isPredefinedModel(modelType))) {
4851
ClientModel.Builder builder = new ClientModel.Builder()
4952
.name(modelName)
5053
.packageName(modelType.getPackage());
@@ -57,11 +60,11 @@ public ClientModel map(ObjectSchema compositeType) {
5760
String parentModelName = null;
5861
boolean hasAdditionalProperties = false;
5962
List<ObjectSchema> parentsNeedFlatten = new ArrayList<>();
63+
ObjectSchema firstParentComplexSchema = null;
6064
if (compositeType.getParents() != null && compositeType.getParents().getImmediate() != null) {
6165
hasAdditionalProperties = compositeType.getParents().getImmediate().stream()
6266
.anyMatch(s -> s instanceof DictionarySchema);
6367

64-
ObjectSchema firstParentComplexSchema = null;
6568
for (Schema parent : compositeType.getParents().getImmediate()) {
6669
if (parent instanceof ObjectSchema) {
6770
if (firstParentComplexSchema == null) {
@@ -176,9 +179,8 @@ public ClientModel map(ObjectSchema compositeType) {
176179
if (compositeType.getChildren() != null && compositeType.getChildren().getImmediate() != null) {
177180
for (ComplexSchema childSchema : compositeType.getChildren().getImmediate()) {
178181
if (childSchema instanceof ObjectSchema) {
179-
ClientModel model = map((ObjectSchema) childSchema);
182+
ClientModel model = this.map((ObjectSchema) childSchema);
180183
derivedTypes.add(model);
181-
//serviceModels.addModel(model);
182184
} else {
183185
throw new RuntimeException("Wait what? How? Child is not an object but a " + childSchema.getClass() + "?");
184186
}
@@ -239,4 +241,14 @@ private static boolean hasFlattenedProperty(ObjectSchema compositeType, Collecti
239241
}
240242
return ret;
241243
}
244+
245+
/**
246+
* Extension for Fluent predefined type.
247+
*
248+
* @param compositeType object type
249+
* @return Whether the type is predefined.
250+
*/
251+
protected boolean isPredefinedModel(ClassType compositeType) {
252+
return false;
253+
}
242254
}

javagen/src/main/java/com/azure/autorest/mapper/ObjectMapper.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
14
package com.azure.autorest.mapper;
25

36
import com.azure.autorest.extension.base.model.codemodel.ObjectSchema;
@@ -31,7 +34,7 @@ public ClassType map(ObjectSchema compositeType) {
3134

3235
ClassType result = null;
3336
if (settings.isFluent()) {
34-
result = mapImplementedModel(compositeType);
37+
result = mapPredefinedModel(compositeType);
3538
}
3639
if (result == null) {
3740
if (isPlainObject(compositeType)) {
@@ -70,22 +73,12 @@ public static boolean isPlainObject(ObjectSchema compositeType) {
7073
}
7174

7275
/**
73-
* Extension for Fluent implemented type.
74-
*
75-
* @param compositeType object type
76-
* @return Whether the type is already implemented.
77-
*/
78-
protected boolean isImplementedModel(ClassType compositeType) {
79-
return false;
80-
}
81-
82-
/**
83-
* Extension for Fluent implemented type.
76+
* Extension for Fluent predefined type.
8477
*
8578
* @param compositeType object type
86-
* @return The implemented type.
79+
* @return The predefined type.
8780
*/
88-
protected ClassType mapImplementedModel(ObjectSchema compositeType) {
81+
protected ClassType mapPredefinedModel(ObjectSchema compositeType) {
8982
return null;
9083
}
9184

0 commit comments

Comments
 (0)