diff --git a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/models/OperationDetails.java b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/models/OperationDetails.java index ea9285a555..d9423dac2f 100644 --- a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/models/OperationDetails.java +++ b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/models/OperationDetails.java @@ -22,7 +22,7 @@ public class OperationDetails implements JsonSerializable { /* * Type of operation. */ - private String kind; + private String kind = "OperationDetails"; /* * Operation ID @@ -73,7 +73,6 @@ public class OperationDetails implements JsonSerializable { * Creates an instance of OperationDetails class. */ public OperationDetails() { - this.kind = "OperationDetails"; } /** diff --git a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/DotFish.java b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/DotFish.java index 1f9e0aa36b..74987437b1 100644 --- a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/DotFish.java +++ b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/DotFish.java @@ -19,7 +19,7 @@ public class DotFish implements JsonSerializable { /* * The fish.type property. */ - private String fishType; + private String fishType = "DotFish"; /* * The species property. @@ -30,7 +30,6 @@ public class DotFish implements JsonSerializable { * Creates an instance of DotFish class. */ public DotFish() { - this.fishType = "DotFish"; } /** diff --git a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/Fish.java b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/Fish.java index d8fb6e558c..22ac112064 100644 --- a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/Fish.java +++ b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/Fish.java @@ -20,7 +20,7 @@ public class Fish implements JsonSerializable { /* * The fishtype property. */ - private String fishtype; + private String fishtype = "Fish"; /* * The species property. @@ -41,7 +41,6 @@ public class Fish implements JsonSerializable { * Creates an instance of Fish class. */ public Fish() { - this.fishtype = "Fish"; } /** diff --git a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/MyBaseType.java b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/MyBaseType.java index c7b50d36ea..3c45135e04 100644 --- a/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/MyBaseType.java +++ b/customization-tests/src/main/java/fixtures/bodycomplex/implementation/models/MyBaseType.java @@ -19,7 +19,7 @@ public class MyBaseType implements JsonSerializable { /* * The kind property. */ - private MyKind kind; + private MyKind kind = MyKind.fromString("MyBaseType"); /* * The propB1 property. @@ -35,7 +35,6 @@ public class MyBaseType implements JsonSerializable { * Creates an instance of MyBaseType class. */ public MyBaseType() { - this.kind = MyKind.fromString("MyBaseType"); } /** diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ModelMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ModelMapper.java index f5b295bf58..6d8e7bfa42 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ModelMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ModelMapper.java @@ -73,18 +73,16 @@ public ClientModel map(ObjectSchema compositeType) { } } - ClientModel.Builder builder = createModelBuilder() - .name(modelName) + ClientModel.Builder builder = createModelBuilder().name(modelName) .packageName(modelType.getPackage()) .type(modelType) .stronglyTypedHeader(compositeType.isStronglyTypedHeader()) .usedInXml(SchemaUtil.treatAsXml(compositeType)) .serializationFormats(compositeType.getSerializationFormats()) - .implementationDetails(new ImplementationDetails.Builder() - .usages(usages) - .build()); + .implementationDetails(new ImplementationDetails.Builder().usages(usages).build()); - boolean isPolymorphic = compositeType.getDiscriminator() != null || compositeType.getDiscriminatorValue() != null; + boolean isPolymorphic = compositeType.getDiscriminator() != null + || compositeType.getDiscriminatorValue() != null; builder.polymorphic(isPolymorphic); HashSet modelImports = new HashSet<>(); @@ -93,7 +91,9 @@ public ClientModel map(ObjectSchema compositeType) { boolean hasAdditionalProperties = false; List parentsNeedFlatten = Collections.emptyList(); if (compositeType.getParents() != null && compositeType.getParents().getImmediate() != null) { - hasAdditionalProperties = compositeType.getParents().getImmediate().stream() + hasAdditionalProperties = compositeType.getParents() + .getImmediate() + .stream() .anyMatch(s -> s instanceof DictionarySchema); ParentSchemaInfo parentSchemaInfo = getParentSchemaInfo(compositeType); @@ -108,15 +108,20 @@ public ClientModel map(ObjectSchema compositeType) { builder.parentModelName(parentModelName); List compositeTypeProperties = compositeType.getProperties() - .stream().filter(p -> !p.isIsDiscriminator()).collect(Collectors.toList()); + .stream() + .filter(p -> !p.isIsDiscriminator()) + .collect(Collectors.toList()); if (!parentsNeedFlatten.isEmpty()) { // Take properties from base class of multiple inheritance as properties of this class. for (ObjectSchema parent : parentsNeedFlatten) { - compositeTypeProperties.addAll(parent.getProperties().stream() + compositeTypeProperties.addAll(parent.getProperties() + .stream() .filter(p -> !p.isIsDiscriminator()) .collect(Collectors.toList())); if (parent.getParents() != null) { - compositeTypeProperties.addAll(parent.getParents().getAll().stream() + compositeTypeProperties.addAll(parent.getParents() + .getAll() + .stream() .filter(s -> s instanceof ObjectSchema) .flatMap(s -> ((ObjectSchema) s).getProperties().stream()) .filter(p -> !p.isIsDiscriminator()) @@ -145,7 +150,8 @@ public ClientModel map(ObjectSchema compositeType) { } if (compositeTypeProperties.stream().anyMatch(p -> { - if (p.getSchema().getSerialization() == null || p.getSchema().getSerialization().getXml() == null) { + if (p.getSchema().getSerialization() == null + || p.getSchema().getSerialization().getXml() == null) { return false; } @@ -156,7 +162,8 @@ public ClientModel map(ObjectSchema compositeType) { } if (compositeTypeProperties.stream().anyMatch(p -> { - if (p.getSchema().getSerialization() == null || p.getSchema().getSerialization().getXml() == null) { + if (p.getSchema().getSerialization() == null + || p.getSchema().getSerialization().getXml() == null) { return false; } @@ -165,14 +172,21 @@ public ClientModel map(ObjectSchema compositeType) { modelImports.add("com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText"); } - if (compositeTypeProperties.stream().anyMatch(p -> p.getSchema().getSerialization() == null - || p.getSchema().getSerialization().getXml() == null || !p.getSchema().getSerialization() - .getXml().isAttribute())) { + if (compositeTypeProperties.stream() + .anyMatch(p -> p.getSchema().getSerialization() == null + || p.getSchema().getSerialization().getXml() == null || !p.getSchema() + .getSerialization() + .getXml() + .isAttribute())) { modelImports.add(JsonProperty.class.getName()); } - if (compositeTypeProperties.stream().anyMatch(p -> p.getSchema().getSerialization() != null - && p.getSchema().getSerialization().getXml() != null && p.getSchema().getSerialization().getXml().isWrapped())) { + if (compositeTypeProperties.stream() + .anyMatch(p -> p.getSchema().getSerialization() != null + && p.getSchema().getSerialization().getXml() != null && p.getSchema() + .getSerialization() + .getXml() + .isWrapped())) { modelImports.add(JsonCreator.class.getName()); } @@ -189,7 +203,9 @@ public ClientModel map(ObjectSchema compositeType) { } String summary = compositeType.getSummary(); - String description = compositeType.getLanguage().getJava() == null ? null : compositeType.getLanguage().getJava().getDescription(); + String description = compositeType.getLanguage().getJava() == null + ? null + : compositeType.getLanguage().getJava().getDescription(); if (CoreUtils.isNullOrEmpty(summary) && CoreUtils.isNullOrEmpty(description)) { builder.description(String.format("The %s model.", compositeType.getLanguage().getJava().getName())); } else { @@ -203,14 +219,16 @@ public ClientModel map(ObjectSchema compositeType) { builder.serializedName(modelSerializedName); List derivedTypes = new ArrayList<>(); - boolean hasChildren = compositeType.getChildren() != null && compositeType.getChildren().getImmediate() != null; + boolean hasChildren = compositeType.getChildren() != null + && compositeType.getChildren().getImmediate() != null; if (hasChildren) { for (Schema childSchema : compositeType.getChildren().getImmediate()) { if (childSchema instanceof ObjectSchema) { ClientModel model = this.map((ObjectSchema) childSchema); derivedTypes.add(model); } else { - throw new RuntimeException("Wait what? How? Child is not an object but a " + childSchema.getClass() + "?"); + throw new RuntimeException( + "Wait what? How? Child is not an object but a " + childSchema.getClass() + "?"); } } } @@ -222,9 +240,9 @@ public ClientModel map(ObjectSchema compositeType) { && compositeType.getSerialization().getXml() != null; if (hasXmlFormat) { final XmlSerializationFormat xml = compositeType.getSerialization().getXml(); - String xmlName = CoreUtils.isNullOrEmpty(xml.getName()) - ? compositeType.getLanguage().getDefault().getName() - : xml.getName(); + String xmlName = CoreUtils.isNullOrEmpty(xml.getName()) ? compositeType.getLanguage() + .getDefault() + .getName() : xml.getName(); builder.xmlName(xmlName); builder.xmlNamespace(xml.getNamespace()); } else { @@ -249,10 +267,9 @@ public ClientModel map(ObjectSchema compositeType) { : discriminatorSerializedName; final String finalPolymorphicDiscriminator = polymorphicDiscriminator; - ClientModelProperty discriminatorProperty = createDiscriminatorProperty( - settings, hasChildren, compositeType, - annotationArgs -> annotationArgs.replace(discriminatorSerializedName, finalPolymorphicDiscriminator), - polymorphicDiscriminator); + ClientModelProperty discriminatorProperty = createDiscriminatorProperty(settings, hasChildren, + compositeType, annotationArgs -> annotationArgs.replace(discriminatorSerializedName, + finalPolymorphicDiscriminator), polymorphicDiscriminator); if (discriminatorProperty != null) { properties.add(discriminatorProperty); @@ -269,10 +286,12 @@ public ClientModel map(ObjectSchema compositeType) { builder.needsFlatten(needsFlatten); builder.imports(new ArrayList<>(modelImports)); - final boolean mutablePropertyAsOptional = usages.contains(ImplementationDetails.Usage.JSON_MERGE_PATCH) && settings.isStreamStyleSerialization(); + final boolean mutablePropertyAsOptional = usages.contains(ImplementationDetails.Usage.JSON_MERGE_PATCH) + && settings.isStreamStyleSerialization(); List propertyReferences = new ArrayList<>(); for (Property property : compositeTypeProperties) { - ClientModelProperty modelProperty = Mappers.getModelPropertyMapper().map(property, mutablePropertyAsOptional); + ClientModelProperty modelProperty = Mappers.getModelPropertyMapper() + .map(property, mutablePropertyAsOptional); if (Objects.equals(polymorphicDiscriminator, modelProperty.getSerializedName())) { // Discriminator is defined both as the discriminator and a property in the model. // Make the discriminator property required if the property is required. But don't add the property @@ -287,7 +306,8 @@ public ClientModel map(ObjectSchema compositeType) { // be null or an infinite loop would happen. if (!CoreUtils.isNullOrEmpty(derivedTypes)) { for (ClientModel derivedType : derivedTypes) { - if (Objects.equals(derivedType.getPolymorphicDiscriminator().getSerializedName(), polymorphicDiscriminator)) { + if (Objects.equals(derivedType.getPolymorphicDiscriminator().getSerializedName(), + polymorphicDiscriminator)) { derivedType.getPolymorphicDiscriminator().setRequired(modelProperty.isRequired()); } } @@ -298,13 +318,18 @@ public ClientModel map(ObjectSchema compositeType) { properties.add(modelProperty); - if (modelProperty.getClientFlatten() && settings.getClientFlattenAnnotationTarget() == JavaSettings.ClientFlattenAnnotationTarget.NONE) { - propertyReferences.addAll(collectPropertiesFromFlattenedModel(compositeType, property, modelProperty, propertyReferences)); + if (modelProperty.getClientFlatten() + && settings.getClientFlattenAnnotationTarget() == JavaSettings.ClientFlattenAnnotationTarget.NONE) { + propertyReferences.addAll( + collectPropertiesFromFlattenedModel(compositeType, property, modelProperty, + propertyReferences)); } } if (hasAdditionalProperties) { - DictionarySchema schema = (DictionarySchema) compositeType.getParents().getImmediate().stream() + DictionarySchema schema = (DictionarySchema) compositeType.getParents() + .getImmediate() + .stream() .filter(s -> s instanceof DictionarySchema) .findFirst() .orElseThrow(() -> new IllegalStateException( @@ -331,12 +356,45 @@ public ClientModel map(ObjectSchema compositeType) { builder.crossLanguageDefinitionId(compositeType.getCrossLanguageDefinitionId()); result = builder.build(); + + if (isPolymorphic && !CoreUtils.isNullOrEmpty(derivedTypes)) { + // Walk the polymorphic hierarchy finding places where the parent model and child model have different + // polymorphic discriminators. When this case is found add the parent polymorphic discriminator as a parent + // polymorphic discriminator to the child model. This is necessary to ensure that the child model generates + // the correct serialization in multi-level polymorphic structures. + for (ClientModel derivedType : derivedTypes) { + if (!Objects.equals(polymorphicDiscriminator, derivedType.getPolymorphicDiscriminatorName())) { + ClientModelProperty parentDiscriminator = result.getPolymorphicDiscriminator() + .newBuilder() + .defaultValue(derivedType.getPolymorphicDiscriminator().getDefaultValue()) + .build(); + + passPolymorphicDiscriminatorToChildren(parentDiscriminator, derivedType); + } + } + } + serviceModels.addModel(result); } return result; } + private static void passPolymorphicDiscriminatorToChildren(ClientModelProperty parentDiscriminator, + ClientModel child) { + // Due to the execution order of ModelMapper, where children models complete mapping before the parent model, + // the parent polymorphic discriminator needs to be added at index 0. Reason, given an example where there are + // three models, where model #1 is the root parent with discriminator type, model #2 is a child of model #2 with + // discriminator kind, and model #3 is a child of model #3 with discriminator form. The order if this running + // will have model #2 add its discriminator to model #3 before model #1 runs adding its discriminator to #2 and + // #3. We want #3 to have the ordering of [type, kind], to represent the ordering of the parent models. + child.getParentPolymorphicDiscriminators().add(0, parentDiscriminator); + + for (ClientModel derived : child.getDerivedModels()) { + passPolymorphicDiscriminatorToChildren(parentDiscriminator, derived); + } + } + private static class ParentSchemaInfo { private final ObjectSchema parentSchema; private final List flattenedParentSchemas; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java index da88ba1c15..958f349b24 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java @@ -47,6 +47,10 @@ public class ClientModel { */ private final boolean isPolymorphicParent; + /** + * Get the properties used by parent models as polymorphic discriminators. + */ + private final List parentPolymorphicDiscriminators; /** * Get the property that determines which polymorphic model type to create. */ @@ -148,6 +152,7 @@ public class ClientModel { * @param implementationDetails The implementation details for the model. * @param usedInXml Whether the model is used in XML serialization. * @param crossLanguageDefinitionId The cross language definition id for the model. + * */ protected ClientModel(String packageKeyword, String name, List imports, String description, boolean isPolymorphic, ClientModelProperty polymorphicDiscriminator, String polymorphicDiscriminatorName, @@ -163,6 +168,7 @@ protected ClientModel(String packageKeyword, String name, List imports, this.description = description; this.isPolymorphic = isPolymorphic; this.isPolymorphicParent = isPolymorphic && !CoreUtils.isNullOrEmpty(derivedModels); + this.parentPolymorphicDiscriminators = new ArrayList<>(); this.polymorphicDiscriminator = polymorphicDiscriminator; this.polymorphicDiscriminatorName = polymorphicDiscriminatorName; this.serializedName = serializedName; @@ -253,6 +259,28 @@ public final boolean isPolymorphicParent() { return isPolymorphicParent; } + /** + * Gets the properties used by parent models as polymorphic discriminators. + *

+ * The only time this will return a non-empty list is when this model is used in a multi-level polymorphic + * hierarchy. Or, as an example, if the root model uses a polymorphic discriminator of {@code kind} and this model + * uses a polymorphic discriminator of {@code type} this will have a single property where the serialized name is + * {@code kind} and the default value for it will be what to root model uses to determine that this is the model + * that should be deserialized. Continuing this example, the third level models, or those that are determined by the + * {@code type} value, will also have a single property where the serialized name is {@code kind} and the default + * value will be what the second level model uses to determine that this is the model that should be deserialized. + * This is because the {@code kind} property will always need to be present for these models. If there are even + * deeper levels of polymorphism, the same pattern will continue. So, if in the third level there is a model that + * introduces another polymorphic discriminator of {@code format} that model would have two properties in this list, + * one with {@code kind} with a default that determined the second level model and one with {@code type} with a + * default that determined the third level model. The fourth level model would then have both as well. + * + * @return The properties used by parent models as polymorphic discriminators. + */ + public final List getParentPolymorphicDiscriminators() { + return parentPolymorphicDiscriminators; + } + /** * Gets the property that determines which polymorphic model type to create. * diff --git a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java index 99a32c77dd..a17271e7b8 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java @@ -68,26 +68,27 @@ public void write(ConvenienceMethod convenienceMethodObj, JavaClass classBlock, ClientMethod protocolMethod = convenienceMethodObj.getProtocolMethod(); convenienceMethodObj.getConvenienceMethods().stream() - .filter(this::isMethodIncluded) - .forEach(convenienceMethod -> { - // javadoc - classBlock.javadocComment(comment -> { - ClientMethodTemplate.generateJavadoc(convenienceMethod, comment, convenienceMethod.getProxyMethod(), false); - }); + .filter(this::isMethodIncluded) + .forEach(convenienceMethod -> { + // javadoc + classBlock.javadocComment(comment -> ClientMethodTemplate.generateJavadoc(convenienceMethod, comment, + convenienceMethod.getProxyMethod(), false)); - addGeneratedAnnotation(classBlock); - TemplateUtil.writeClientMethodServiceMethodAnnotation(convenienceMethod, classBlock); + addGeneratedAnnotation(classBlock); + TemplateUtil.writeClientMethodServiceMethodAnnotation(convenienceMethod, classBlock); - JavaVisibility methodVisibility = convenienceMethod.getMethodVisibilityInWrapperClient(); + JavaVisibility methodVisibility = convenienceMethod.getMethodVisibilityInWrapperClient(); - // convenience method - String methodDeclaration = String.format("%1$s %2$s(%3$s)", convenienceMethod.getReturnValue().getType(), getMethodName(convenienceMethod), convenienceMethod.getParametersDeclaration()); - classBlock.method(methodVisibility, null, methodDeclaration, methodBlock -> { - methodBlock.line("// Generated convenience method for " + getMethodName(protocolMethod)); + // convenience method + String methodDeclaration = String.format("%1$s %2$s(%3$s)", + convenienceMethod.getReturnValue().getType(), getMethodName(convenienceMethod), + convenienceMethod.getParametersDeclaration()); + classBlock.method(methodVisibility, null, methodDeclaration, methodBlock -> { + methodBlock.line("// Generated convenience method for " + getMethodName(protocolMethod)); - writeMethodImplementation(protocolMethod, convenienceMethod, methodBlock, typeReferenceStaticClasses); - }); + writeMethodImplementation(protocolMethod, convenienceMethod, methodBlock, typeReferenceStaticClasses); }); + }); } /** @@ -112,12 +113,14 @@ protected void writeMethodImplementation( // parameter transformation if (!CoreUtils.isNullOrEmpty(convenienceMethod.getMethodTransformationDetails())) { - convenienceMethod.getMethodTransformationDetails().forEach(d -> writeParameterTransformation(d, convenienceMethod, protocolMethod, methodBlock, parametersMap)); + convenienceMethod.getMethodTransformationDetails() + .forEach(d -> writeParameterTransformation(d, convenienceMethod, protocolMethod, methodBlock, parametersMap)); } writeValidationForVersioning(convenienceMethod, parametersMap.keySet(), methodBlock); - boolean isJsonMergePatchOperation = protocolMethod != null && protocolMethod.getProxyMethod() != null && "application/merge-patch+json".equalsIgnoreCase(protocolMethod.getProxyMethod().getRequestContentType()); + boolean isJsonMergePatchOperation = protocolMethod != null && protocolMethod.getProxyMethod() != null + && "application/merge-patch+json".equalsIgnoreCase(protocolMethod.getProxyMethod().getRequestContentType()); Map parameterExpressionsMap = new HashMap<>(); for (Map.Entry entry : parametersMap.entrySet()) { MethodParameter parameter = entry.getKey(); @@ -141,41 +144,47 @@ protected void writeMethodImplementation( writeQueryParam(parameter, methodBlock); break; - case BODY: { + case BODY: Consumer writeLine = javaBlock -> { IType parameterType = parameter.getClientMethodParameter().getClientType(); - String expression = expressionConvertToBinaryData(parameter.getName(), parameter.getClientMethodParameter().getWireType(), protocolMethod.getProxyMethod().getRequestContentType()); - if (isJsonMergePatchOperation && ClientModelUtil.isClientModel(parameterType) && ClientModelUtil.isJsonMergePatchModel(ClientModelUtil.getClientModel(((ClassType) parameterType).getName()))) { + String expression = expressionConvertToBinaryData(parameter.getName(), + parameter.getClientMethodParameter().getWireType(), + protocolMethod.getProxyMethod().getRequestContentType()); + + if (isJsonMergePatchOperation + && ClientModelUtil.isClientModel(parameterType) + && ClientModelUtil.isJsonMergePatchModel(ClientModelUtil.getClientModel(((ClassType) parameterType).getName()), JavaSettings.getInstance())) { String variableName = writeParameterConversionExpressionWithJsonMergePatchEnabled(javaBlock, parameterType.toString(), parameter.getName(), expression); - javaBlock.line(String.format("requestOptions.setBody(%s);", variableName)); + javaBlock.line("requestOptions.setBody(" + variableName + ");"); } else { - javaBlock.line(String.format("requestOptions.setBody(%s);", expression)); + javaBlock.line("requestOptions.setBody(" + expression + ");"); } }; if (!parameter.getClientMethodParameter().isRequired()) { - methodBlock.ifBlock(String.format("%s != null", parameter.getName()), writeLine); + methodBlock.ifBlock(parameter.getName() + " != null", writeLine); } else { writeLine.accept(methodBlock); } - } - break; + break; } } } // invocation with protocol method parameters and RequestOptions String invocationExpression = protocolMethod.getMethodInputParameters().stream() - .map(p -> { - String parameterName = p.getName(); - String expression = parameterExpressionsMap.get(parameterName); - IType parameterRawType = p.getRawType(); - if (isJsonMergePatchOperation && ClientModelUtil.isClientModel(parameterRawType) && RequestParameterLocation.BODY.equals(p.getRequestParameterLocation()) && ClientModelUtil.isJsonMergePatchModel(ClientModelUtil.getClientModel(((ClassType) parameterRawType).getName()))) { - return writeParameterConversionExpressionWithJsonMergePatchEnabled(methodBlock, parameterRawType.toString(), parameterName, expression); - } else { - return expression == null ? parameterName : expression; - } - }) - .collect(Collectors.joining(", ")); + .map(p -> { + String parameterName = p.getName(); + String expression = parameterExpressionsMap.get(parameterName); + IType parameterRawType = p.getRawType(); + if (isJsonMergePatchOperation && ClientModelUtil.isClientModel(parameterRawType) + && RequestParameterLocation.BODY.equals(p.getRequestParameterLocation()) + && ClientModelUtil.isJsonMergePatchModel(ClientModelUtil.getClientModel(((ClassType) parameterRawType).getName()), JavaSettings.getInstance())) { + return writeParameterConversionExpressionWithJsonMergePatchEnabled(methodBlock, parameterRawType.toString(), parameterName, expression); + } else { + return expression == null ? parameterName : expression; + } + }) + .collect(Collectors.joining(", ")); // write the invocation of protocol method, and related type conversion writeInvocationAndConversion(convenienceMethod, protocolMethod, invocationExpression, methodBlock, typeReferenceStaticClasses); @@ -193,8 +202,8 @@ protected void writeValidationForVersioning(ClientMethod convenienceMethod, Set< for (MethodParameter parameter : parameters) { if (parameter.getClientMethodParameter().getVersioning() != null && parameter.getClientMethodParameter().getVersioning().getAdded() != null) { String condition = String.format( - "!Arrays.asList(%1$s).contains(serviceClient.getServiceVersion().getVersion())", - parameter.getClientMethodParameter().getVersioning().getAdded().stream().map(ClassType.STRING::defaultValueExpression).collect(Collectors.joining(", "))); + "!Arrays.asList(%s).contains(serviceClient.getServiceVersion().getVersion())", + parameter.getClientMethodParameter().getVersioning().getAdded().stream().map(ClassType.STRING::defaultValueExpression).collect(Collectors.joining(", "))); methodBlock.ifBlock(condition, ifBlock -> { String exceptionExpression = String.format( "new IllegalArgumentException(\"Parameter %1$s is only available in api-version %2$s.\")", diff --git a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java index 1cb0f6d1fe..06b1350b8a 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -148,7 +148,7 @@ public final void write(ClientModel model, JavaFile javaFile) { addProperties(model, classBlock, settings); // add jsonMergePatch related properties and accessors - if (ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization()) { + if (ClientModelUtil.isJsonMergePatchModel(model, settings)) { addJsonMergePatchRelatedPropertyAndAccessors(classBlock, model); } @@ -178,7 +178,8 @@ public final void write(ClientModel model, JavaFile javaFile) { } // getter method of discriminator property in subclass is handled differently - final boolean polymorphicDiscriminatorInSubclass = property.isPolymorphicDiscriminator() && !modelDefinesProperty(model, property); + boolean polymorphicDiscriminatorInSubclass = property.isPolymorphicDiscriminator() + && !modelDefinesProperty(model, property); if (polymorphicDiscriminatorInSubclass) { classBlock.annotation("Override"); } @@ -198,7 +199,7 @@ public final void write(ClientModel model, JavaFile javaFile) { classBlock.method(methodVisibility, null, model.getName() + " " + property.getSetterName() + "(" + propertyClientType + " " + property.getName() + ")", methodBlock -> addSetterMethod(propertyWireType, propertyClientType, property, treatAsXml, - methodBlock, settings, ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization())); + methodBlock, settings, ClientModelUtil.isJsonMergePatchModel(model, settings))); } else { // If stream-style serialization is being generated or the property is the polymorphic // discriminator, some additional setters may need to be added to support read-only properties that @@ -224,7 +225,7 @@ public final void write(ClientModel model, JavaFile javaFile) { + property.getName() + ")", methodBlock -> addSetterMethod(propertyWireType, propertyWireType, property, treatAsXml, methodBlock, settings, - ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization())); + ClientModelUtil.isJsonMergePatchModel(model, settings))); } } @@ -256,14 +257,13 @@ public final void write(ClientModel model, JavaFile javaFile) { classBlock.javadocComment(JavaJavadocComment::inheritDoc); addGeneratedAnnotation(classBlock); classBlock.annotation("Override"); - String methodSignature = model.getName() + " " + parentProperty.getSetterName() + "(" + parentProperty.getClientType() + " " + parentProperty.getName() + ")"; classBlock.publicMethod(methodSignature, methodBlock -> { methodBlock.line( "super." + parentProperty.getSetterName() + "(" + parentProperty.getName() + ");"); - if (ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization()) { + if (ClientModelUtil.isJsonMergePatchModel(model, settings)) { methodBlock.line("this.updatedProperties.add(\"" + parentProperty.getName() + "\");"); } methodBlock.methodReturn("this"); @@ -377,7 +377,7 @@ private void addImports(Set imports, ClientModel model, JavaSettings set model.addImportsTo(imports, settings); // add Json merge patch related imports - if (ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization()) { + if (ClientModelUtil.isJsonMergePatchModel(model, settings)) { imports.add(settings.getPackage(settings.getImplementationSubpackage()) + "." + ClientModelUtil.JSON_MERGE_PATCH_HELPER_CLASS_NAME); imports.add(Set.class.getName()); imports.add(HashSet.class.getName()); @@ -539,71 +539,82 @@ protected void addXmlNamespaceConstants(ClientModel model, JavaClass classBlock) * @param settings AutoRest configuration settings. */ private void addProperties(ClientModel model, JavaClass classBlock, JavaSettings settings) { + for (ClientModelProperty parentDiscriminator : model.getParentPolymorphicDiscriminators()) { + addProperty(parentDiscriminator, model, classBlock, settings); + } + for (ClientModelProperty property : model.getProperties()) { -// if (property.isPolymorphicDiscriminator() && !modelDefinesProperty(model, property)) { -// // Only the super most parent model should have the polymorphic discriminator as a field. -// // The child models should use the parent's field. If the polymorphic property is required, it will be -// // initialized in the parent's constructor. Otherwise, it will be set using the package-private setter. -// continue; -// } + addProperty(property, model, classBlock, settings); + } + } + + private void addProperty(ClientModelProperty property, ClientModel model, JavaClass classBlock, + JavaSettings settings) { + String propertyName = property.getName(); + IType propertyType = property.getWireType(); - String propertyName = property.getName(); - IType propertyType = property.getWireType(); + String defaultValue; + if (property.isPolymorphicDiscriminator()) { + defaultValue = (property.getDefaultValue() == null) + ? property.getClientType().defaultValueExpression(model.getSerializedName()) + : property.getDefaultValue(); + } else { + defaultValue = property.getDefaultValue(); + } - String fieldSignature; - if (model.isUsedInXml()) { - if (property.isXmlWrapper()) { - if (!settings.isStreamStyleSerialization()) { - String xmlWrapperClassName = getPropertyXmlWrapperClassName(property); - classBlock.staticFinalClass(JavaVisibility.PackagePrivate, xmlWrapperClassName, - innerClass -> addXmlWrapperClass(innerClass, property, xmlWrapperClassName, settings)); + String fieldSignature; + if (model.isUsedInXml()) { + if (property.isXmlWrapper()) { + if (!settings.isStreamStyleSerialization()) { + String xmlWrapperClassName = getPropertyXmlWrapperClassName(property); + classBlock.staticFinalClass(JavaVisibility.PackagePrivate, xmlWrapperClassName, + innerClass -> addXmlWrapperClass(innerClass, property, xmlWrapperClassName, settings)); - fieldSignature = xmlWrapperClassName + " " + propertyName; - } else { - fieldSignature = propertyType + " " + propertyName; - } - } else if (propertyType instanceof ListType) { - fieldSignature = propertyType + " " + propertyName + " = new ArrayList<>()"; + fieldSignature = xmlWrapperClassName + " " + propertyName; } else { - // handle x-ms-client-default - // Only set the property to a default value if the property isn't included in the constructor. - // There can be cases with polymorphic discriminators where they have both a default value and are - // required, in which case the default value will be set in the constructor. - if (property.getDefaultValue() != null - && (!ClientModelUtil.includePropertyInConstructor(property, settings) || property.isConstant())) { - fieldSignature = propertyType + " " + propertyName + " = " + property.getDefaultValue(); - } else { - fieldSignature = propertyType + " " + propertyName; - } + fieldSignature = propertyType + " " + propertyName; } + } else if (propertyType instanceof ListType) { + fieldSignature = propertyType + " " + propertyName + " = new ArrayList<>()"; } else { - if (property.getClientFlatten() && property.isRequired() && property.getClientType() instanceof ClassType) { - // if the property of flattened model is required, initialize it - fieldSignature = propertyType + " " + propertyName + " = new " + propertyType + "()"; + // handle x-ms-client-default + // Only set the property to a default value if the property isn't included in the constructor. + // There can be cases with polymorphic discriminators where they have both a default value and are + // required, in which case the default value will be set in the constructor. + if (defaultValue != null + && (!ClientModelUtil.includePropertyInConstructor(property, settings) || property.isConstant())) { + fieldSignature = propertyType + " " + propertyName + " = " + defaultValue; } else { - // handle x-ms-client-default - // Only set the property to a default value if the property isn't included in the constructor. - // There can be cases with polymorphic discriminators where they have both a default value and are - // required, in which case the default value will be set in the constructor. - if (property.getDefaultValue() != null - && (!ClientModelUtil.includePropertyInConstructor(property, settings) || property.isConstant())) { - fieldSignature = propertyType + " " + propertyName + " = " + property.getDefaultValue(); - } else { - fieldSignature = propertyType + " " + propertyName; - } + fieldSignature = propertyType + " " + propertyName; + } + } + } else { + if (property.getClientFlatten() && property.isRequired() && property.getClientType() instanceof ClassType) { + // if the property of flattened model is required, initialize it + fieldSignature = propertyType + " " + propertyName + " = new " + propertyType + "()"; + } else { + // handle x-ms-client-default + // Only set the property to a default value if the property isn't included in the constructor. + // There can be cases with polymorphic discriminators where they have both a default value and are + // required, in which case the default value will be set in the constructor. + if (defaultValue != null + && (!ClientModelUtil.includePropertyInConstructor(property, settings) || property.isConstant())) { + fieldSignature = propertyType + " " + propertyName + " = " + defaultValue; + } else { + fieldSignature = propertyType + " " + propertyName; } } + } - classBlock.blockComment(comment -> comment.line(property.getDescription())); + classBlock.blockComment(comment -> comment.line(property.getDescription())); - addGeneratedAnnotation(classBlock); - addFieldAnnotations(model, property, classBlock, settings); + addGeneratedAnnotation(classBlock); + addFieldAnnotations(model, property, classBlock, settings); - if (ClientModelUtil.includePropertyInConstructor(property, settings)) { - classBlock.privateFinalMemberVariable(fieldSignature); - } else { - classBlock.privateMemberVariable(fieldSignature); - } + if (ClientModelUtil.includePropertyInConstructor(property, settings)) { + classBlock.privateFinalMemberVariable(fieldSignature); + } else { + classBlock.privateMemberVariable(fieldSignature); } } @@ -814,19 +825,13 @@ private void addModelConstructor(ClientModel model, JavaVisibility constructorVi // If there is a polymorphic discriminator , add a line to initialize the discriminator. ClientModelProperty polymorphicProperty = model.getPolymorphicDiscriminator(); if (polymorphicProperty != null && !polymorphicProperty.isRequired()) { - String discriminatorValue = polymorphicProperty.getDefaultValue() != null - ? polymorphicProperty.getDefaultValue() - : polymorphicProperty.getClientType().defaultValueExpression(model.getSerializedName()); + if (ClientModelUtil.isJsonMergePatchModel(model, settings)) { + for (ClientModelProperty property : model.getParentPolymorphicDiscriminators()) { + constructor.line("this.updatedProperties.add(\"" + property.getName() + "\");"); + } - if (modelDefinesProperty(model, polymorphicProperty)) { - constructor.line("this." + polymorphicProperty.getName() + " = " + discriminatorValue + ";"); - } - if (settings.isStreamStyleSerialization() && ClientModelUtil.isJsonMergePatchModel(model)) { constructor.line("this.updatedProperties.add(\"" + polymorphicProperty.getName() + "\");"); } -// else { -// constructor.line(polymorphicProperty.getSetterName() + "(" + discriminatorValue + ");"); -// } } // constant properties should already be initialized in class variable definition diff --git a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java index e835c561a6..8eb0e120dc 100644 --- a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java @@ -216,7 +216,7 @@ protected void writeStreamStyleSerialization(JavaClass classBlock, ClientModel m writeFromXml(classBlock, model, propertiesManager, settings, Templates.getModelTemplate()::addGeneratedAnnotation); } else { - if (ClientModelUtil.isJsonMergePatchModel(model)) { + if (ClientModelUtil.isJsonMergePatchModel(model, settings)) { writeToJson(classBlock, propertiesManager, true, Templates.getModelTemplate()::addGeneratedAnnotation); writeToJsonMergePatch(classBlock, propertiesManager, Templates.getModelTemplate()::addGeneratedAnnotation); @@ -288,6 +288,8 @@ private static void serializeJsonProperties(JavaBlock methodBlock, ClientModelPr BiConsumer serializeJsonProperty = (property, fromSuper) -> serializeJsonProperty( methodBlock, property, property.getSerializedName(), fromSuper, true, isJsonMergePatch); + propertiesManager.getModel().getParentPolymorphicDiscriminators() + .forEach(discriminator -> serializeJsonProperty.accept(discriminator, false)); propertiesManager.forEachSuperRequiredProperty(property -> serializeJsonProperty.accept(property, true)); propertiesManager.forEachSuperSetterProperty(property -> serializeJsonProperty.accept(property, true)); propertiesManager.forEachRequiredProperty(property -> serializeJsonProperty.accept(property, false)); @@ -687,12 +689,36 @@ private static void writeSuperTypeFromJson(JavaClass classBlock, ClientModel mod // Add deserialization for all child types. List childTypes = getAllChildTypes(model, new ArrayList<>()); for (ClientModel childType : childTypes) { + // Determine which serialization method to use based on whether the child type is also a polymorphic + // parent and the child shares the same polymorphic discriminator as this model. + // If the child and parent have different discriminator names then the child will need to be + // deserialized checking the multi-level polymorphic discriminator. + // Using the nested discriminator sample, there is + // Fish : kind + // - Salmon : kind + // - Shark : sharktype + // - Sawshark : sharktype + // So, if deserialization enters Fish and the "kind" is "Shark" then it needs to check the + // "sharktype" to determine if it's a Sawshark or another subtype of Shark. + boolean sameDiscimrinator = Objects.equals(childType.getPolymorphicDiscriminatorName(), + model.getPolymorphicDiscriminatorName()); + + if (!sameDiscimrinator && !Objects.equals(childType.getParentModelName(), model.getName())) { + // Child model and parent model don't share the same discriminator and the child isn't a direct + // child of the parent model, so skip this child model. This is done as the child model should + // be deserialized by the subtype that defines the different polymorphic discriminator. Using + // the sample above, Fish can't use "kind" to deserialize to a Shark subtype, it needs to use + // "sharktype". + continue; + } + + String deserializationMethod = (isSuperTypeWithDiscriminator(childType) && sameDiscimrinator) + ? ".fromJsonKnownDiscriminator(readerToUse.reset())" + : ".fromJson(readerToUse.reset())"; + ifBlock = ifOrElseIf(tryStatement, ifBlock, "\"" + childType.getSerializedName() + "\".equals(discriminatorValue)", - ifStatement -> ifStatement.methodReturn( - childType.getName() + (isSuperTypeWithDiscriminator(childType) - ? ".fromJsonKnownDiscriminator(readerToUse.reset())" - : ".fromJson(readerToUse.reset())"))); + ifStatement -> ifStatement.methodReturn(childType.getName() + deserializationMethod)); } if (ifBlock == null) { @@ -753,7 +779,7 @@ private static void writeTerminalTypeFromJson(JavaClass classBlock, ClientModelP private static void writeFromJsonDeserialization(JavaBlock methodBlock, ClientModelPropertiesManager propertiesManager, JavaSettings settings) { boolean polymorphicJsonMergePatchScenario = propertiesManager.getModel().isPolymorphic() - && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel()); + && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel(), settings); // Add the deserialization logic. methodBlock.indent(() -> { // Initialize local variables to track what has been deserialized. @@ -1284,7 +1310,7 @@ private static void handleReadReturn(JavaBlock methodBlock, String modelName, if (ifStatementBuilder.length() > 0) { methodBlock.ifBlock(ifStatementBuilder.toString(), ifAction -> - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager)); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, settings)); if (propertiesManager.getRequiredPropertiesCount() == 1) { StringBuilder stringBuilder = new StringBuilder(); @@ -1300,17 +1326,17 @@ private static void handleReadReturn(JavaBlock methodBlock, String modelName, methodBlock.line("throw new IllegalStateException(\"Missing required property/properties: \" + String.join(\", \", missingProperties));"); } } else { - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, settings); } } else { - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, settings); } } private static void createObjectAndReturn(JavaBlock methodBlock, String modelName, String constructorArgs, - ClientModelPropertiesManager propertiesManager) { + ClientModelPropertiesManager propertiesManager, JavaSettings settings) { boolean polymorphicJsonMergePatchScenario = propertiesManager.getModel().isPolymorphic() - && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel()); + && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel(), settings); if (propertiesManager.hasConstructorArguments()) { if (propertiesManager.getSetterPropertiesCount() == 0 && propertiesManager.getReadOnlyPropertiesCount() == 0 @@ -1423,6 +1449,11 @@ private static void handleSettingDeserializedValue(JavaBlock methodBlock, String } } + private static boolean isSuperTypeWithDiscriminator(ClientModel child) { + return !CoreUtils.isNullOrEmpty(child.getPolymorphicDiscriminatorName()) + && !CoreUtils.isNullOrEmpty(child.getDerivedModels()); + } + // TODO (alzimmer): This is a very inefficient design where we're using the ClientModelProperty to find which model // in the polymorphic hierarchy defines it, but this is a simple bootstrapping method rather than a larger // re-architecting. @@ -1437,11 +1468,6 @@ private static ClientModel definingModel(ClientModel model, ClientModelProperty throw new IllegalStateException("No ClientModel in the polymorphic hierarchy define this property, this should never happen."); } - private static boolean isSuperTypeWithDiscriminator(ClientModel model) { - return !CoreUtils.isNullOrEmpty(model.getPolymorphicDiscriminatorName()) - && !CoreUtils.isNullOrEmpty(model.getDerivedModels()); - } - /** * Helper method for adding a base if condition or an else if condition. * diff --git a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java index 698c0da133..bd2c7b9588 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java @@ -458,9 +458,11 @@ public static boolean isOutputOnly(ClientModel model) { /** * Check if the model is used in json-merge-patch operation */ - public static boolean isJsonMergePatchModel(ClientModel model) { - return model.getImplementationDetails() != null && model.getImplementationDetails().getUsages() != null - && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH); + public static boolean isJsonMergePatchModel(ClientModel model, JavaSettings settings) { + // JSON merge patch is only supported for stream style serialization. + return settings.isStreamStyleSerialization() + && model.getImplementationDetails() != null && model.getImplementationDetails().getUsages() != null + && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH); } /** diff --git a/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java b/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java index 3c54e1d2e3..bdcc741ec2 100644 --- a/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java +++ b/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java @@ -47,8 +47,7 @@ public class TypeSpecPlugin extends Javagen { public Client processClient(CodeModel codeModel) { // transform code model - codeModel = Preprocessor.convertOptionalConstantsToEnum(codeModel); - codeModel = new Transformer().transform(codeModel); + codeModel = new Transformer().transform(Preprocessor.convertOptionalConstantsToEnum(codeModel)); // map to client model Client client = Mappers.getClientMapper().map(codeModel); @@ -127,15 +126,15 @@ protected void writeClientModels(Client client, JavaPackage javaPackage, JavaSet // Union client.getUnionModels().stream() .filter(ModelUtil::isGeneratingModel) - .forEach(model -> javaPackage.addUnionModel(model)); + .forEach(javaPackage::addUnionModel); } @Override protected void writeHelperClasses(Client client, JavaPackage javaPackage, JavaSettings settings) { // JsonMergePatchHelper List jsonMergePatchModels = client.getModels().stream() - .filter(ModelUtil::isGeneratingModel) - .filter(ClientModelUtil::isJsonMergePatchModel).collect(Collectors.toList()); + .filter(model -> ModelUtil.isGeneratingModel(model) && ClientModelUtil.isJsonMergePatchModel(model, settings)) + .collect(Collectors.toList()); if (!jsonMergePatchModels.isEmpty()) { javaPackage.addJsonMergePatchHelper(jsonMergePatchModels); } diff --git a/typespec-tests/pom.xml b/typespec-tests/pom.xml index d26b385a20..985b2a3074 100644 --- a/typespec-tests/pom.xml +++ b/typespec-tests/pom.xml @@ -52,6 +52,20 @@ 4.11.0 test + + + + net.bytebuddy + byte-buddy + 1.14.12 + test + + + net.bytebuddy + byte-buddy-agent + 1.14.12 + test + io.projectreactor reactor-test diff --git a/typespec-tests/src/main/java/com/_specs_/azure/clientgenerator/core/access/implementation/models/AbstractModel.java b/typespec-tests/src/main/java/com/_specs_/azure/clientgenerator/core/access/implementation/models/AbstractModel.java index 7ff66964b9..868c9a2020 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/clientgenerator/core/access/implementation/models/AbstractModel.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/clientgenerator/core/access/implementation/models/AbstractModel.java @@ -21,7 +21,7 @@ public class AbstractModel implements JsonSerializable { * The kind property. */ @Generated - private String kind; + private String kind = "AbstractModel"; /* * The name property. @@ -36,7 +36,6 @@ public class AbstractModel implements JsonSerializable { */ @Generated protected AbstractModel(String name) { - this.kind = "AbstractModel"; this.name = name; } diff --git a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/Dog.java b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/Dog.java index ba55edbf3d..0fc8c725a0 100644 --- a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/Dog.java +++ b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/Dog.java @@ -24,7 +24,7 @@ public class Dog { */ @JsonTypeId @JsonProperty(value = "kind", required = true) - private DogKind kind; + private DogKind kind = DogKind.fromString("Dog"); /* * Weight of the dog @@ -36,7 +36,6 @@ public class Dog { * Creates an instance of Dog class. */ public Dog() { - this.kind = DogKind.fromString("Dog"); } /** diff --git a/typespec-tests/src/main/java/com/cadl/naming/models/Data.java b/typespec-tests/src/main/java/com/cadl/naming/models/Data.java index c28af47bbf..34da609016 100644 --- a/typespec-tests/src/main/java/com/cadl/naming/models/Data.java +++ b/typespec-tests/src/main/java/com/cadl/naming/models/Data.java @@ -22,14 +22,13 @@ public class Data implements JsonSerializable { * The @data.kind property. */ @Generated - private String type; + private String type = "Data"; /** * Creates an instance of Data class. */ @Generated protected Data() { - this.type = "Data"; } /** diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java index dfe9f9f771..f65a877e88 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java @@ -24,7 +24,7 @@ public class Fish implements JsonSerializable { * The kind property. */ @Generated - private String kind; + private String kind = "Fish"; /* * The id property. @@ -104,7 +104,6 @@ public void setColor(Fish model, String color) { */ @Generated public Fish() { - this.kind = "Fish"; this.updatedProperties.add("kind"); } @@ -276,9 +275,7 @@ public static Fish fromJson(JsonReader jsonReader) throws IOException { } // Use the discriminator value to determine which subtype should be deserialized. if ("shark".equals(discriminatorValue)) { - return Shark.fromJsonKnownDiscriminator(readerToUse.reset()); - } else if ("saw".equals(discriminatorValue)) { - return SawShark.fromJson(readerToUse.reset()); + return Shark.fromJson(readerToUse.reset()); } else if ("salmon".equals(discriminatorValue)) { return Salmon.fromJson(readerToUse.reset()); } else { diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java b/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java index dd6eb50a33..d6e7241579 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java @@ -19,6 +19,12 @@ */ @Fluent public final class SawShark extends Shark { + /* + * The kind property. + */ + @Generated + private String kind = "shark"; + /* * The sharktype property. */ @@ -36,6 +42,7 @@ public final class SawShark extends Shark { */ @Generated public SawShark() { + this.updatedProperties.add("kind"); this.updatedProperties.add("sharktype"); } @@ -93,6 +100,7 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); + jsonWriter.writeStringField("kind", this.kind); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("color", getColor()); jsonWriter.writeNumberField("weight", getWeight()); @@ -104,6 +112,13 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStartObject(); + if (updatedProperties.contains("kind")) { + if (this.kind == null) { + jsonWriter.writeNullField("kind"); + } else { + jsonWriter.writeStringField("kind", this.kind); + } + } jsonWriter.writeIntField("age", getAge()); if (updatedProperties.contains("color")) { if (getColor() == null) { diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java index c88c8111ab..0725982933 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java @@ -19,6 +19,12 @@ */ @Fluent public class Shark extends Fish { + /* + * The kind property. + */ + @Generated + private String kind = "shark"; + /* * The sharktype property. */ @@ -51,7 +57,7 @@ public void setWeight(Shark model, Integer weight) { */ @Generated public Shark() { - this.sharktype = "shark"; + this.updatedProperties.add("kind"); this.updatedProperties.add("sharktype"); } @@ -120,6 +126,7 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); + jsonWriter.writeStringField("kind", this.kind); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("color", getColor()); jsonWriter.writeStringField("sharktype", this.sharktype); @@ -131,6 +138,13 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStartObject(); + if (updatedProperties.contains("kind")) { + if (this.kind == null) { + jsonWriter.writeNullField("kind"); + } else { + jsonWriter.writeStringField("kind", this.kind); + } + } jsonWriter.writeIntField("age", getAge()); if (updatedProperties.contains("color")) { if (getColor() == null) { diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Dog.java b/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Dog.java index ac0b2b191b..d4f046b81f 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Dog.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Dog.java @@ -21,7 +21,7 @@ public class Dog implements JsonSerializable { * discriminator property */ @Generated - private DogKind kind; + private DogKind kind = DogKind.fromString("Dog"); /* * Weight of the dog @@ -36,7 +36,6 @@ public class Dog implements JsonSerializable { */ @Generated public Dog(int weight) { - this.kind = DogKind.fromString("Dog"); this.weight = weight; } diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Snake.java b/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Snake.java index 74c84ff808..cea781f69a 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Snake.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/enumdiscriminator/models/Snake.java @@ -21,7 +21,7 @@ public class Snake implements JsonSerializable { * discriminator property */ @Generated - private SnakeKind kind; + private SnakeKind kind = SnakeKind.fromString("Snake"); /* * Length of the snake @@ -36,7 +36,6 @@ public class Snake implements JsonSerializable { */ @Generated public Snake(int length) { - this.kind = SnakeKind.fromString("Snake"); this.length = length; } diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Fish.java b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Fish.java index fce0019c27..6fab81a60e 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Fish.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Fish.java @@ -21,7 +21,7 @@ public class Fish implements JsonSerializable { * The kind property. */ @Generated - private String kind; + private String kind = "Fish"; /* * The age property. @@ -36,7 +36,6 @@ public class Fish implements JsonSerializable { */ @Generated public Fish(int age) { - this.kind = "Fish"; this.age = age; } @@ -99,11 +98,7 @@ public static Fish fromJson(JsonReader jsonReader) throws IOException { } // Use the discriminator value to determine which subtype should be deserialized. if ("shark".equals(discriminatorValue)) { - return Shark.fromJsonKnownDiscriminator(readerToUse.reset()); - } else if ("saw".equals(discriminatorValue)) { - return SawShark.fromJson(readerToUse.reset()); - } else if ("goblin".equals(discriminatorValue)) { - return GoblinShark.fromJson(readerToUse.reset()); + return Shark.fromJson(readerToUse.reset()); } else if ("salmon".equals(discriminatorValue)) { return Salmon.fromJson(readerToUse.reset()); } else { diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/GoblinShark.java b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/GoblinShark.java index 0fc4bc3b8c..2fa8e54b95 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/GoblinShark.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/GoblinShark.java @@ -16,6 +16,12 @@ */ @Immutable public final class GoblinShark extends Shark { + /* + * The kind property. + */ + @Generated + private String kind = "shark"; + /* * The sharktype property. */ @@ -50,6 +56,7 @@ public String getSharktype() { @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStartObject(); + jsonWriter.writeStringField("kind", this.kind); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("sharktype", this.sharktype); return jsonWriter.writeEndObject(); diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/SawShark.java b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/SawShark.java index ef7305ac0f..d0345243a3 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/SawShark.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/SawShark.java @@ -16,6 +16,12 @@ */ @Immutable public final class SawShark extends Shark { + /* + * The kind property. + */ + @Generated + private String kind = "shark"; + /* * The sharktype property. */ @@ -50,6 +56,7 @@ public String getSharktype() { @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStartObject(); + jsonWriter.writeStringField("kind", this.kind); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("sharktype", this.sharktype); return jsonWriter.writeEndObject(); diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Shark.java b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Shark.java index 0d1e3edb01..83ba5196e2 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Shark.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/nesteddiscriminator/models/Shark.java @@ -16,6 +16,12 @@ */ @Immutable public class Shark extends Fish { + /* + * The kind property. + */ + @Generated + private String kind = "shark"; + /* * The sharktype property. */ @@ -30,7 +36,6 @@ public class Shark extends Fish { @Generated public Shark(int age) { super(age); - this.sharktype = "shark"; } /** @@ -50,6 +55,7 @@ public String getSharktype() { @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStartObject(); + jsonWriter.writeStringField("kind", this.kind); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("sharktype", this.sharktype); return jsonWriter.writeEndObject(); diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Bird.java b/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Bird.java index 8cd05d6b41..6855214445 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Bird.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Bird.java @@ -21,7 +21,7 @@ public class Bird implements JsonSerializable { * The kind property. */ @Generated - private String kind; + private String kind = "Bird"; /* * The wingspan property. @@ -36,7 +36,6 @@ public class Bird implements JsonSerializable { */ @Generated public Bird(int wingspan) { - this.kind = "Bird"; this.wingspan = wingspan; } diff --git a/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Dinosaur.java b/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Dinosaur.java index c95181e5d1..5c98891e39 100644 --- a/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Dinosaur.java +++ b/typespec-tests/src/main/java/com/type/model/inheritance/singlediscriminator/models/Dinosaur.java @@ -21,7 +21,7 @@ public class Dinosaur implements JsonSerializable { * The kind property. */ @Generated - private String kind; + private String kind = "Dinosaur"; /* * The size property. @@ -36,7 +36,6 @@ public class Dinosaur implements JsonSerializable { */ @Generated protected Dinosaur(int size) { - this.kind = "Dinosaur"; this.size = size; } diff --git a/typespec-tests/src/main/java/com/type/property/additionalproperties/models/ExtendsUnknownAdditionalPropertiesDiscriminated.java b/typespec-tests/src/main/java/com/type/property/additionalproperties/models/ExtendsUnknownAdditionalPropertiesDiscriminated.java index 14399ad1a1..c336bbe475 100644 --- a/typespec-tests/src/main/java/com/type/property/additionalproperties/models/ExtendsUnknownAdditionalPropertiesDiscriminated.java +++ b/typespec-tests/src/main/java/com/type/property/additionalproperties/models/ExtendsUnknownAdditionalPropertiesDiscriminated.java @@ -24,7 +24,7 @@ public class ExtendsUnknownAdditionalPropertiesDiscriminated * The discriminator */ @Generated - private String kind; + private String kind = "ExtendsUnknownAdditionalPropertiesDiscriminated"; /* * The name property @@ -45,7 +45,6 @@ public class ExtendsUnknownAdditionalPropertiesDiscriminated */ @Generated public ExtendsUnknownAdditionalPropertiesDiscriminated(String name) { - this.kind = "ExtendsUnknownAdditionalPropertiesDiscriminated"; this.name = name; } diff --git a/typespec-tests/src/main/java/com/type/property/additionalproperties/models/IsUnknownAdditionalPropertiesDiscriminated.java b/typespec-tests/src/main/java/com/type/property/additionalproperties/models/IsUnknownAdditionalPropertiesDiscriminated.java index 4f55ae9cdd..91dcdb0987 100644 --- a/typespec-tests/src/main/java/com/type/property/additionalproperties/models/IsUnknownAdditionalPropertiesDiscriminated.java +++ b/typespec-tests/src/main/java/com/type/property/additionalproperties/models/IsUnknownAdditionalPropertiesDiscriminated.java @@ -24,7 +24,7 @@ public class IsUnknownAdditionalPropertiesDiscriminated * The discriminator */ @Generated - private String kind; + private String kind = "IsUnknownAdditionalPropertiesDiscriminated"; /* * The name property @@ -45,7 +45,6 @@ public class IsUnknownAdditionalPropertiesDiscriminated */ @Generated public IsUnknownAdditionalPropertiesDiscriminated(String name) { - this.kind = "IsUnknownAdditionalPropertiesDiscriminated"; this.name = name; } diff --git a/typespec-tests/src/test/java/com/cadl/builtin/ExceptionTests.java b/typespec-tests/src/test/java/com/cadl/builtin/ExceptionTests.java index af8a7b73ee..a992f960e3 100644 --- a/typespec-tests/src/test/java/com/cadl/builtin/ExceptionTests.java +++ b/typespec-tests/src/test/java/com/cadl/builtin/ExceptionTests.java @@ -4,51 +4,23 @@ package com.cadl.builtin; import com.azure.core.exception.ResourceNotFoundException; -import com.azure.core.http.HttpClient; import com.azure.core.http.HttpHeaders; -import com.azure.core.http.HttpRequest; -import com.azure.core.http.HttpResponse; -import com.azure.core.models.ResponseError; -import org.junit.jupiter.api.Assertions; +import com.azure.core.test.http.MockHttpResponse; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; public class ExceptionTests { @Test public void testExceptionValue() { - HttpClient httpClient = Mockito.mock(HttpClient.class); - HttpResponse httpResponse = Mockito.mock(HttpResponse.class); - ArgumentCaptor httpRequest = ArgumentCaptor.forClass(HttpRequest.class); - String responseStr = "{\"error\":{\"code\":\"RESOURCE_NOT_FOUND\",\"message\":\"resource not found\"}}"; - Mockito.when(httpResponse.getStatusCode()).thenReturn(404); - Mockito.when(httpResponse.getHeaders()).thenReturn(new HttpHeaders()); - Mockito - .when(httpResponse.getBody()) - .thenReturn(Flux.just(ByteBuffer.wrap(responseStr.getBytes(StandardCharsets.UTF_8)))); - Mockito - .when(httpResponse.getBodyAsByteArray()) - .thenReturn(Mono.just(responseStr.getBytes(StandardCharsets.UTF_8))); - Mockito - .when(httpClient.send(httpRequest.capture(), Mockito.any())) - .thenReturn(Mono.defer( - () -> { - Mockito.when(httpResponse.getRequest()).thenReturn(httpRequest.getValue()); - return Mono.just(httpResponse); - })); - - BuiltinAsyncClient client = new BuiltinClientBuilder() - .endpoint("http://localhost:3000") - .httpClient(httpClient) - .buildAsyncClient(); + BuiltinAsyncClient client = new BuiltinClientBuilder().endpoint("http://localhost:3000") + .httpClient(request -> Mono.just(new MockHttpResponse(request, 404, new HttpHeaders(), + responseStr.getBytes(StandardCharsets.UTF_8)))) + .buildAsyncClient(); try { client.read("q", "q").block(); @@ -57,7 +29,7 @@ public void testExceptionValue() { //org.opentest4j.AssertionFailedError: //Expected :class com.azure.core.models.ResponseError //Actual :class java.util.LinkedHashMap -// Assertions.assertEquals(ResponseError.class, e.getValue().getClass()); + // Assertions.assertEquals(ResponseError.class, e.getValue().getClass()); } } } diff --git a/typespec-tests/src/test/java/com/cadl/flatten/FlattenTests.java b/typespec-tests/src/test/java/com/cadl/flatten/FlattenTests.java index ab84e538d2..82f84f1a0c 100644 --- a/typespec-tests/src/test/java/com/cadl/flatten/FlattenTests.java +++ b/typespec-tests/src/test/java/com/cadl/flatten/FlattenTests.java @@ -3,37 +3,46 @@ package com.cadl.flatten; -import com.azure.core.http.HttpHeaders; -import com.azure.core.http.rest.SimpleResponse; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.test.http.MockHttpResponse; import com.azure.core.util.BinaryData; +import com.azure.core.util.UrlBuilder; import com.cadl.flatten.implementation.FlattenClientImpl; import com.cadl.flatten.models.User; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import reactor.core.publisher.Mono; +import java.util.concurrent.atomic.AtomicReference; + public class FlattenTests { @Test public void testFlatten() { - FlattenClientImpl impl = Mockito.mock(FlattenClientImpl.class); - ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor payloadCaptor = ArgumentCaptor.forClass(BinaryData.class); - Mockito.when(impl.sendWithResponseAsync(idCaptor.capture(), payloadCaptor.capture(), Mockito.any())) - .thenReturn(Mono.just(new SimpleResponse<>(null, 200, new HttpHeaders(), null))); - + AtomicReference idCaptor = new AtomicReference<>(); + AtomicReference payloadCaptor = new AtomicReference<>(); + + HttpPipeline pipeline = new HttpPipelineBuilder() + .httpClient(request -> { + payloadCaptor.set(request.getBodyAsBinaryData()); + idCaptor.set(UrlBuilder.parse(request.getUrl()).getQuery().get("id")); + return Mono.just(new MockHttpResponse(request, 200)); + }) + .build(); + FlattenClientImpl impl = new FlattenClientImpl(pipeline, "https://localhost", + FlattenServiceVersion.V2022_06_01_PREVIEW); FlattenAsyncClient client = new FlattenAsyncClient(impl); - client.send("id1", "input1", new User("user1")); + client.send("id1", "input1", new User("user1")).block(); - Assertions.assertEquals("id1", idCaptor.getValue()); - Assertions.assertEquals("{\"input\":\"input1\",\"constant\":\"constant\",\"user\":{\"user\":\"user1\"}}", payloadCaptor.getValue().toString()); + Assertions.assertEquals("id1", idCaptor.get()); + Assertions.assertEquals("{\"input\":\"input1\",\"constant\":\"constant\",\"user\":{\"user\":\"user1\"}}", + payloadCaptor.get().toString()); - client.send("id2", "input2"); + client.send("id2", "input2").block(); - Assertions.assertEquals("id2", idCaptor.getValue()); - Assertions.assertEquals("{\"input\":\"input2\",\"constant\":\"constant\"}", payloadCaptor.getValue().toString()); + Assertions.assertEquals("id2", idCaptor.get()); + Assertions.assertEquals("{\"input\":\"input2\",\"constant\":\"constant\"}", payloadCaptor.get().toString()); } } diff --git a/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java b/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java index 25f3a118e0..09f498295a 100644 --- a/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java +++ b/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java @@ -132,9 +132,7 @@ public void testSerializationForHierarchicalProperty() throws JsonProcessingExce String json = BinaryData.fromObject(resource).toString(); JsonNode node = OBJECT_MAPPER.readTree(json); Assertions.assertEquals(JsonNodeType.NULL, node.get("fish").get("color").getNodeType()); - // TODO (alzimmer): Added SawShark into the hierarchy for further validation but this brings up a bug where - // multi-level polymorphism does not generate correctly. Need to fix this in the future. - Assertions.assertEquals("shark", node.get("fish").get("sharktype").asText()); + Assertions.assertEquals("shark", node.get("fish").get("kind").asText()); Assertions.assertEquals(2, node.get("fish").get("age").asInt()); } diff --git a/typespec-tests/src/test/java/com/type/model/inheritance/NestedDiscriminatorTests.java b/typespec-tests/src/test/java/com/type/model/inheritance/NestedDiscriminatorTests.java index ba86ac0a39..c4e2ef844f 100644 --- a/typespec-tests/src/test/java/com/type/model/inheritance/NestedDiscriminatorTests.java +++ b/typespec-tests/src/test/java/com/type/model/inheritance/NestedDiscriminatorTests.java @@ -30,7 +30,6 @@ void getModel() { } @Test - @Disabled("The item `kind` is missing in the generated json file by the method `toJson` of the class `Shark`.") void putModel() { Shark body = new GoblinShark(1); client.putModel(body); @@ -41,14 +40,13 @@ void getRecursiveModel() { Salmon salmon = (Salmon) client.getRecursiveModel(); Assertions.assertEquals(2, salmon.getFriends().size()); Assertions.assertEquals(2, salmon.getHate().size()); - Assertions.assertEquals(Shark.class, salmon.getPartner().getClass()); + Assertions.assertEquals(SawShark.class, salmon.getPartner().getClass()); Assertions.assertEquals(1, salmon.getAge()); Assertions.assertEquals(2, (salmon.getPartner()).getAge()); } @Test - @Disabled("The item `kind` is missing in the generated json file by the method `toJson` of the class `Shark`. ") void putRecursiveModel() { Salmon salmon = new Salmon(1); salmon.setPartner(new SawShark(2)); @@ -88,4 +86,4 @@ void getWrongDiscriminator() { Fish fish = client.getWrongDiscriminator(); Assertions.assertEquals(1, fish.getAge()); } -} \ No newline at end of file +} diff --git a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/DotFish.java b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/DotFish.java index 477544d3d9..683268c40e 100644 --- a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/DotFish.java +++ b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/DotFish.java @@ -19,7 +19,7 @@ public class DotFish implements JsonSerializable { /* * The fish.type property. */ - private String fishType; + private String fishType = "DotFish"; /* * The species property. @@ -30,7 +30,6 @@ public class DotFish implements JsonSerializable { * Creates an instance of DotFish class. */ protected DotFish() { - this.fishType = "DotFish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/Fish.java b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/Fish.java index 5b78180b6d..aaa347e2e5 100644 --- a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/Fish.java +++ b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/Fish.java @@ -20,7 +20,7 @@ public class Fish implements JsonSerializable { /* * The fishtype property. */ - private String fishtype; + private String fishtype = "Fish"; /* * The species property. @@ -43,7 +43,6 @@ public class Fish implements JsonSerializable { * @param length the length value to set. */ public Fish(float length) { - this.fishtype = "Fish"; this.length = length; } diff --git a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/MyBaseType.java b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/MyBaseType.java index 4a84d6f071..860a987c5c 100644 --- a/vanilla-tests/src/main/java/fixtures/bodycomplex/models/MyBaseType.java +++ b/vanilla-tests/src/main/java/fixtures/bodycomplex/models/MyBaseType.java @@ -19,7 +19,7 @@ public class MyBaseType implements JsonSerializable { /* * The kind property. */ - private MyKind kind; + private MyKind kind = MyKind.fromString("MyBaseType"); /* * The propB1 property. @@ -35,7 +35,6 @@ public class MyBaseType implements JsonSerializable { * Creates an instance of MyBaseType class. */ protected MyBaseType() { - this.kind = MyKind.fromString("MyBaseType"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/discriminatorenum/models/Dog.java b/vanilla-tests/src/main/java/fixtures/discriminatorenum/models/Dog.java index 92837a0c12..0374dbc373 100644 --- a/vanilla-tests/src/main/java/fixtures/discriminatorenum/models/Dog.java +++ b/vanilla-tests/src/main/java/fixtures/discriminatorenum/models/Dog.java @@ -19,7 +19,7 @@ public class Dog implements JsonSerializable { /* * discriminator property */ - private DogKind kind; + private DogKind kind = DogKind.fromString("Dog"); /* * Weight of the dog @@ -30,7 +30,6 @@ public class Dog implements JsonSerializable { * Creates an instance of Dog class. */ public Dog() { - this.kind = DogKind.fromString("Dog"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/discriminatorflattening/clientflatten/models/MetricAlertCriteria.java b/vanilla-tests/src/main/java/fixtures/discriminatorflattening/clientflatten/models/MetricAlertCriteria.java index 022e7cc77d..2c360e8cba 100644 --- a/vanilla-tests/src/main/java/fixtures/discriminatorflattening/clientflatten/models/MetricAlertCriteria.java +++ b/vanilla-tests/src/main/java/fixtures/discriminatorflattening/clientflatten/models/MetricAlertCriteria.java @@ -21,7 +21,7 @@ public class MetricAlertCriteria implements JsonSerializable { /* * discriminator property */ - private DogKind kind; + private DogKind kind = DogKind.fromString("Dog"); /* * Weight of the dog @@ -31,7 +31,6 @@ public class Dog implements JsonSerializable { * Creates an instance of Dog class. */ public Dog() { - this.kind = DogKind.fromString("Dog"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java index 97a7ff9749..7fbf8db03a 100644 --- a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java +++ b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java @@ -36,7 +36,7 @@ public class MetricAlertCriteria { */ @JsonTypeId @JsonProperty(value = "odata.type", required = true) - private Odatatype odataType; + private Odatatype odataType = Odatatype.fromString("MetricAlertCriteria"); /* * The rule criteria that defines the conditions of the alert rule. @@ -48,7 +48,6 @@ public class MetricAlertCriteria { * Creates an instance of MetricAlertCriteria class. */ public MetricAlertCriteria() { - this.odataType = Odatatype.fromString("MetricAlertCriteria"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/DotFish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/DotFish.java index 5c68eb9870..45795f136b 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/DotFish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/DotFish.java @@ -19,7 +19,7 @@ public class DotFish implements JsonSerializable { /* * The fish.type property. */ - private String fishType; + private String fishType = "DotFish"; /* * The species property. @@ -30,7 +30,6 @@ public class DotFish implements JsonSerializable { * Creates an instance of DotFish class. */ public DotFish() { - this.fishType = "DotFish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/Fish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/Fish.java index 2c2ad32163..496c25ee23 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/Fish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/Fish.java @@ -20,7 +20,7 @@ public class Fish implements JsonSerializable { /* * The fishtype property. */ - private String fishtype; + private String fishtype = "Fish"; /* * The species property. @@ -41,7 +41,6 @@ public class Fish implements JsonSerializable { * Creates an instance of Fish class. */ public Fish() { - this.fishtype = "Fish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/MyBaseType.java b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/MyBaseType.java index d0497a5a66..aa6d5a488e 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/MyBaseType.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserialization/models/MyBaseType.java @@ -19,7 +19,7 @@ public class MyBaseType implements JsonSerializable { /* * The kind property. */ - private MyKind kind; + private MyKind kind = MyKind.fromString("MyBaseType"); /* * The propB1 property. @@ -35,7 +35,6 @@ public class MyBaseType implements JsonSerializable { * Creates an instance of MyBaseType class. */ public MyBaseType() { - this.kind = MyKind.fromString("MyBaseType"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/DotFish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/DotFish.java index cf23d48873..33598a7df8 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/DotFish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/DotFish.java @@ -19,7 +19,7 @@ public class DotFish implements JsonSerializable { /* * The fish.type property. */ - private String fishType; + private String fishType = "DotFish"; /* * The species property. @@ -30,7 +30,6 @@ public class DotFish implements JsonSerializable { * Creates an instance of DotFish class. */ public DotFish() { - this.fishType = "DotFish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/Fish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/Fish.java index 140dc61cab..0858834897 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/Fish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/Fish.java @@ -20,7 +20,7 @@ public class Fish implements JsonSerializable { /* * The fishtype property. */ - private String fishtype; + private String fishtype = "Fish"; /* * The species property. @@ -43,7 +43,6 @@ public class Fish implements JsonSerializable { * @param length the length value to set. */ public Fish(float length) { - this.fishtype = "Fish"; this.length = length; } diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/MyBaseType.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/MyBaseType.java index 5f422ce9e3..dab453466a 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/MyBaseType.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationctorargs/models/MyBaseType.java @@ -19,7 +19,7 @@ public class MyBaseType implements JsonSerializable { /* * The kind property. */ - private MyKind kind; + private MyKind kind = MyKind.fromString("MyBaseType"); /* * The propB1 property. @@ -35,7 +35,6 @@ public class MyBaseType implements JsonSerializable { * Creates an instance of MyBaseType class. */ public MyBaseType() { - this.kind = MyKind.fromString("MyBaseType"); } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/DotFish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/DotFish.java index 5a1490d3cf..0d4b41feef 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/DotFish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/DotFish.java @@ -19,7 +19,7 @@ public class DotFish implements JsonSerializable { /* * The fish.type property. */ - private String fishType; + private String fishType = "DotFish"; /* * The species property. @@ -30,7 +30,6 @@ public class DotFish implements JsonSerializable { * Creates an instance of DotFish class. */ protected DotFish() { - this.fishType = "DotFish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/Fish.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/Fish.java index c8306ed967..d7866310e8 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/Fish.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/Fish.java @@ -20,7 +20,7 @@ public class Fish implements JsonSerializable { /* * The fishtype property. */ - private String fishtype; + private String fishtype = "Fish"; /* * The species property. @@ -41,7 +41,6 @@ public class Fish implements JsonSerializable { * Creates an instance of Fish class. */ public Fish() { - this.fishtype = "Fish"; } /** diff --git a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/MyBaseType.java b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/MyBaseType.java index 1a841fb8d2..d45fb6c7ce 100644 --- a/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/MyBaseType.java +++ b/vanilla-tests/src/main/java/fixtures/streamstyleserializationimmutableoutput/models/MyBaseType.java @@ -19,7 +19,7 @@ public class MyBaseType implements JsonSerializable { /* * The kind property. */ - private MyKind kind; + private MyKind kind = MyKind.fromString("MyBaseType"); /* * The propB1 property. @@ -35,7 +35,6 @@ public class MyBaseType implements JsonSerializable { * Creates an instance of MyBaseType class. */ protected MyBaseType() { - this.kind = MyKind.fromString("MyBaseType"); } /**