From 189639a4a25df5b02786f4adbfe09bd1fa339909 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Fri, 19 Jan 2024 11:15:17 -0800 Subject: [PATCH 01/10] Update codgen to support latest generic APIs --- .../extension/base/plugin/JavaSettings.java | 8 + javagen/pom.xml | 5 + .../autorest/mapper/PrimitiveMapper.java | 3 +- .../autorest/mapper/ProxyMethodMapper.java | 1 + .../model/clientmodel/Annotation.java | 13 ++ .../autorest/model/clientmodel/ClassType.java | 7 +- .../model/clientmodel/ClientModel.java | 3 + .../model/clientmodel/ProxyMethod.java | 19 ++ .../clientmodel/ProxyMethodParameter.java | 16 +- .../autorest/model/javamodel/JavaPackage.java | 10 +- .../template/ClientMethodTemplateBase.java | 30 ++-- .../ConvenienceMethodTemplateBase.java | 6 +- .../azure/autorest/template/EnumTemplate.java | 100 ++++++++++- .../template/MethodGroupTemplate.java | 9 +- .../autorest/template/ModelTemplate.java | 21 ++- .../autorest/template/ProxyTemplate.java | 41 +++-- .../template/ServiceAsyncClientTemplate.java | 6 +- .../ServiceClientBuilderTemplate.java | 7 +- .../template/ServiceClientTemplate.java | 17 +- .../template/ServiceSyncClientTemplate.java | 7 +- .../template/WrapperClientMethodTemplate.java | 6 +- .../azure/autorest/util/ClientModelUtil.java | 1 + .../GenericMultipartFormDataHelper.java | 163 ++++++++++++++++++ .../com/azure/autorest/TypeSpecPlugin.java | 8 +- 24 files changed, 458 insertions(+), 49 deletions(-) create mode 100644 javagen/src/main/resources/GenericMultipartFormDataHelper.java diff --git a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java index 10969e3b47..b03dd215bd 100644 --- a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java +++ b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java @@ -168,6 +168,7 @@ public static JavaSettings getInstance() { getBooleanValue(host, "include-read-only-in-constructor-args", false), // setting the default as true as the Java design guideline recommends using String for URLs. getBooleanValue(host, "url-as-string", true), + getBooleanValue(host, "uuid-as-string", true), // setting this to false by default as a lot of existing libraries still use swagger and // were generated with required = true set in JsonProperty annotation @@ -329,6 +330,7 @@ private JavaSettings(AutorestSettings autorestSettings, boolean noCustomHeaders, boolean includeReadOnlyInConstructorArgs, boolean urlAsString, + boolean uuidAsString, boolean disableRequiredPropertyAnnotation, boolean pageSizeEnabled, boolean useKeyCredential, @@ -429,6 +431,7 @@ private JavaSettings(AutorestSettings autorestSettings, this.noCustomHeaders = noCustomHeaders; this.includeReadOnlyInConstructorArgs = includeReadOnlyInConstructorArgs; this.urlAsString = urlAsString; + this.uuidAsString = uuidAsString; this.disableRequiredJsonAnnotation = disableRequiredPropertyAnnotation; this.pageSizeEnabled = pageSizeEnabled; this.useKeyCredential = useKeyCredential; @@ -480,6 +483,11 @@ public boolean urlAsString() { return urlAsString; } + private final boolean uuidAsString; + public boolean uuidAsString() { + return uuidAsString; + } + private final boolean disableRequiredJsonAnnotation; public boolean isDisableRequiredJsonAnnotation() { return disableRequiredJsonAnnotation; diff --git a/javagen/pom.xml b/javagen/pom.xml index 3ea73f3161..c1d9131feb 100644 --- a/javagen/pom.xml +++ b/javagen/pom.xml @@ -68,6 +68,11 @@ 4.13.2 test + + com.generic + generic-core + 1.0.0-beta.1 + diff --git a/javagen/src/main/java/com/azure/autorest/mapper/PrimitiveMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/PrimitiveMapper.java index 47e17e5db0..6e7ff459fb 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/PrimitiveMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/PrimitiveMapper.java @@ -46,6 +46,7 @@ public IType map(PrimitiveSchema primaryType) { protected IType createPrimitiveType(PrimitiveSchema primaryType) { boolean isLowLevelClient = JavaSettings.getInstance().isDataPlaneClient(); boolean urlAsString = JavaSettings.getInstance().urlAsString(); + boolean uuidAsString = JavaSettings.getInstance().uuidAsString(); switch (primaryType.getType()) { // case null: @@ -106,7 +107,7 @@ protected IType createPrimitiveType(PrimitiveSchema primaryType) { } return durationType; case UNIXTIME: return isLowLevelClient ? PrimitiveType.LONG : PrimitiveType.UNIX_TIME_LONG; - case UUID: return isLowLevelClient ? ClassType.STRING : ClassType.UUID; + case UUID: return isLowLevelClient || uuidAsString ? ClassType.STRING : ClassType.UUID; case OBJECT: return ClassType.OBJECT; case CREDENTIAL: return ClassType.TOKEN_CREDENTIAL; default: diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java index 2d4c4d692b..125d5c1bb2 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java @@ -27,6 +27,7 @@ import com.azure.autorest.util.XmsExampleWrapper; import com.azure.core.http.HttpMethod; import com.azure.core.util.CoreUtils; +import com.generic.core.http.exception.HttpExceptionType; import org.slf4j.Logger; import java.util.ArrayList; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java index ee1ff2040d..b4e0501969 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java @@ -69,6 +69,19 @@ public class Annotation { .knownClass(com.azure.core.annotation.HeaderCollection.class) .build(); + public static final Annotation METADATA = new Annotation.Builder() + .knownClass(com.generic.core.annotation.Metadata.class) + .build(); + public static final Annotation HttpRequestInformation = new Annotation.Builder() + .knownClass(com.generic.core.http.annotation.HttpRequestInformation.class) + .build(); + public static final Annotation UnexpectedResponseExceptionInformation = new Annotation.Builder() + .knownClass(com.generic.core.http.annotation.UnexpectedResponseExceptionInformation.class) + .build(); + public static final Annotation TYPE_CONDITIONS = new Annotation.Builder() + .knownClass(com.generic.core.annotation.TypeConditions.class) + .build(); + private final String fullName; private final String packageName; private final String name; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java index 6b0b4fc49b..a70d5f634f 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java @@ -140,24 +140,25 @@ public String getGenericClass() { } private static final Map, ClassDetails> CLASS_TYPE_MAPPING = new HashMap, ClassDetails>() {{ - put(RestProxy.class, new ClassDetails(RestProxy.class, "com.generic.core.http.RestProxy")); + put(RestProxy.class, new ClassDetails(RestProxy.class, "com.generic.core.implementation.http.RestProxy")); put(HttpPipeline.class, new ClassDetails(HttpPipeline.class, "com.generic.core.http.pipeline.HttpPipeline")); put(HttpPipelineBuilder.class, new ClassDetails(HttpPipelineBuilder.class, "com.generic.core.http.pipeline.HttpPipelineBuilder")); put(Context.class, new ClassDetails(Context.class, "com.generic.core.models.Context")); put(HttpClient.class, new ClassDetails(HttpClient.class, "com.generic.core.http.client.HttpClient")); put(HttpLogOptions.class, new ClassDetails(HttpLogOptions.class, "com.generic.core.http.policy.logging.HttpLogOptions")); put(HttpPipelinePolicy.class, new ClassDetails(HttpPipelinePolicy.class, "com.generic.core.http.pipeline.HttpPipelinePolicy")); - put(KeyCredentialPolicy.class, new ClassDetails(KeyCredentialPolicy.class, "com.generic.core.http.policy.credential.KeyCredentialPolicy")); + put(KeyCredentialPolicy.class, new ClassDetails(KeyCredentialPolicy.class, "com.generic.core.http.policy.KeyCredentialPolicy")); put(Configuration.class, new ClassDetails(Configuration.class, "com.generic.core.util.configuration.Configuration")); put(HttpHeaders.class, new ClassDetails(HttpHeaders.class, "com.generic.core.models.Headers")); put(HttpHeaderName.class, new ClassDetails(HttpHeaderName.class, "com.generic.core.http.models.HttpHeaderName")); put(HttpRequest.class, new ClassDetails(HttpRequest.class, "com.generic.core.http.models.HttpRequest")); - put(RequestOptions.class, new ClassDetails(RequestOptions.class, "com.generic.core.models.RequestOptions")); + put(RequestOptions.class, new ClassDetails(RequestOptions.class, "com.generic.core.http.models.RequestOptions")); put(BinaryData.class, new ClassDetails(BinaryData.class, "com.generic.core.models.BinaryData")); put(RetryOptions.class, new ClassDetails(RetryOptions.class, "com.generic.core.http.policy.retry.RetryOptions")); put(Response.class, new ClassDetails(Response.class, "com.generic.core.http.Response")); put(SimpleResponse.class, new ClassDetails(SimpleResponse.class, "com.generic.core.http.SimpleResponse")); put(ExpandableStringEnum.class, new ClassDetails(ExpandableStringEnum.class, "com.generic.core.models.ExpandableStringEnum")); + put(HttpResponseException.class, new ClassDetails(HttpResponseException.class, "com.generic.core.http.exception.HttpResponseException")); }}; private static ClassType.Builder getClassTypeBuilder(Class classKey) { 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 bc012ca48c..1d044685a9 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 @@ -416,6 +416,8 @@ protected void addJsonFlattenAnnotationImport(Set imports) { */ protected void addImmutableAnnotationImport(Set imports) { Annotation.IMMUTABLE.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); + Annotation.TYPE_CONDITIONS.addImportsTo(imports); } /** @@ -425,6 +427,7 @@ protected void addImmutableAnnotationImport(Set imports) { */ protected void addFluentAnnotationImport(Set imports) { Annotation.FLUENT.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); } /** diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java index 662992f434..7029b96def 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java @@ -8,7 +8,10 @@ import com.azure.autorest.util.MethodNamer; import com.azure.core.http.ContentType; import com.azure.core.http.HttpMethod; +import com.generic.core.http.exception.HttpExceptionType; +import com.generic.core.implementation.http.rest.RestProxyUtils; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -18,6 +21,14 @@ * A method within a Proxy. */ public class ProxyMethod { + + private static final Map EXCEPTION_TYPE_MAP = new HashMap<>() {{ + put(ClassType.CLIENT_AUTHENTICATION_EXCEPTION, HttpExceptionType.CLIENT_AUTHENTICATION); + put(ClassType.RESOURCE_EXISTS_EXCEPTION, HttpExceptionType.RESOURCE_EXISTS); + put(ClassType.RESOURCE_NOT_FOUND_EXCEPTION, HttpExceptionType.RESOURCE_NOT_FOUND); + put(ClassType.RESOURCE_MODIFIED_EXCEPTION, HttpExceptionType.RESOURCE_MODIFIED); + }}; + /** * Get the Content-Type of the request. */ @@ -388,6 +399,9 @@ private IType mapToSyncType(IType type) { * implementations. */ public void addImportsTo(Set imports, boolean includeImplementationImports, JavaSettings settings) { + imports.add(RestProxyUtils.class.getName()); + Annotation.HttpRequestInformation.addImportsTo(imports); + Annotation.UnexpectedResponseExceptionInformation.addImportsTo(imports); if (includeImplementationImports) { if (getUnexpectedResponseExceptionType() != null) { Annotation.UNEXPECTED_RESPONSE_EXCEPTION_TYPE.addImportsTo(imports); @@ -426,6 +440,11 @@ public void addImportsTo(Set imports, boolean includeImplementationImpor } } + public HttpExceptionType getHttpExceptionType(ClassType classType) { + return EXCEPTION_TYPE_MAP.get(classType); + } + + public static class Builder { protected String requestContentType; protected IType returnType; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodParameter.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodParameter.java index 5c30b84483..4f684b7637 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodParameter.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodParameter.java @@ -171,9 +171,15 @@ public final String convertFromClientType(String source, String target, boolean */ public void addImportsTo(Set imports, boolean includeImplementationImports, JavaSettings settings) { if (getRequestParameterLocation() != RequestParameterLocation.NONE/* && getRequestParameterLocation() != RequestParameterLocation.FormData*/) { - imports.add(String.format("%1$s.annotation.%2$sParam", - ExternalPackage.CORE.getPackageName(), - CodeNamer.toPascalCase(getRequestParameterLocation().toString()))); + if (settings.isBranded()) { + imports.add(String.format("%1$s.annotation.%2$sParam", + ExternalPackage.CORE.getPackageName(), + CodeNamer.toPascalCase(getRequestParameterLocation().toString()))); + } else { + imports.add(String.format("%1$s.http.annotation.%2$sParam", + ExternalPackage.CORE.getPackageName(), + CodeNamer.toPascalCase(getRequestParameterLocation().toString()))); + } } if (getRequestParameterLocation() != RequestParameterLocation.BODY) { if (getClientType() == ArrayType.BYTE_ARRAY) { @@ -189,6 +195,10 @@ public void addImportsTo(Set imports, boolean includeImplementationImpor // imports.add(String.format("com.azure.core.annotation.FormParam")); // } + if (!settings.isBranded()) { + imports.add("com.generic.core.http.models.HttpMethod"); + } + getWireType().addImportsTo(imports, includeImplementationImports); } diff --git a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaPackage.java b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaPackage.java index f891d1ffee..b4bc8eec6a 100644 --- a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaPackage.java +++ b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaPackage.java @@ -220,15 +220,19 @@ public final void addPom(String name, Pom pom) { } public final void addJavaFromResources(String packageName, String name) { - JavaFile javaFile = javaFileFactory.createSourceFile(packageName, name); - try (InputStream inputStream = JavaPackage.class.getClassLoader().getResourceAsStream(name + ".java"); + addJavaFromResources(packageName, name, name); + } + + public final void addJavaFromResources(String packageName, String resourceName, String fileName) { + JavaFile javaFile = javaFileFactory.createSourceFile(packageName, fileName); + try (InputStream inputStream = JavaPackage.class.getClassLoader().getResourceAsStream(resourceName + ".java"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { Iterator linesIterator = bufferedReader.lines().iterator(); while (linesIterator.hasNext()) { javaFile.line(linesIterator.next()); } } catch (IOException e) { - throw new RuntimeException("Failed to read " + name + ".java from resources.", e); + throw new RuntimeException("Failed to read " + resourceName + ".java from resources.", e); } addJavaFile(javaFile); } diff --git a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplateBase.java b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplateBase.java index 401dfbeaa3..a7e72f3d17 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplateBase.java @@ -132,19 +132,25 @@ protected static void generateProtocolMethodJavadoc(ClientMethod clientMethod, J protected static void generateJavadocExceptions(ClientMethod clientMethod, JavaJavadocComment commentBlock, boolean useFullClassName) { ProxyMethod restAPIMethod = clientMethod.getProxyMethod(); - if (restAPIMethod != null && restAPIMethod.getUnexpectedResponseExceptionType() != null) { - commentBlock.methodThrows(useFullClassName - ? restAPIMethod.getUnexpectedResponseExceptionType().getFullName() - : restAPIMethod.getUnexpectedResponseExceptionType().getName(), - "thrown if the request is rejected by server"); - } - if (restAPIMethod != null && restAPIMethod.getUnexpectedResponseExceptionTypes() != null) { - for (Map.Entry> exception : restAPIMethod.getUnexpectedResponseExceptionTypes().entrySet()) { + if (JavaSettings.getInstance().isBranded()) { + if (restAPIMethod != null && restAPIMethod.getUnexpectedResponseExceptionType() != null) { commentBlock.methodThrows(useFullClassName - ? exception.getKey().getFullName() - : exception.getKey().getName(), - String.format("thrown if the request is rejected by server on status code %s", - exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + ? restAPIMethod.getUnexpectedResponseExceptionType().getFullName() + : restAPIMethod.getUnexpectedResponseExceptionType().getName(), + "thrown if the request is rejected by server"); + } + if (restAPIMethod != null && restAPIMethod.getUnexpectedResponseExceptionTypes() != null) { + for (Map.Entry> exception : restAPIMethod.getUnexpectedResponseExceptionTypes().entrySet()) { + commentBlock.methodThrows(useFullClassName + ? exception.getKey().getFullName() + : exception.getKey().getName(), + String.format("thrown if the request is rejected by server on status code %s", + exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + } + } + } else { + if (restAPIMethod != null && (restAPIMethod.getUnexpectedResponseExceptionType() != null || restAPIMethod.getUnexpectedResponseExceptionTypes() != null)) { + commentBlock.methodThrows("HttpResponseException", "thrown if the service returns an error"); } } } 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 77a8f73257..277be9a8f9 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java @@ -344,7 +344,11 @@ protected void addImports(Set imports, List convenien } protected void addGeneratedAnnotation(JavaType typeBlock) { - typeBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + typeBlock.annotation(Annotation.GENERATED.getName()); + } else { + typeBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } /** diff --git a/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java b/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java index 77169803c1..ec150cb0d6 100644 --- a/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java @@ -14,11 +14,15 @@ import com.azure.autorest.model.javamodel.JavaEnum; import com.azure.autorest.model.javamodel.JavaFile; import com.azure.autorest.model.javamodel.JavaJavadocComment; +import com.azure.autorest.model.javamodel.JavaModifier; +import com.azure.autorest.model.javamodel.JavaVisibility; import com.azure.autorest.util.CodeNamer; import com.azure.core.util.CoreUtils; +import com.generic.core.models.HeaderName; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Writes a EnumType to a JavaFile. @@ -37,12 +41,92 @@ public final void write(EnumType enumType, JavaFile javaFile) { JavaSettings settings = JavaSettings.getInstance(); if (enumType.getExpandable()) { - writeExpandableStringEnum(enumType, javaFile, settings); + if(settings.isBranded()) { + writeExpandableStringEnum(enumType, javaFile, settings); + } else { + writeExpandableStringEnumInterface(enumType, javaFile, settings); + } } else { writeEnum(enumType, javaFile, settings); } } + private void writeExpandableStringEnumInterface(EnumType enumType, JavaFile javaFile, JavaSettings settings) { + Set imports = new HashSet<>(); + imports.add("java.util.Collection"); + imports.add("java.util.concurrent.ConcurrentHashMap"); + imports.add("java.util.Map"); + imports.add(getStringEnumImport()); + if (!settings.isStreamStyleSerialization()) { + imports.add("com.fasterxml.jackson.annotation.JsonCreator"); + } + + addGeneratedImport(imports); + + javaFile.declareImport(imports); + javaFile.javadocComment(comment -> comment.description(enumType.getDescription())); + + String enumName = enumType.getName(); + String declaration = enumName + " implements ExpandableStringEnum<" + enumName + ">"; + + javaFile.publicFinalClass(declaration, classBlock -> { + IType elementType = enumType.getElementType(); + String typeName = elementType.getClientType().toString(); + String pascalTypeName = CodeNamer.toPascalCase(typeName); + classBlock.publicStaticFinalVariable("Map VALUES = new ConcurrentHashMap<>()"); + + for (ClientEnumValue enumValue : enumType.getValues()) { + String value = enumValue.getValue(); + classBlock.javadocComment(CoreUtils.isNullOrEmpty(enumValue.getDescription()) + ? "Static value " + value + " for " + enumName + "." + : enumValue.getDescription()); + addGeneratedAnnotation(classBlock); + classBlock.publicStaticFinalVariable(String.format("%1$s %2$s = from%3$s(%4$s)", enumName, + enumValue.getName(), pascalTypeName, elementType.defaultValueExpression(value))); + } + + classBlock.variable("String name", JavaVisibility.Private, JavaModifier.Final); + classBlock.privateConstructor(enumName + "(String name)", ctor -> { + ctor.line("this.name = name;"); + }); + + // fromString(typeName) + classBlock.javadocComment(comment -> { + comment.description("Creates or finds a " + enumName + " from its string representation."); + comment.param("name", "a name to look for"); + comment.methodReturns("the corresponding " + enumName); + }); + + addGeneratedAnnotation(classBlock); + if (!settings.isStreamStyleSerialization()) { + classBlock.annotation("JsonCreator"); + } + + classBlock.publicStaticMethod(String.format("%1$s from%2$s(%3$s name)", enumName, pascalTypeName, typeName), + function -> { + function.ifBlock("name == null", ifAction -> ifAction.methodReturn("null")); + function.line(enumName + " value = VALUES.get(name);"); + function.ifBlock("value != null", ifAction -> { + ifAction.line("return value;"); + }); + function.methodReturn("VALUES.computeIfAbsent(name, key -> new " + enumName + "(key))"); + }); + + // values() + classBlock.javadocComment(comment -> { + comment.description("Gets known " + enumName + " values."); + comment.methodReturns("known " + enumName + " values"); + }); + + addGeneratedAnnotation(classBlock); + classBlock.publicStaticMethod("Collection<" + enumName + "> values()", + function -> function.methodReturn("VALUES.values()")); + + classBlock.annotation("Override"); + classBlock.method(JavaVisibility.Public, null, "String toString()", function -> function.methodReturn("name")); + }); + } + private void writeExpandableStringEnum(EnumType enumType, JavaFile javaFile, JavaSettings settings) { Set imports = new HashSet<>(); imports.add("java.util.Collection"); @@ -215,18 +299,28 @@ protected String createEnumJsonCreatorIfCheck(EnumType enumType) { protected void addGeneratedImport(Set imports) { if (JavaSettings.getInstance().isDataPlaneClient()) { Annotation.GENERATED.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); } } protected void addGeneratedAnnotation(JavaContext classBlock) { if (JavaSettings.getInstance().isDataPlaneClient()) { - classBlock.annotation(Annotation.GENERATED.getName()); + + if (JavaSettings.getInstance().isBranded()) { + classBlock.annotation(Annotation.GENERATED.getName()); + } else { + classBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } } protected void addGeneratedAnnotation(JavaEnum enumBlock) { if (JavaSettings.getInstance().isDataPlaneClient()) { - enumBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + enumBlock.annotation(Annotation.GENERATED.getName()); + } else { + enumBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } } } diff --git a/javagen/src/main/java/com/azure/autorest/template/MethodGroupTemplate.java b/javagen/src/main/java/com/azure/autorest/template/MethodGroupTemplate.java index 46e3bccc14..60ceea3e43 100644 --- a/javagen/src/main/java/com/azure/autorest/template/MethodGroupTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/MethodGroupTemplate.java @@ -122,7 +122,12 @@ protected void writeAdditionalClassBlock(JavaClass classBlock) { protected void writeServiceProxyConstruction(JavaBlock constructor, MethodGroupClient methodGroupClient) { ClassType proxyType = ClassType.REST_PROXY; - constructor.line(String.format("this.service = %1$s.create(%2$s.class, client.getHttpPipeline(), client.getSerializerAdapter());", - proxyType.getName(), methodGroupClient.getProxy().getName())); + if (JavaSettings.getInstance().isBranded()) { + constructor.line(String.format("this.service = %1$s.create(%2$s.class, client.getHttpPipeline(), client.getSerializerAdapter());", + proxyType.getName(), methodGroupClient.getProxy().getName())); + } else { + constructor.line(String.format("this.service = %1$s.create(%2$s.class, client.getHttpPipeline(), RestProxyUtils.createDefaultSerializer());", + proxyType.getName(), methodGroupClient.getProxy().getName())); + } } } 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 aa2237fe43..bf2ce64b3a 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -495,10 +495,18 @@ private void addFluentOrImmutableAnnotation(ClientModel model, boolean immutable .concat(model.getProperties().stream(), propertyReferences.stream()) .anyMatch(p -> ClientModelUtil.hasSetter(p, settings)); - if (fluent) { - javaFile.annotation("Fluent"); + if (JavaSettings.getInstance().isBranded()) { + if (fluent) { + javaFile.annotation("Fluent"); + } else { + javaFile.annotation("Immutable"); + } } else { - javaFile.annotation("Immutable"); + if (fluent) { + javaFile.annotation("Metadata(conditions = {TypeConditions.FLUENT})"); + } else { + javaFile.annotation("Metadata(conditions = {TypeConditions.IMMUTABLE})"); + } } } @@ -1141,12 +1149,17 @@ protected void writeStreamStyleSerialization(JavaClass classBlock, ClientModel m protected void addGeneratedImport(Set imports) { if (JavaSettings.getInstance().isDataPlaneClient()) { Annotation.GENERATED.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); } } protected void addGeneratedAnnotation(JavaContext classBlock) { if (JavaSettings.getInstance().isDataPlaneClient()) { - classBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + classBlock.annotation(Annotation.GENERATED.getName()); + } else { + classBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } } diff --git a/javagen/src/main/java/com/azure/autorest/template/ProxyTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ProxyTemplate.java index 148d29af45..47afa9c934 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ProxyTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ProxyTemplate.java @@ -42,8 +42,12 @@ public final void write(Proxy restAPI, JavaClass classBlock) { { comment.description(String.format("The interface defining all the services for %1$s to be used by the proxy service to perform REST calls.", restAPI.getClientTypeName())); }); - classBlock.annotation(String.format("Host(\"%1$s\")", restAPI.getBaseURL())); - classBlock.annotation(String.format("ServiceInterface(name = \"%1$s\")", serviceInterfaceWithLengthLimit(restAPI.getClientTypeName()))); + if (settings.isBranded()) { + classBlock.annotation(String.format("Host(\"%1$s\")", restAPI.getBaseURL())); + classBlock.annotation(String.format("ServiceInterface(name = \"%1$s\")", serviceInterfaceWithLengthLimit(restAPI.getClientTypeName()))); + } else { + classBlock.annotation(String.format("ServiceInterface(name = \"%1$s\", host = \"%2$s\")", serviceInterfaceWithLengthLimit(restAPI.getClientTypeName()), restAPI.getBaseURL())); + } JavaVisibility visibility = JavaVisibility.Private; if (settings.isServiceInterfaceAsPublic()) { @@ -59,10 +63,15 @@ public final void write(Proxy restAPI, JavaClass classBlock) { writeProxyMethodHeaders(restAPIMethod, interfaceBlock); - interfaceBlock.annotation(String.format("%1$s(\"%2$s\")", CodeNamer.toPascalCase(restAPIMethod.getHttpMethod().toString().toLowerCase()), restAPIMethod.getUrlPath())); - - if (!restAPIMethod.getResponseExpectedStatusCodes().isEmpty()) { - interfaceBlock.annotation(String.format("ExpectedResponses({%1$s})", restAPIMethod.getResponseExpectedStatusCodes().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + if (settings.isBranded()) { + interfaceBlock.annotation(String.format("%1$s(\"%2$s\")", CodeNamer.toPascalCase(restAPIMethod.getHttpMethod().toString().toLowerCase()), restAPIMethod.getUrlPath())); + if (!restAPIMethod.getResponseExpectedStatusCodes().isEmpty()) { + interfaceBlock.annotation(String.format("ExpectedResponses({%1$s})", restAPIMethod.getResponseExpectedStatusCodes().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + } + } else { + interfaceBlock.annotation("HttpRequestInformation(method = HttpMethod." + restAPIMethod.getHttpMethod().toString() + + ", path = \"" + restAPIMethod.getUrlPath() + + "\", expectedStatusCodes = { " + restAPIMethod.getResponseExpectedStatusCodes().stream().map(String::valueOf).collect(Collectors.joining(", ")) + " })"); } if (!settings.isDataPlaneClient()) { @@ -153,14 +162,26 @@ public final void write(Proxy restAPI, JavaClass classBlock) { } protected void writeUnexpectedExceptions(ProxyMethod restAPIMethod, JavaInterface interfaceBlock) { - for (Map.Entry> exception : restAPIMethod.getUnexpectedResponseExceptionTypes().entrySet()) { - interfaceBlock.annotation(String.format("UnexpectedResponseExceptionType(value = %1$s.class, code = {%2$s})", - exception.getKey(), exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + if (JavaSettings.getInstance().isBranded()) { + for (Map.Entry> exception : restAPIMethod.getUnexpectedResponseExceptionTypes().entrySet()) { + interfaceBlock.annotation(String.format("UnexpectedResponseExceptionType(value = %1$s.class, code = {%2$s})", + exception.getKey(), exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(", ")))); + } + } else { + for (Map.Entry> exception : restAPIMethod.getUnexpectedResponseExceptionTypes().entrySet()) { + interfaceBlock.annotation("UnexpectedResponseExceptionInformation(exceptionTypeName = \"" + + restAPIMethod.getHttpExceptionType(exception.getKey()).toString() + + "\", statusCode = {" + exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(",")) + " })"); + } } } protected void writeSingleUnexpectedException(ProxyMethod restAPIMethod, JavaInterface interfaceBlock) { - interfaceBlock.annotation(String.format("UnexpectedResponseExceptionType(%1$s.class)", restAPIMethod.getUnexpectedResponseExceptionType())); + if(JavaSettings.getInstance().isBranded()) { + interfaceBlock.annotation(String.format("UnexpectedResponseExceptionType(%1$s.class)", restAPIMethod.getUnexpectedResponseExceptionType())); + } else { + interfaceBlock.annotation("UnexpectedResponseExceptionInformation"); + } } protected void writeProxyMethodSignature(java.util.ArrayList parameterDeclarationList, ProxyMethod restAPIMethod, JavaInterface interfaceBlock) { diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceAsyncClientTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceAsyncClientTemplate.java index 0bdee68b72..43b7af9266 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceAsyncClientTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceAsyncClientTemplate.java @@ -141,7 +141,11 @@ protected void addServiceClientAnnotationImports(Set imports) { } protected void addGeneratedAnnotation(JavaContext classBlock) { - classBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + classBlock.annotation(Annotation.GENERATED.getName()); + } else { + classBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } /** diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java index 9bd9ff5197..eb6aa9c418 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java @@ -547,10 +547,15 @@ protected String primaryBuildMethodName(JavaSettings settings) { protected void addGeneratedImport(Set imports) { Annotation.GENERATED.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); } protected void addGeneratedAnnotation(JavaContext classBlock) { - classBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + classBlock.annotation(Annotation.GENERATED.getName()); + } else { + classBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } protected void addOverrideAnnotation(JavaContext classBlock) { diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java index 2ab880d250..d2047642c3 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java @@ -200,8 +200,18 @@ public final void write(ServiceClient serviceClient, JavaFile javaFile) { { if (!settings.isBranded()) { if (constructor.getParameters().equals(Arrays.asList(serviceClient.getHttpPipelineParameter()))) { + constructorBlock.line("this.httpPipeline = httpPipeline;"); + for (ServiceClientProperty serviceClientProperty : serviceClient.getProperties().stream().filter(ServiceClientProperty::isReadOnly).collect(Collectors.toList())) { + if (serviceClientProperty.getDefaultValueExpression() != null) { + constructorBlock.line("this.%s = %s;", serviceClientProperty.getName(), serviceClientProperty.getDefaultValueExpression()); + } + } + + for (MethodGroupClient methodGroupClient : serviceClient.getMethodGroupClients()) { + constructorBlock.line("this.%s = new %s(this);", methodGroupClient.getVariableName(), methodGroupClient.getClassName()); + } + if (serviceClient.getProxy() != null) { - constructorBlock.line("this.httpPipeline = httpPipeline;"); TemplateHelper.createRestProxyInstance(this, serviceClient, constructorBlock); } } @@ -278,7 +288,10 @@ public final void write(ServiceClient serviceClient, JavaFile javaFile) { } protected String getSerializerPhrase() { - return "this.getSerializerAdapter()"; + if (JavaSettings.getInstance().isBranded()) { + return "this.getSerializerAdapter()"; + } + return "RestProxyUtils.createDefaultSerializer()"; } protected void writeSerializerMemberInitialization(JavaBlock constructorBlock) { diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceSyncClientTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceSyncClientTemplate.java index 9f3d86ae9a..e26b152575 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceSyncClientTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceSyncClientTemplate.java @@ -171,10 +171,15 @@ protected void writeMethod(ClientMethod clientMethod, JavaClass classBlock) { protected void addServiceClientAnnotationImport(Set imports) { Annotation.SERVICE_CLIENT.addImportsTo(imports); Annotation.GENERATED.addImportsTo(imports); + Annotation.METADATA.addImportsTo(imports); } protected void addGeneratedAnnotation(JavaContext classBlock) { - classBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + classBlock.annotation(Annotation.GENERATED.getName()); + } else { + classBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } private void writeConvenienceMethods(List convenienceMethods, JavaClass classBlock) { diff --git a/javagen/src/main/java/com/azure/autorest/template/WrapperClientMethodTemplate.java b/javagen/src/main/java/com/azure/autorest/template/WrapperClientMethodTemplate.java index b37e492e28..fdff854849 100644 --- a/javagen/src/main/java/com/azure/autorest/template/WrapperClientMethodTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/WrapperClientMethodTemplate.java @@ -124,6 +124,10 @@ protected void generateJavadoc(ClientMethod clientMethod, JavaType typeBlock, Pr } protected void addGeneratedAnnotation(JavaType typeBlock) { - typeBlock.annotation(Annotation.GENERATED.getName()); + if (JavaSettings.getInstance().isBranded()) { + typeBlock.annotation(Annotation.GENERATED.getName()); + } else { + typeBlock.annotation(Annotation.METADATA.getName() + "(generated = true)"); + } } } 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 2a64977737..9e6cc56960 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java @@ -56,6 +56,7 @@ public class ClientModelUtil { public static final String FILENAME_SUFFIX = "Filename"; public static final String MULTI_PART_FORM_DATA_HELPER_CLASS_NAME = "MultipartFormDataHelper"; + public static final String GENERIC_MULTI_PART_FORM_DATA_HELPER_CLASS_NAME = "GenericMultipartFormDataHelper"; public static final String CORE_TO_CODEGEN_BRIDGE_UTILS_CLASS_NAME = "CoreToCodegenBridgeUtils"; diff --git a/javagen/src/main/resources/GenericMultipartFormDataHelper.java b/javagen/src/main/resources/GenericMultipartFormDataHelper.java new file mode 100644 index 0000000000..fe8180cc3f --- /dev/null +++ b/javagen/src/main/resources/GenericMultipartFormDataHelper.java @@ -0,0 +1,163 @@ +import com.generic.core.models.HeaderName; +import com.generic.core.http.models.RequestOptions; +import com.generic.core.models.BinaryData; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +// DO NOT modify this helper class + +public final class MultipartFormDataHelper { + /** + * Line separator for the multipart HTTP request. + */ + private static final String CRLF = "\r\n"; + + /** + * Value to be used as part of the divider for the multipart requests. + */ + private final String boundary; + + /** + * The actual part separator in the request. This is obtained by prepending "--" to the "boundary". + */ + private final String partSeparator; + + /** + * The marker for the ending of a multipart request. This is obtained by post-pending "--" to the "partSeparator". + */ + private final String endMarker; + + /** + * Charset used for encoding the multipart HTTP request. + */ + private final Charset encoderCharset = StandardCharsets.UTF_8; + + private InputStream requestDataStream = new ByteArrayInputStream(new byte[0]); + private long requestLength = 0; + + private RequestOptions requestOptions; + private BinaryData requestBody; + + /** + * Default constructor used in the code. The boundary is a random value. + * + * @param requestOptions the RequestOptions to update + */ + public MultipartFormDataHelper(RequestOptions requestOptions) { + this(requestOptions, UUID.randomUUID().toString().substring(0, 16)); + } + + private MultipartFormDataHelper(RequestOptions requestOptions, String boundary) { + this.requestOptions = requestOptions; + this.boundary = boundary; + this.partSeparator = "--" + boundary; + this.endMarker = this.partSeparator + "--"; + } + + /** + * Gets the multipart HTTP request body. + * + * @return the BinaryData of the multipart HTTP request body + */ + public BinaryData getRequestBody() { + return requestBody; + } + + // text/plain + /** + * Formats a text/plain field for a multipart HTTP request. + * + * @param fieldName the field name + * @param value the value of the text/plain field + * @return the MultipartFormDataHelper instance + */ + public MultipartFormDataHelper serializeTextField(String fieldName, String value) { + if (value != null) { + String serialized = partSeparator + + CRLF + "Content-Disposition: form-data; name=\"" + + fieldName + "\"" + CRLF + CRLF + + value + + CRLF; + byte[] data = serialized.getBytes(encoderCharset); + appendBytes(data); + } + return this; + } + + // application/json + /** + * Formats a application/json field for a multipart HTTP request. + * + * @param fieldName the field name + * @param jsonObject the object of the application/json field + * @return the MultipartFormDataHelper instance + */ + public MultipartFormDataHelper serializeJsonField(String fieldName, Object jsonObject) { + if (jsonObject != null) { + String serialized = partSeparator + CRLF + "Content-Disposition: form-data; name=\"" + fieldName + "\"" + + CRLF + "Content-Type: application/json" + + CRLF + CRLF + BinaryData.fromObject(jsonObject) + CRLF; + byte[] data = serialized.getBytes(encoderCharset); + appendBytes(data); + } + return this; + } + + // application/octet-stream + /** + * Formats a application/octet-stream field for a multipart HTTP request. + * + * @param fieldName the field name + * @param file the BinaryData of the file + * @param filename the filename + * @return the MultipartFormDataHelper instance + */ + public MultipartFormDataHelper serializeFileField(String fieldName, BinaryData file, String filename) { + if (file != null) { + // Multipart preamble + String fileFieldPreamble = partSeparator + + CRLF + "Content-Disposition: form-data; name=\"" + fieldName + + "\"; filename=\"" + filename + "\"" + + CRLF + "Content-Type: application/octet-stream" + CRLF + CRLF; + byte[] data = fileFieldPreamble.getBytes(encoderCharset); + appendBytes(data); + + // Writing the file into the request as a byte stream + requestLength += file.getLength(); + requestDataStream = new SequenceInputStream(requestDataStream, file.toStream()); + + // CRLF + data = CRLF.getBytes(encoderCharset); + appendBytes(data); + } + return this; + } + + /** + * Ends the serialization of the multipart HTTP request. + * + * @return the MultipartFormDataHelper instance + */ + public MultipartFormDataHelper end() { + byte[] data = endMarker.getBytes(encoderCharset); + appendBytes(data); + + requestBody = BinaryData.fromStream(requestDataStream, requestLength); + + requestOptions + .setHeader(HeaderName.CONTENT_TYPE, "multipart/form-data; boundary=" + this.boundary) + .setHeader(HeaderName.CONTENT_LENGTH, String.valueOf(requestLength)); + + return this; + } + + private void appendBytes(byte[] bytes) { + requestLength += bytes.length; + requestDataStream = new SequenceInputStream(requestDataStream, new ByteArrayInputStream(bytes)); + } +} 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 89ef77b221..220669d8d5 100644 --- a/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java +++ b/typespec-extension/src/main/java/com/azure/autorest/TypeSpecPlugin.java @@ -161,7 +161,13 @@ protected void writeHelperClasses(Client client, JavaPackage javaPackage, JavaSe .filter(ModelUtil::isGeneratingModel) .anyMatch(m -> m.getImplementationDetails() != null && m.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.MULTIPART_FORM_DATA)); if (generateMultipartFormDataHelper) { - javaPackage.addJavaFromResources(settings.getPackage(settings.getImplementationSubpackage()), ClientModelUtil.MULTI_PART_FORM_DATA_HELPER_CLASS_NAME); + if (JavaSettings.getInstance().isBranded()) { + javaPackage.addJavaFromResources(settings.getPackage(settings.getImplementationSubpackage()), ClientModelUtil.MULTI_PART_FORM_DATA_HELPER_CLASS_NAME); + } else { + javaPackage.addJavaFromResources(settings.getPackage(settings.getImplementationSubpackage()), + ClientModelUtil.GENERIC_MULTI_PART_FORM_DATA_HELPER_CLASS_NAME, + ClientModelUtil.MULTI_PART_FORM_DATA_HELPER_CLASS_NAME); + } } } From ef920edb73a94a922d42726219e39d20302e9c07 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Tue, 5 Mar 2024 23:59:05 -0800 Subject: [PATCH 02/10] latest updates from generic core --- .../azure/autorest/mapper/ClientMapper.java | 18 ++-- .../autorest/model/clientmodel/ClassType.java | 63 ++++--------- .../model/clientmodel/ClientBuilderTrait.java | 64 ++++++++++--- .../model/clientmodel/ClientMethod.java | 2 +- .../template/ClientMethodTemplate.java | 37 +++++--- .../ConvenienceMethodTemplateBase.java | 2 +- .../ServiceClientBuilderTemplate.java | 14 ++- .../template/ServiceClientTemplate.java | 5 +- .../StreamSerializationModelTemplate.java | 4 + .../com/azure/autorest/util/TemplateUtil.java | 7 +- .../GenericMultipartFormDataHelper.java | 91 +++++++++++++++---- typespec-extension/src/code-model-builder.ts | 12 ++- 12 files changed, 202 insertions(+), 117 deletions(-) diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java index 3cb0ecb305..dac0e0394f 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java @@ -3,6 +3,7 @@ package com.azure.autorest.mapper; +import com.azure.autorest.Javagen; import com.azure.autorest.extension.base.model.codemodel.ArraySchema; import com.azure.autorest.extension.base.model.codemodel.ChoiceSchema; import com.azure.autorest.extension.base.model.codemodel.CodeModel; @@ -458,27 +459,24 @@ protected Map { + Javagen.getPluginInstance().getLogger().info("Client property name " + property.getName()); + return property; + }) .filter(property -> property.getName().equals("endpoint")) .findFirst() .ifPresent(property -> clientBuilder.addBuilderTrait(ClientBuilderTrait.getEndpointTrait(property))); @@ -611,7 +609,7 @@ private static ModuleInfo getModuleInfo(List modelsPackages) { List requireModules = moduleInfo.getRequireModules(); requireModules.add(new ModuleInfo.RequireModule(ExternalPackage.CORE.getPackageName(), true)); if (settings.isStreamStyleSerialization()) { - requireModules.add(new ModuleInfo.RequireModule(ExternalPackage.JSON.getPackageName(), false)); + requireModules.add(new ModuleInfo.RequireModule(ExternalPackage.JSON.getPackageName(), true)); } List exportModules = moduleInfo.getExportModules(); diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java index c9b190945f..9845ddb057 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClassType.java @@ -7,6 +7,9 @@ import com.azure.autorest.extension.base.plugin.JavaSettings; import com.azure.autorest.util.ClientModelUtil; import com.azure.autorest.util.TemplateUtil; +import com.azure.core.client.traits.ConfigurationTrait; +import com.azure.core.client.traits.EndpointTrait; +import com.azure.core.client.traits.HttpTrait; import com.azure.core.client.traits.KeyCredentialTrait; import com.azure.core.credential.AzureKeyCredential; import com.azure.core.credential.KeyCredential; @@ -46,9 +49,11 @@ import com.azure.core.util.DateTimeRfc1123; import com.azure.core.util.ExpandableStringEnum; import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.logging.LogLevel; import com.azure.core.util.polling.PollOperationDetails; import com.azure.core.util.serializer.JsonSerializer; import com.azure.core.util.serializer.SerializerAdapter; +import com.azure.core.util.serializer.TypeReference; import com.azure.json.JsonReader; import com.azure.json.JsonSerializable; import com.azure.json.JsonToken; @@ -75,48 +80,6 @@ */ public class ClassType implements IType { -// private static class ClassDetails { -// -// private final Class azureClass; -// private final Class genericClass; -// -// public ClassDetails(Class azureClass, Class genericClass) { -// this.azureClass = azureClass; -// this.genericClass = genericClass; -// } -// -// public Class getAzureClass() { -// return azureClass; -// } -// -// public Class getGenericClass() { -// return genericClass; -// } -// -// } -// -// private static final Map, ClassDetails> CLASS_TYPE_MAPPING = new HashMap, ClassDetails>() {{ -// put(com.azure.core.http.rest.RestProxy.class, new ClassDetails(com.azure.core.http.rest.RestProxy.class, com.generic.core.http.RestProxy.class)); -// put(com.azure.core.http.HttpPipeline.class, new ClassDetails(com.azure.core.http.HttpPipeline.class, com.generic.core.http.pipeline.HttpPipeline.class)); -// put(com.azure.core.http.HttpPipelineBuilder.class, new ClassDetails(com.azure.core.http.HttpPipelineBuilder.class, com.generic.core.http.pipeline.HttpPipelineBuilder.class)); -// put(com.azure.core.util.Context.class, new ClassDetails(com.azure.core.util.Context.class, com.generic.core.models.Context.class)); -// put(com.azure.core.http.HttpClient.class, new ClassDetails(com.azure.core.http.HttpClient.class, com.generic.core.http.client.HttpClient.class)); -// put(com.azure.core.http.policy.HttpLogOptions.class, new ClassDetails(com.azure.core.http.policy.HttpLogOptions.class, com.generic.core.http.policy.logging.HttpLogOptions.class)); -// put(com.azure.core.http.policy.HttpPipelinePolicy.class, new ClassDetails(com.azure.core.http.policy.HttpPipelinePolicy.class, com.generic.core.http.pipeline.HttpPipelinePolicy.class)); -// put(com.azure.core.http.policy.KeyCredentialPolicy.class, new ClassDetails(com.azure.core.http.policy.KeyCredentialPolicy.class, com.generic.core.http.policy.credential.KeyCredentialPolicy.class)); -// put(com.azure.core.util.Configuration.class, new ClassDetails(com.azure.core.util.Configuration.class, com.generic.core.util.configuration.Configuration.class)); -// put(com.azure.core.http.HttpHeaders.class, new ClassDetails(com.azure.core.http.HttpHeaders.class, com.generic.core.models.Headers.class)); -// put(com.azure.core.http.HttpHeaderName.class, new ClassDetails(com.azure.core.http.HttpHeaderName.class, com.generic.core.http.models.HttpHeaderName.class)); -// put(com.azure.core.http.HttpRequest.class, new ClassDetails(com.azure.core.http.HttpRequest.class, com.generic.core.http.models.HttpRequest.class)); -// // TODO: generic not having ClientOptions -//// put(com.azure.core.util.ClientOptions.class, new ClassDetails(com.azure.core.util.ClientOptions.class, com.generic.core.models.ClientOptions.class)); -// put(com.azure.core.http.rest.RequestOptions.class, new ClassDetails(com.azure.core.http.rest.RequestOptions.class, com.generic.core.models.RequestOptions.class)); -// put(com.azure.core.util.BinaryData.class, new ClassDetails(com.azure.core.util.BinaryData.class, com.generic.core.models.BinaryData.class)); -// put(com.azure.core.http.policy.RetryOptions.class, new ClassDetails(com.azure.core.http.policy.RetryOptions.class, com.generic.core.http.policy.retry.RetryOptions.class)); -// put(com.azure.core.http.rest.Response.class, new ClassDetails(com.azure.core.http.rest.Response.class, com.generic.core.http.Response.class)); -// put(com.azure.core.http.rest.SimpleResponse.class, new ClassDetails(com.azure.core.http.rest.SimpleResponse.class, com.generic.core.http.SimpleResponse.class)); -// put(com.azure.core.util.ExpandableStringEnum.class, new ClassDetails(com.azure.core.util.ExpandableStringEnum.class, com.generic.core.models.ExpandableStringEnum.class)); -// }}; private static class ClassDetails { @@ -144,7 +107,7 @@ public String getGenericClass() { put(HttpPipelineBuilder.class, new ClassDetails(HttpPipelineBuilder.class, "com.generic.core.http.pipeline.HttpPipelineBuilder")); put(Context.class, new ClassDetails(Context.class, "com.generic.core.models.Context")); put(HttpClient.class, new ClassDetails(HttpClient.class, "com.generic.core.http.client.HttpClient")); - put(HttpLogOptions.class, new ClassDetails(HttpLogOptions.class, "com.generic.core.http.policy.logging.HttpLogOptions")); + put(HttpLogOptions.class, new ClassDetails(HttpLogOptions.class, "com.generic.core.http.policy.HttpLoggingPolicy.HttpLogOptions")); put(HttpPipelinePolicy.class, new ClassDetails(HttpPipelinePolicy.class, "com.generic.core.http.pipeline.HttpPipelinePolicy")); put(KeyCredentialPolicy.class, new ClassDetails(KeyCredentialPolicy.class, "com.generic.core.http.policy.KeyCredentialPolicy")); put(Configuration.class, new ClassDetails(Configuration.class, "com.generic.core.util.configuration.Configuration")); @@ -153,11 +116,18 @@ public String getGenericClass() { put(HttpRequest.class, new ClassDetails(HttpRequest.class, "com.generic.core.http.models.HttpRequest")); put(RequestOptions.class, new ClassDetails(RequestOptions.class, "com.generic.core.http.models.RequestOptions")); put(BinaryData.class, new ClassDetails(BinaryData.class, "com.generic.core.models.BinaryData")); - put(RetryOptions.class, new ClassDetails(RetryOptions.class, "com.generic.core.http.policy.retry.RetryOptions")); + put(RetryOptions.class, new ClassDetails(RetryOptions.class, "com.generic.core.http.models.RetryOptions")); put(Response.class, new ClassDetails(Response.class, "com.generic.core.http.Response")); put(SimpleResponse.class, new ClassDetails(SimpleResponse.class, "com.generic.core.http.SimpleResponse")); put(ExpandableStringEnum.class, new ClassDetails(ExpandableStringEnum.class, "com.generic.core.models.ExpandableStringEnum")); put(HttpResponseException.class, new ClassDetails(HttpResponseException.class, "com.generic.core.http.exception.HttpResponseException")); + put(HttpTrait.class, new ClassDetails(HttpTrait.class, "com.generic.core.models.traits.HttpTrait")); + put(ConfigurationTrait.class, new ClassDetails(ConfigurationTrait.class, "com.generic.core.models.traits.ConfigurationTrait")); + put(EndpointTrait.class, new ClassDetails(EndpointTrait.class, "com.generic.core.models.traits.EndpointTrait")); + put(KeyCredentialTrait.class, new ClassDetails(KeyCredentialTrait.class, "com.generic.core.models.traits.KeyCredentialTrait")); + put(TypeReference.class, new ClassDetails(TypeReference.class, "com.generic.core.models.TypeReference")); + put(ClientLogger.class, new ClassDetails(ClientLogger.class, "com.generic.core.util.ClientLogger")); + put(LogLevel.class, new ClassDetails(LogLevel.class, "com.generic.core.util.ClientLogger.LogLevel")); }}; private static ClassType.Builder getClassTypeBuilder(Class classKey) { @@ -417,6 +387,7 @@ private static ClassType.Builder getClassTypeBuilder(Class classKey) { .build(); public static final ClassType CLIENT_LOGGER = ClassType.getClassTypeBuilder(ClientLogger.class).build(); + public static final ClassType LOG_LEVEL = ClassType.getClassTypeBuilder(LogLevel.class).build(); public static final ClassType AZURE_ENVIRONMENT = new ClassType.Builder(false) .packageName("com.azure.core.management").name("AzureEnvironment") @@ -509,11 +480,15 @@ private static ClassType.Builder getClassTypeBuilder(Class classKey) { public static final ClassType HTTP_PIPELINE_BUILDER = getClassTypeBuilder(HttpPipelineBuilder.class).build(); public static final ClassType KEY_CREDENTIAL_POLICY = getClassTypeBuilder(KeyCredentialPolicy.class).build(); public static final ClassType KEY_CREDENTIAL_TRAIT = getClassTypeBuilder(KeyCredentialTrait.class).build(); + public static final ClassType ENDPOINT_TRAIT = getClassTypeBuilder(EndpointTrait.class).build(); + public static final ClassType HTTP_TRAIT = getClassTypeBuilder(HttpTrait.class).build(); + public static final ClassType CONFIGURATION_TRAIT = getClassTypeBuilder(ConfigurationTrait.class).build(); public static final ClassType POLL_OPERATION_DETAILS = getClassTypeBuilder(PollOperationDetails.class).build(); public static final ClassType JSON_SERIALIZABLE = getClassTypeBuilder(JsonSerializable.class).build(); public static final ClassType JSON_WRITER = getClassTypeBuilder(JsonWriter.class).build(); public static final ClassType JSON_READER = getClassTypeBuilder(JsonReader.class).build(); public static final ClassType JSON_TOKEN = getClassTypeBuilder(JsonToken.class).build(); + public static final ClassType TYPE_REFERENCE = getClassTypeBuilder(TypeReference.class).build(); private final String fullName; private final String packageName; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java index 6c84b559c1..bcf5fe37d1 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java @@ -13,6 +13,7 @@ import com.azure.core.client.traits.TokenCredentialTrait; import com.azure.core.credential.AzureKeyCredential; import com.azure.core.credential.TokenCredential; +import com.azure.core.util.logging.LogLevel; import java.util.ArrayList; import java.util.List; @@ -92,8 +93,7 @@ private static ClientBuilderTrait createHttpTrait() { httpTrait.setTraitInterfaceName("HttpTrait"); List importPackages = new ArrayList<>(); httpTrait.setImportPackages(importPackages); - importPackages.add(HttpTrait.class.getName()); - + importPackages.add(ClassType.HTTP_TRAIT.getFullName()); List httpClientBuilderTraitMethods = new ArrayList<>(); httpTrait.setTraitMethods(httpClientBuilderTraitMethods); @@ -103,11 +103,12 @@ private static ClientBuilderTrait createHttpTrait() { JavaSettings.getInstance().isAzureOrFluent() ? "new HttpPipelineBuilder().policies(new UserAgentPolicy(), new RetryPolicy()).build()" : "createHttpPipeline()"); + importPackages.add(ClassType.LOG_LEVEL.getFullName()); Consumer pipelineMethodImpl = function -> { final String pipelineVarName = "pipeline"; if (JavaSettings.getInstance().isUseClientLogger()) { function.ifBlock(String.format("this.%1$s != null && %1$s == null", pipelineVarName), ifBlock -> { - function.line("LOGGER.info(\"HttpPipeline is being set to 'null' when it was previously configured.\");"); + function.line(addLogging(LogLevel.INFORMATIONAL, "HttpPipeline is being set to 'null' when it was previously configured.")); }); } function.line(String.format("this.%1$s = %2$s;", pipelineVarName, pipelineVarName)); @@ -147,17 +148,19 @@ private static ClientBuilderTrait createHttpTrait() { httpClientBuilderTraitMethods.add(httpLogOptionsMethod); // clientOptions - ServiceClientProperty clientOptionsProperty = new ServiceClientProperty("The client options such as application ID and custom headers to set on a request.", - ClassType.CLIENT_OPTIONS, "clientOptions", false, null); - Consumer clientOptionsMethodImpl = function -> { - function.line(String.format("this.%1$s = %2$s;", "clientOptions", "clientOptions")); - function.methodReturn("this"); - }; - ClientBuilderTraitMethod clientOptionsMethod = createTraitMethod("clientOptions", "clientOptions", ClassType.CLIENT_OPTIONS, - clientOptionsProperty, "{@inheritDoc}", clientOptionsMethodImpl); - importPackages.add(ClassType.CLIENT_OPTIONS.getFullName()); + if (JavaSettings.getInstance().isBranded()) { + ServiceClientProperty clientOptionsProperty = new ServiceClientProperty("The client options such as application ID and custom headers to set on a request.", + ClassType.CLIENT_OPTIONS, "clientOptions", false, null); + Consumer clientOptionsMethodImpl = function -> { + function.line(String.format("this.%1$s = %2$s;", "clientOptions", "clientOptions")); + function.methodReturn("this"); + }; + ClientBuilderTraitMethod clientOptionsMethod = createTraitMethod("clientOptions", "clientOptions", ClassType.CLIENT_OPTIONS, + clientOptionsProperty, "{@inheritDoc}", clientOptionsMethodImpl); + importPackages.add(ClassType.CLIENT_OPTIONS.getFullName()); - httpClientBuilderTraitMethods.add(clientOptionsMethod); + httpClientBuilderTraitMethods.add(clientOptionsMethod); + } // retryOptions ServiceClientProperty retryOptionsProperty = @@ -186,12 +189,43 @@ private static ClientBuilderTrait createHttpTrait() { return httpTrait; } + private static String addLogging(LogLevel level, String message) { + + if (JavaSettings.getInstance().isBranded()) { + switch (level) { + case VERBOSE: + return String.format("LOGGER.verbose(\"%s\");", message); + case INFORMATIONAL: + return String.format("LOGGER.info(\"%s\");", message); + case WARNING: + return String.format("LOGGER.warning(\"%s\");", message); + case ERROR: + return String.format("LOGGER.error(\"%s\");", message); + default: + return String.format("LOGGER.info(\"%s\");", message); + } + } else { + switch (level) { + case VERBOSE: + return String.format("LOGGER.log(LogLevel.VERBOSE, () -> \"%s\");", message); + case INFORMATIONAL: + return String.format("LOGGER.log(LogLevel.INFORMATIONAL, () -> \"%s\");", message); + case WARNING: + return String.format("LOGGER.log(LogLevel.WARNING, () -> \"%s\");", message); + case ERROR: + return String.format("LOGGER.log(LogLevel.ERROR, () -> \"%s\");", message); + default: + return String.format("LOGGER.log(LogLevel.INFORMATIONAL, () -> \"%s\");", message); + } + } + } + private static ClientBuilderTrait createConfigurationTrait() { ClientBuilderTrait configurationTrait = new ClientBuilderTrait(); configurationTrait.setTraitInterfaceName("ConfigurationTrait"); List importPackages = new ArrayList<>(); configurationTrait.setImportPackages(importPackages); - importPackages.add(ConfigurationTrait.class.getName()); + importPackages.add(ClassType.CONFIGURATION_TRAIT.getFullName()); List configurationClientBuilderTraitMethods = new ArrayList<>(); configurationTrait.setTraitMethods(configurationClientBuilderTraitMethods); @@ -221,7 +255,7 @@ public static ClientBuilderTrait getEndpointTrait(ServiceClientProperty property List importPackages = new ArrayList<>(); endpointTrait.setImportPackages(importPackages); - importPackages.add(EndpointTrait.class.getName()); + importPackages.add(ClassType.ENDPOINT_TRAIT.getFullName()); List endpointClientBuilderTraitMethods = new ArrayList<>(); endpointTrait.setTraitMethods(endpointClientBuilderTraitMethods); diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientMethod.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientMethod.java index 4a41d47e62..8e5cafa37e 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientMethod.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientMethod.java @@ -417,7 +417,7 @@ public void addImportsTo(Set imports, boolean includeImplementationImpor imports.add("com.fasterxml.jackson.core.type.TypeReference"); } } else { - imports.add("com.azure.core.util.serializer.TypeReference"); + imports.add(ClassType.TYPE_REFERENCE.getFullName()); imports.add("java.time.Duration"); imports.add(PollingStrategyOptions.class.getName()); diff --git a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java index f892838750..d0e2c9caa9 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java @@ -32,6 +32,7 @@ import com.azure.autorest.util.MethodNamer; import com.azure.autorest.util.MethodUtil; import com.azure.autorest.util.TemplateUtil; +import com.azure.core.annotation.ReturnType; import com.azure.core.http.HttpHeaderName; import com.azure.core.util.CoreUtils; import com.azure.core.util.serializer.CollectionFormat; @@ -669,7 +670,7 @@ protected void generateProtocolPagingSync(ClientMethod clientMethod, JavaType ty } protected void generateProtocolPagingPlainSync(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.COLLECTION)"); + addServiceMethodAnnotation(typeBlock, ReturnType.COLLECTION); if (clientMethod.getMethodPageDetails().nonNullNextLink()) { writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addOptionalVariables(function, clientMethod); @@ -723,7 +724,7 @@ protected void generateProtocolPagingSinglePage(ClientMethod clientMethod, JavaT } private void generatePagedSinglePage(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { if (!settings.isSyncStackEnabled()) { @@ -775,7 +776,7 @@ private void generatePagedSinglePage(ClientMethod clientMethod, JavaType typeBlo protected void generatePagingSync(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.COLLECTION)"); + addServiceMethodAnnotation(typeBlock, ReturnType.COLLECTION); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addOptionalVariables(function, clientMethod); function.methodReturn(String.format("new PagedIterable<>(%s(%s))", clientMethod.getProxyMethod().getSimpleAsyncMethodName(), clientMethod.getArgumentList())); @@ -783,7 +784,7 @@ protected void generatePagingSync(ClientMethod clientMethod, JavaType typeBlock, } protected void generatePagingPlainSync(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.COLLECTION)"); + addServiceMethodAnnotation(typeBlock, ReturnType.COLLECTION); if (clientMethod.getMethodPageDetails().nonNullNextLink()) { writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addOptionalVariables(function, clientMethod); @@ -850,7 +851,7 @@ protected void generatePagingPlainSync(ClientMethod clientMethod, JavaType typeB } protected void generatePagingAsync(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.COLLECTION)"); + addServiceMethodAnnotation(typeBlock, ReturnType.COLLECTION); if (clientMethod.getMethodPageDetails().nonNullNextLink()) { writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addOptionalVariables(function, clientMethod); @@ -887,8 +888,14 @@ protected void generatePagingAsync(ClientMethod clientMethod, JavaType typeBlock } } + private static void addServiceMethodAnnotation(JavaType typeBlock, ReturnType returnType) { + if (JavaSettings.getInstance().isBranded()) { + typeBlock.annotation("ServiceMethod(returns = ReturnType." + returnType.name() + ");"); + } + } + protected void generateResumable(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); typeBlock.publicMethod(clientMethod.getDeclaration(), function -> { ProxyMethodParameter parameter = restAPIMethod.getParameters().get(0); addValidations(function, clientMethod.getRequiredNullableParameterExpressions(), clientMethod.getValidateExpressions(), settings); @@ -897,7 +904,7 @@ protected void generateResumable(ClientMethod clientMethod, JavaType typeBlock, } protected void generateSimpleAsync(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), (function -> { addOptionalVariables(function, clientMethod); function.line("return %s(%s)", clientMethod.getProxyMethod().getSimpleAsyncRestResponseMethodName(), clientMethod.getArgumentList()); @@ -918,7 +925,7 @@ protected void generateSimpleAsync(ClientMethod clientMethod, JavaType typeBlock } private void generateSimpleSyncMethod(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), (function -> { addOptionalVariables(function, clientMethod); @@ -948,7 +955,7 @@ private void generateSimpleSyncMethod(ClientMethod clientMethod, JavaType typeBl private void generateSimplePlainSyncMethod(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), (function -> { addOptionalVariables(function, clientMethod); @@ -980,7 +987,7 @@ protected void generateSyncMethod(ClientMethod clientMethod, JavaType typeBlock, asyncMethodName = clientMethod.getProxyMethod().getSimpleAsyncRestResponseMethodName(); } String effectiveAsyncMethodName = asyncMethodName; - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addOptionalVariables(function, clientMethod); if (clientMethod.getReturnValue().getType() == ClassType.INPUT_STREAM) { @@ -1044,7 +1051,7 @@ protected void generateSyncMethod(ClientMethod clientMethod, JavaType typeBlock, protected void generatePlainSyncMethod(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { String effectiveProxyMethodName = clientMethod.getProxyMethod().getName(); - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addValidations(function, clientMethod.getRequiredNullableParameterExpressions(), clientMethod.getValidateExpressions(), settings); @@ -1144,7 +1151,7 @@ protected static String parameterDescriptionOrDefault(ClientMethodParameter para } protected void generatePagedAsyncSinglePage(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addValidations(function, clientMethod.getRequiredNullableParameterExpressions(), clientMethod.getValidateExpressions(), settings); @@ -1282,7 +1289,7 @@ private static String checkAndReplaceParamNameCollision(ClientMethod clientMetho } protected void generateSimpleAsyncRestResponse(ClientMethod clientMethod, JavaType typeBlock, ProxyMethod restAPIMethod, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { addValidations(function, clientMethod.getRequiredNullableParameterExpressions(), clientMethod.getValidateExpressions(), settings); addOptionalAndConstantVariables(function, clientMethod, restAPIMethod.getParameters(), settings); @@ -1577,7 +1584,7 @@ private String getSyncPollingStrategy(ClientMethod clientMethod, String contextP } protected void generateSendRequestAsync(ClientMethod clientMethod, JavaType typeBlock, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { function.line("return FluxUtil.withContext(context -> %1$s.getHttpPipeline().send(%2$s, context)", clientMethod.getClientReference(), clientMethod.getArgumentList()); @@ -1589,7 +1596,7 @@ protected void generateSendRequestAsync(ClientMethod clientMethod, JavaType type } protected void generateSendRequestSync(ClientMethod clientMethod, JavaType typeBlock, JavaSettings settings) { - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + addServiceMethodAnnotation(typeBlock, ReturnType.SINGLE); writeMethod(typeBlock, clientMethod.getMethodVisibility(), clientMethod.getDeclaration(), function -> { function.methodReturn("this.sendRequestAsync(httpRequest).contextWrite(c -> c.putAll(FluxUtil.toReactorContext(context).readOnly())).block()"); }); 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 dec8fdbbce..195d274831 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java @@ -339,7 +339,7 @@ protected void addImports(Set imports, List convenien // collection format imports.add(JacksonAdapter.class.getName()); imports.add(CollectionFormat.class.getName()); - imports.add(TypeReference.class.getName()); + ClassType.TYPE_REFERENCE.addImportsTo(imports, false); // byte[] ClassType.BASE_64_URL.addImportsTo(imports, false); diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java index 322e5e5f8f..1c6b866c73 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceClientBuilderTemplate.java @@ -135,7 +135,7 @@ public final void write(ClientBuilder clientBuilder, JavaFile javaFile) { javaFile.annotation(String.format("ServiceClientBuilder(serviceClients = %1$s)", builderTypes)); String classDefinition = serviceClientBuilderName; - if (!settings.isAzureOrFluent() && /* TODO: generic not having Trait */ settings.isBranded() && !CoreUtils.isNullOrEmpty(clientBuilder.getBuilderTraits())) { + if (!settings.isAzureOrFluent() && !CoreUtils.isNullOrEmpty(clientBuilder.getBuilderTraits())) { String serviceClientBuilderGeneric = "<" + serviceClientBuilderName + ">"; String interfaces = clientBuilder.getBuilderTraits().stream() @@ -184,9 +184,13 @@ public final void write(ClientBuilder clientBuilder, JavaFile javaFile) { javaBlock.line("this.pipelinePolicies = new ArrayList<>();"); }); } else { + addGeneratedAnnotation(classBlock); + classBlock.privateFinalMemberVariable("List", "pipelinePolicies"); + classBlock.javadocComment(String.format("Create an instance of the %s.", serviceClientBuilderName)); addGeneratedAnnotation(classBlock); classBlock.publicConstructor(String.format("%1$s()", serviceClientBuilderName), javaBlock -> { + javaBlock.line("this.pipelinePolicies = new ArrayList<>();"); }); } } @@ -294,7 +298,13 @@ public final void write(ClientBuilder clientBuilder, JavaFile javaFile) { } if (!settings.isBranded()) { - function.line(String.format("%1$s client = new %1$s(%2$s);", serviceClient.getClassName(), "this.createHttpPipeline()")); + if (constructorArgs != null && !constructorArgs.isEmpty()) { + function.line(String.format("%1$s client = new %2$s(%3$s%4$s);", + serviceClient.getClassName(), serviceClient.getClassName(), + getLocalBuildVariableName("pipeline"), constructorArgs)); + } else { + function.line(String.format("%1$s client = new %1$s(%2$s);", serviceClient.getClassName(), getLocalBuildVariableName("pipeline"))); + } } else if (settings.isFluent()) { function.line(String.format("%1$s client = new %2$s(%3$s, %4$s, %5$s, %6$s%7$s);", serviceClient.getClassName(), diff --git a/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java index d2047642c3..2d2deea164 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ServiceClientTemplate.java @@ -200,10 +200,11 @@ public final void write(ServiceClient serviceClient, JavaFile javaFile) { { if (!settings.isBranded()) { if (constructor.getParameters().equals(Arrays.asList(serviceClient.getHttpPipelineParameter()))) { - constructorBlock.line("this.httpPipeline = httpPipeline;"); - for (ServiceClientProperty serviceClientProperty : serviceClient.getProperties().stream().filter(ServiceClientProperty::isReadOnly).collect(Collectors.toList())) { + for (ServiceClientProperty serviceClientProperty : serviceClient.getProperties().stream().collect(Collectors.toList())) { if (serviceClientProperty.getDefaultValueExpression() != null) { constructorBlock.line("this.%s = %s;", serviceClientProperty.getName(), serviceClientProperty.getDefaultValueExpression()); + } else { + constructorBlock.line("this.%s = %s;", serviceClientProperty.getName(), serviceClientProperty.getName()); } } 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 3aa062c599..1762cdb268 100644 --- a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java @@ -505,6 +505,8 @@ private static void serializeJsonContainerProperty(JavaBlock methodBlock, String // becomes reality this will need to be reworked to handle that case. serializeJsonContainerProperty(methodBlock, "writeMap", elementType, ((MapType) elementType).getValueType(), serializedName, propertyValueGetter, depth + 1, isJsonMergePatch); + } else if (elementType == ClassType.BINARY_DATA) { + methodBlock.line(lambdaWriterName + ".writeUntyped(" + elementName + ")"); } else { throw new RuntimeException("Unknown value type " + elementType + " in " + containerType + " serialization. Need to add support for it."); @@ -1189,6 +1191,8 @@ private static void deserializeJsonContainerProperty(JavaBlock methodBlock, Stri deserializeJsonContainerProperty(methodBlock, "readMap", elementWireType, ((MapType) elementWireType).getValueType(), ((MapType) elementClientType).getValueType(), depth + 1); + } else if (elementWireType == ClassType.BINARY_DATA) { + methodBlock.line(lambdaReaderName + ".readUntyped()"); } else { throw new RuntimeException("Unknown value type " + elementWireType + " in " + containerType + " serialization. Need to add support for it."); diff --git a/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java b/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java index 50840b5d62..d3744b5603 100644 --- a/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java @@ -249,7 +249,9 @@ public static void writeClientMethodServiceMethodAnnotation(ClientMethod clientM typeBlock.annotation("ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)"); break; default: - typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + if (JavaSettings.getInstance().isBranded()) { + typeBlock.annotation("ServiceMethod(returns = ReturnType.SINGLE)"); + } break; } } @@ -290,8 +292,7 @@ private static void addJsonGetterOrJsonSetter(JavaClass classBlock, JavaSettings public static void addClientLogger(JavaClass classBlock, String className, JavaFileContents javaFileContents) { String content = javaFileContents.toString(); if (content.contains("throw LOGGER") - || content.contains("LOGGER.logThrowable") - || content.contains("LOGGER.logException") + || content.contains("LOGGER.log") || content.contains("LOGGER.info")) { // hack to add LOGGER class variable only if LOGGER is used in code classBlock.privateStaticFinalVariable(String.format("%1$s LOGGER = new ClientLogger(%2$s.class)", diff --git a/javagen/src/main/resources/GenericMultipartFormDataHelper.java b/javagen/src/main/resources/GenericMultipartFormDataHelper.java index fe8180cc3f..ccf2b6bc6f 100644 --- a/javagen/src/main/resources/GenericMultipartFormDataHelper.java +++ b/javagen/src/main/resources/GenericMultipartFormDataHelper.java @@ -7,6 +7,7 @@ import java.io.SequenceInputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.UUID; // DO NOT modify this helper class @@ -17,6 +18,8 @@ public final class MultipartFormDataHelper { */ private static final String CRLF = "\r\n"; + private static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + /** * Value to be used as part of the divider for the multipart requests. */ @@ -79,8 +82,8 @@ public BinaryData getRequestBody() { public MultipartFormDataHelper serializeTextField(String fieldName, String value) { if (value != null) { String serialized = partSeparator - + CRLF + "Content-Disposition: form-data; name=\"" - + fieldName + "\"" + CRLF + CRLF + + CRLF + "Content-Disposition: form-data; name=\"" + escapeName(fieldName) + "\"" + + CRLF + CRLF + value + CRLF; byte[] data = serialized.getBytes(encoderCharset); @@ -99,7 +102,8 @@ public MultipartFormDataHelper serializeTextField(String fieldName, String value */ public MultipartFormDataHelper serializeJsonField(String fieldName, Object jsonObject) { if (jsonObject != null) { - String serialized = partSeparator + CRLF + "Content-Disposition: form-data; name=\"" + fieldName + "\"" + String serialized = partSeparator + CRLF + + "Content-Disposition: form-data; name=\"" + escapeName(fieldName) + "\"" + CRLF + "Content-Type: application/json" + CRLF + CRLF + BinaryData.fromObject(jsonObject) + CRLF; byte[] data = serialized.getBytes(encoderCharset); @@ -108,32 +112,53 @@ public MultipartFormDataHelper serializeJsonField(String fieldName, Object jsonO return this; } - // application/octet-stream /** - * Formats a application/octet-stream field for a multipart HTTP request. + * Formats a file field for a multipart HTTP request. * * @param fieldName the field name * @param file the BinaryData of the file + * @param contentType the content-type of the file * @param filename the filename * @return the MultipartFormDataHelper instance */ - public MultipartFormDataHelper serializeFileField(String fieldName, BinaryData file, String filename) { + public MultipartFormDataHelper serializeFileField( + String fieldName, + BinaryData file, + String contentType, + String filename) { if (file != null) { - // Multipart preamble - String fileFieldPreamble = partSeparator - + CRLF + "Content-Disposition: form-data; name=\"" + fieldName - + "\"; filename=\"" + filename + "\"" - + CRLF + "Content-Type: application/octet-stream" + CRLF + CRLF; - byte[] data = fileFieldPreamble.getBytes(encoderCharset); - appendBytes(data); - - // Writing the file into the request as a byte stream - requestLength += file.getLength(); - requestDataStream = new SequenceInputStream(requestDataStream, file.toStream()); + if (contentType != null && !contentType.isEmpty()) { + contentType = APPLICATION_OCTET_STREAM; + } + writeFileField(fieldName, file, contentType, filename); + } + return this; + } - // CRLF - data = CRLF.getBytes(encoderCharset); - appendBytes(data); + /** + * Formats a file field (potentially multiple files) for a multipart HTTP request. + * + * @param fieldName the field name + * @param files the List of BinaryData of the files + * @param contentTypes the List of content-type of the files + * @param filenames the List of filenames + * @return the MultipartFormDataHelper instance + */ + public MultipartFormDataHelper serializeFileFields( + String fieldName, + List files, + List contentTypes, + List filenames) { + if (files != null) { + for (int i = 0; i < files.size(); ++i) { + BinaryData file = files.get(i); + String contentType = contentTypes.get(i); + if (contentType != null && !contentType.isEmpty()) { + contentType = APPLICATION_OCTET_STREAM; + } + String filename = filenames.get(i); + writeFileField(fieldName, file, contentType, filename); + } } return this; } @@ -156,8 +181,34 @@ public MultipartFormDataHelper end() { return this; } + private void writeFileField(String fieldName, BinaryData file, String contentType, String filename) { + String contentDispositionFilename = ""; + if (filename != null && !filename.isEmpty()) { + contentDispositionFilename = "; filename=\"" + escapeName(filename) + "\""; + } + + // Multipart preamble + String fileFieldPreamble = partSeparator + + CRLF + "Content-Disposition: form-data; name=\"" + escapeName(fieldName) + "\"" + contentDispositionFilename + + CRLF + "Content-Type: " + contentType + CRLF + CRLF; + byte[] data = fileFieldPreamble.getBytes(encoderCharset); + appendBytes(data); + + // Writing the file into the request as a byte stream + requestLength += file.getLength(); + requestDataStream = new SequenceInputStream(requestDataStream, file.toStream()); + + // CRLF + data = CRLF.getBytes(encoderCharset); + appendBytes(data); + } + private void appendBytes(byte[] bytes) { requestLength += bytes.length; requestDataStream = new SequenceInputStream(requestDataStream, new ByteArrayInputStream(bytes)); } + + private static String escapeName(String name) { + return name.replace("\n", "%0A").replace("\r", "%0D").replace("\"", "%22"); + } } diff --git a/typespec-extension/src/code-model-builder.ts b/typespec-extension/src/code-model-builder.ts index c506bf137e..7245bd81a0 100644 --- a/typespec-extension/src/code-model-builder.ts +++ b/typespec-extension/src/code-model-builder.ts @@ -188,10 +188,9 @@ export class CodeModelBuilder { private typeNameOptions: TypeNameOptions; private namespace: string; private sdkContext: SdkContext; - private options: EmitterOptions; - private codeModel: CodeModel; + private loggingEnabled: boolean = false; readonly schemaCache = new ProcessingCache((type: Type, name: string) => this.processSchemaImpl(type, name)); readonly typeUnionRefCache = new Map(); // Union means it ref a Union type, null means it does not ref any Union, nndefined means type visited but not completed @@ -201,6 +200,9 @@ export class CodeModelBuilder { public constructor(program1: Program, context: EmitContext) { this.options = context.options; this.program = program1; + if(this.options["dev-options"]?.loglevel) { + this.loggingEnabled = true; + } if (this.options["skip-special-headers"]) { this.options["skip-special-headers"].forEach((it) => SPECIAL_HEADER_NAMES.add(it.toLowerCase())); @@ -210,7 +212,7 @@ export class CodeModelBuilder { const service = listServices(this.program)[0]; const serviceNamespace = service.type; if (serviceNamespace === undefined) { - throw Error("Can not emit yaml for a namespace that doesn't exist."); + throw Error("Cannot emit yaml for a namespace that doesn't exist."); } // java namespace @@ -2622,7 +2624,9 @@ export class CodeModelBuilder { } private logWarning(msg: string) { - logWarning(this.program, msg); + if(this.loggingEnabled) { + logWarning(this.program, msg); + } } private trace(msg: string) { From 2feccd6d00db43dd0572508a15cbb2e8ac06f824 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 01:31:38 -0800 Subject: [PATCH 03/10] update pom to add repositories section --- javagen/pom.xml | 7 +++++++ .../java/com/azure/autorest/mapper/PomMapper.java | 5 +++++ .../com/azure/autorest/model/clientmodel/Pom.java | 11 +++++++++++ .../java/com/azure/autorest/template/PomTemplate.java | 11 +++++++++++ 4 files changed, 34 insertions(+) diff --git a/javagen/pom.xml b/javagen/pom.xml index c1d9131feb..6522320ef6 100644 --- a/javagen/pom.xml +++ b/javagen/pom.xml @@ -17,6 +17,13 @@ azure-autorest-javagen 1.0.0-beta.1 + + + clientcore + https://clientcore.blob.core.windows.net/artifacts + + + com.fasterxml.jackson.core diff --git a/javagen/src/main/java/com/azure/autorest/mapper/PomMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/PomMapper.java index cc0731193b..375263788b 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/PomMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/PomMapper.java @@ -8,8 +8,10 @@ import com.azure.autorest.model.projectmodel.Project; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -83,6 +85,9 @@ private Pom createGenericPom(Project project) { pom.setServiceName(project.getServiceName()); pom.setServiceDescription(project.getServiceDescriptionForPom()); + Map repositories = new HashMap<>(); + repositories.put("clientcore", "https://clientcore.blob.core.windows.net/artifacts"); + pom.setRepositories(repositories); Set addedDependencyPrefixes = new HashSet<>(); List dependencyIdentifiers = new ArrayList<>(); diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Pom.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Pom.java index 5b30deec61..cfa40a7c35 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Pom.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Pom.java @@ -4,6 +4,7 @@ package com.azure.autorest.model.clientmodel; import java.util.List; +import java.util.Map; public class Pom { private String parentIdentifier; @@ -15,6 +16,7 @@ public class Pom { private String serviceName; private String serviceDescription; private List dependencyIdentifiers; + private Map repositories; private boolean requireCompilerPlugins = false; @@ -106,4 +108,13 @@ public Pom setRequireCompilerPlugins(boolean requireCompilerPlugins) { this.requireCompilerPlugins = requireCompilerPlugins; return this; } + + public Map getRepositories() { + return repositories; + } + + public Pom setRepositories(Map repositories) { + this.repositories = repositories; + return this; + } } diff --git a/javagen/src/main/java/com/azure/autorest/template/PomTemplate.java b/javagen/src/main/java/com/azure/autorest/template/PomTemplate.java index 98c9290d18..c55bda15a3 100644 --- a/javagen/src/main/java/com/azure/autorest/template/PomTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/PomTemplate.java @@ -108,6 +108,17 @@ public final void write(Pom pom, XmlFile xmlFile) { }); } + if (!branded && pom.getRepositories() != null && !pom.getRepositories().isEmpty()) { + projectBlock.block("repositories", repositoriesBlock -> { + for (Map.Entry repository : pom.getRepositories().entrySet()) { + repositoriesBlock.block("repository", repositoryBlock -> { + repositoryBlock.tag("id", repository.getKey()); + repositoryBlock.tag("url", repository.getValue()); + }); + } + }); + } + projectBlock.block("properties", propertiesBlock -> { propertiesBlock.tag("project.build.sourceEncoding", "UTF-8"); writeJacoco(propertiesBlock); From dcc6ac84d27ece4593224fc60b1be85a8ba11217 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 01:43:04 -0800 Subject: [PATCH 04/10] fix checkstyle --- .../java/com/azure/autorest/mapper/ProxyMethodMapper.java | 1 - .../java/com/azure/autorest/model/clientmodel/Annotation.java | 4 ++-- .../azure/autorest/model/clientmodel/ClientBuilderTrait.java | 2 -- .../com/azure/autorest/model/clientmodel/ProxyMethod.java | 4 ++-- .../autorest/template/ConvenienceMethodTemplateBase.java | 1 - .../main/java/com/azure/autorest/template/EnumTemplate.java | 2 -- 6 files changed, 4 insertions(+), 10 deletions(-) diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java index 60a80025cc..3d29131807 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java @@ -27,7 +27,6 @@ import com.azure.autorest.util.XmsExampleWrapper; import com.azure.core.http.HttpMethod; import com.azure.core.util.CoreUtils; -import com.generic.core.http.exception.HttpExceptionType; import org.slf4j.Logger; import java.util.ArrayList; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java index b4e0501969..d96ef4ed1e 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/Annotation.java @@ -72,10 +72,10 @@ public class Annotation { public static final Annotation METADATA = new Annotation.Builder() .knownClass(com.generic.core.annotation.Metadata.class) .build(); - public static final Annotation HttpRequestInformation = new Annotation.Builder() + public static final Annotation HTTP_REQUEST_INFORMATION = new Annotation.Builder() .knownClass(com.generic.core.http.annotation.HttpRequestInformation.class) .build(); - public static final Annotation UnexpectedResponseExceptionInformation = new Annotation.Builder() + public static final Annotation UNEXPECTED_RESPONSE_EXCEPTION_INFORMATION = new Annotation.Builder() .knownClass(com.generic.core.http.annotation.UnexpectedResponseExceptionInformation.class) .build(); public static final Annotation TYPE_CONDITIONS = new Annotation.Builder() diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java index bcf5fe37d1..086d29e332 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientBuilderTrait.java @@ -6,9 +6,7 @@ import com.azure.autorest.extension.base.plugin.JavaSettings; import com.azure.autorest.model.javamodel.JavaBlock; import com.azure.core.client.traits.AzureKeyCredentialTrait; -import com.azure.core.client.traits.ConfigurationTrait; import com.azure.core.client.traits.EndpointTrait; -import com.azure.core.client.traits.HttpTrait; import com.azure.core.client.traits.KeyCredentialTrait; import com.azure.core.client.traits.TokenCredentialTrait; import com.azure.core.credential.AzureKeyCredential; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java index 7029b96def..557582f04a 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethod.java @@ -400,8 +400,8 @@ private IType mapToSyncType(IType type) { */ public void addImportsTo(Set imports, boolean includeImplementationImports, JavaSettings settings) { imports.add(RestProxyUtils.class.getName()); - Annotation.HttpRequestInformation.addImportsTo(imports); - Annotation.UnexpectedResponseExceptionInformation.addImportsTo(imports); + Annotation.HTTP_REQUEST_INFORMATION.addImportsTo(imports); + Annotation.UNEXPECTED_RESPONSE_EXCEPTION_INFORMATION.addImportsTo(imports); if (includeImplementationImports) { if (getUnexpectedResponseExceptionType() != null) { Annotation.UNEXPECTED_RESPONSE_EXCEPTION_TYPE.addImportsTo(imports); 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 195d274831..5b8fb75966 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java @@ -36,7 +36,6 @@ import com.azure.core.util.FluxUtil; import com.azure.core.util.serializer.CollectionFormat; import com.azure.core.util.serializer.JacksonAdapter; -import com.azure.core.util.serializer.TypeReference; import java.util.Arrays; import java.util.Collection; diff --git a/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java b/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java index ec150cb0d6..d0603f0973 100644 --- a/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/EnumTemplate.java @@ -18,11 +18,9 @@ import com.azure.autorest.model.javamodel.JavaVisibility; import com.azure.autorest.util.CodeNamer; import com.azure.core.util.CoreUtils; -import com.generic.core.models.HeaderName; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /** * Writes a EnumType to a JavaFile. From db3ec038df9820db3af67ef8cd6442ed808feb60 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 02:23:43 -0800 Subject: [PATCH 05/10] fix annotation --- .../java/com/azure/autorest/template/ClientMethodTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java index d0e2c9caa9..76daf3219a 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ClientMethodTemplate.java @@ -890,7 +890,7 @@ protected void generatePagingAsync(ClientMethod clientMethod, JavaType typeBlock private static void addServiceMethodAnnotation(JavaType typeBlock, ReturnType returnType) { if (JavaSettings.getInstance().isBranded()) { - typeBlock.annotation("ServiceMethod(returns = ReturnType." + returnType.name() + ");"); + typeBlock.annotation("ServiceMethod(returns = ReturnType." + returnType.name() + ")"); } } From af5959fdf832081b7b2b7e86241590a143dcbb44 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 02:31:53 -0800 Subject: [PATCH 06/10] fix formatting --- typespec-extension/src/code-model-builder.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typespec-extension/src/code-model-builder.ts b/typespec-extension/src/code-model-builder.ts index 397fd89e76..bfe0cd8476 100644 --- a/typespec-extension/src/code-model-builder.ts +++ b/typespec-extension/src/code-model-builder.ts @@ -199,7 +199,7 @@ export class CodeModelBuilder { public constructor(program1: Program, context: EmitContext) { this.options = context.options; this.program = program1; - if(this.options["dev-options"]?.loglevel) { + if (this.options["dev-options"]?.loglevel) { this.loggingEnabled = true; } @@ -2623,8 +2623,8 @@ export class CodeModelBuilder { } private logWarning(msg: string) { - if(this.loggingEnabled) { - logWarning(this.program, msg); + if (this.loggingEnabled) { + logWarning(this.program, msg); } } From d71681177ea458c51ff0a12f1b1f2d48866919e8 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 02:48:30 -0800 Subject: [PATCH 07/10] regen --- .../FormRecognizerClientImplBuilder.java | 14 +++++++------- .../extension/base/plugin/JavaSettings.java | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java index c94e685d7b..3b145f2b68 100644 --- a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java +++ b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java @@ -6,11 +6,11 @@ import com.azure.core.annotation.Generated; import com.azure.core.annotation.ServiceClientBuilder; -import com.azure.core.client.traits.AzureKeyCredentialTrait; import com.azure.core.client.traits.ConfigurationTrait; import com.azure.core.client.traits.EndpointTrait; import com.azure.core.client.traits.HttpTrait; -import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.client.traits.KeyCredentialTrait; +import com.azure.core.credential.KeyCredential; import com.azure.core.http.HttpClient; import com.azure.core.http.HttpHeaderName; import com.azure.core.http.HttpHeaders; @@ -47,7 +47,7 @@ @ServiceClientBuilder(serviceClients = { FormRecognizerClientImpl.class }) public final class FormRecognizerClientImplBuilder implements HttpTrait, ConfigurationTrait, - AzureKeyCredentialTrait, EndpointTrait { + KeyCredentialTrait, EndpointTrait { @Generated private static final String SDK_NAME = "name"; @@ -176,18 +176,18 @@ public FormRecognizerClientImplBuilder configuration(Configuration configuration } /* - * The AzureKeyCredential used for authentication. + * The KeyCredential used for authentication. */ @Generated - private AzureKeyCredential azureKeyCredential; + private KeyCredential keyCredential; /** * {@inheritDoc}. */ @Generated @Override - public FormRecognizerClientImplBuilder credential(AzureKeyCredential azureKeyCredential) { - this.azureKeyCredential = azureKeyCredential; + public FormRecognizerClientImplBuilder credential(KeyCredential keyCredential) { + this.keyCredential = keyCredential; return this; } diff --git a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java index 3f41c76584..3541d9c273 100644 --- a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java +++ b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java @@ -166,7 +166,7 @@ public static JavaSettings getInstance() { getBooleanValue(host, "include-read-only-in-constructor-args", false), // setting the default as true as the Java design guideline recommends using String for URLs. getBooleanValue(host, "url-as-string", true), - getBooleanValue(host, "uuid-as-string", true), + getBooleanValue(host, "uuid-as-string", false), // setting this to false by default as a lot of existing libraries still use swagger and // were generated with required = true set in JsonProperty annotation From 38d5909559676589d2e5373da5a8a980f18902a1 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 09:00:42 -0800 Subject: [PATCH 08/10] fix metadata --- .../com/azure/autorest/model/clientmodel/ClientModel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 8f46b57e10..b9c240b5de 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 @@ -436,8 +436,10 @@ protected void addJsonFlattenAnnotationImport(Set imports) { */ protected void addImmutableAnnotationImport(Set imports) { Annotation.IMMUTABLE.addImportsTo(imports); - Annotation.METADATA.addImportsTo(imports); Annotation.TYPE_CONDITIONS.addImportsTo(imports); + if (!JavaSettings.getInstance().isBranded()) { + Annotation.METADATA.addImportsTo(imports); + } } /** @@ -447,7 +449,9 @@ protected void addImmutableAnnotationImport(Set imports) { */ protected void addFluentAnnotationImport(Set imports) { Annotation.FLUENT.addImportsTo(imports); - Annotation.METADATA.addImportsTo(imports); + if(!JavaSettings.getInstance().isBranded()) { + Annotation.METADATA.addImportsTo(imports); + } } /** From 134216d6d68378030fd901abd9f607319eaadd22 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 09:14:50 -0800 Subject: [PATCH 09/10] fix key credential --- .../FormRecognizerClientImplBuilder.java | 14 +++++++------- .../com/azure/autorest/mapper/ClientMapper.java | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java index 3b145f2b68..83c56abab0 100644 --- a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java +++ b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java @@ -6,11 +6,11 @@ import com.azure.core.annotation.Generated; import com.azure.core.annotation.ServiceClientBuilder; +import com.azure.core.client.traits.AzureKeyCredentialTrait; import com.azure.core.client.traits.ConfigurationTrait; import com.azure.core.client.traits.EndpointTrait; import com.azure.core.client.traits.HttpTrait; -import com.azure.core.client.traits.KeyCredentialTrait; -import com.azure.core.credential.KeyCredential; +import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; import com.azure.core.http.HttpHeaderName; import com.azure.core.http.HttpHeaders; @@ -47,7 +47,7 @@ @ServiceClientBuilder(serviceClients = { FormRecognizerClientImpl.class }) public final class FormRecognizerClientImplBuilder implements HttpTrait, ConfigurationTrait, - KeyCredentialTrait, EndpointTrait { + AzureKeyCredentialTrait, EndpointTrait { @Generated private static final String SDK_NAME = "name"; @@ -176,18 +176,18 @@ public FormRecognizerClientImplBuilder configuration(Configuration configuration } /* - * The KeyCredential used for authentication. + * The AzureKeyCredential used for authentication. */ @Generated - private KeyCredential keyCredential; + private AzureKeyCredential azureKeyCredential; /** * {@inheritDoc}. */ @Generated @Override - public FormRecognizerClientImplBuilder credential(KeyCredential keyCredential) { - this.keyCredential = keyCredential; + public FormRecognizerClientImplBuilder credential(AzureKeyCredential keyCredential) { + this.azureKeyCredential = azureKeyCredential; return this; } diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java index dac0e0394f..7376b7d6c4 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java @@ -466,7 +466,7 @@ private void addBuilderTraits(ClientBuilder clientBuilder, ServiceClient service clientBuilder.addBuilderTrait(ClientBuilderTrait.TOKEN_CREDENTIAL_TRAIT); } if (serviceClient.getSecurityInfo().getSecurityTypes().contains(Scheme.SecuritySchemeType.KEY)) { - if (JavaSettings.getInstance().isBranded() || JavaSettings.getInstance().isUseKeyCredential()) { + if (!JavaSettings.getInstance().isBranded() || JavaSettings.getInstance().isUseKeyCredential()) { clientBuilder.addBuilderTrait(ClientBuilderTrait.KEY_CREDENTIAL_TRAIT); } else { clientBuilder.addBuilderTrait(ClientBuilderTrait.AZURE_KEY_CREDENTIAL_TRAIT); From 6c258902cad49589f862b4f0e58790b5d306edd6 Mon Sep 17 00:00:00 2001 From: Srikanta Nagaraja Date: Wed, 6 Mar 2024 09:37:14 -0800 Subject: [PATCH 10/10] fix var name --- .../implementation/FormRecognizerClientImplBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java index 83c56abab0..c94e685d7b 100644 --- a/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java +++ b/azure-dataplane-tests/src/main/java/com/azure/ai/formrecognizer/documentanalysis/implementation/FormRecognizerClientImplBuilder.java @@ -186,7 +186,7 @@ public FormRecognizerClientImplBuilder configuration(Configuration configuration */ @Generated @Override - public FormRecognizerClientImplBuilder credential(AzureKeyCredential keyCredential) { + public FormRecognizerClientImplBuilder credential(AzureKeyCredential azureKeyCredential) { this.azureKeyCredential = azureKeyCredential; return this; }