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 69e84e1aa3..7b265416a6 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -835,7 +835,17 @@ private void addModelConstructor(ClientModel model, JavaVisibility constructorVi // Finally, add all required properties. if (settings.isRequiredFieldsAsConstructorArgs()) { for (ClientModelProperty property : requiredProperties) { - constructor.line("this." + property.getName() + " = " + property.getWireType().convertFromClientType(property.getName()) + ";"); + if (property.getClientType() != property.getWireType()) { + // If the property needs to be converted and the passed value is null, set the field to null as the + // converter will likely throw a NullPointerException. + // Otherwise, just convert the value. + constructor.ifBlock(property.getName() + " == null", + ifBlock -> ifBlock.line("this.%s = %s;", property.getName(), property.getWireType().defaultValueExpression())) + .elseBlock(elseBlock -> elseBlock.line("this.%s = %s;", + property.getName(), property.getWireType().convertFromClientType(property.getName()))); + } else { + constructor.line("this." + property.getName() + " = " + property.getWireType().convertFromClientType(property.getName()) + ";"); + } } } }); @@ -993,7 +1003,7 @@ private static void addSetterMethod(IType propertyWireType, IType propertyClient // converter will likely throw a NullPointerException. // Otherwise, just convert the value. methodBlock.ifBlock(property.getName() + " == null", - ifBlock -> ifBlock.line("this.%s = null;", property.getName())) + ifBlock -> ifBlock.line("this.%s = %s;", property.getName(), property.getWireType().defaultValueExpression())) .elseBlock(elseBlock -> elseBlock.line("this.%s = %s;", property.getName(), propertyWireType.convertFromClientType(expression))); } else { diff --git a/typespec-extension/changelog.md b/typespec-extension/changelog.md index f24fd68e01..46477203e2 100644 --- a/typespec-extension/changelog.md +++ b/typespec-extension/changelog.md @@ -1,5 +1,12 @@ # Release History +## 0.15.8 (2024-04-11) + +Compatible with compiler 0.55. + +- Bug fix on `@encode`. +- Bug fix on required property of nullable type. + ## 0.15.7 (2024-04-03) Compatible with compiler 0.55. diff --git a/typespec-extension/package-lock.json b/typespec-extension/package-lock.json index 6e0f96514b..86471e084d 100644 --- a/typespec-extension/package-lock.json +++ b/typespec-extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure-tools/typespec-java", - "version": "0.15.7", + "version": "0.15.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@azure-tools/typespec-java", - "version": "0.15.7", + "version": "0.15.8", "license": "MIT", "dependencies": { "@autorest/codemodel": "~4.20.0", diff --git a/typespec-extension/package.json b/typespec-extension/package.json index 01acd1cf35..2d0a3e421c 100644 --- a/typespec-extension/package.json +++ b/typespec-extension/package.json @@ -1,6 +1,6 @@ { "name": "@azure-tools/typespec-java", - "version": "0.15.7", + "version": "0.15.8", "description": "TypeSpec library for emitting Java client from the TypeSpec REST protocol binding", "keywords": [ "TypeSpec" diff --git a/typespec-extension/src/code-model-builder.ts b/typespec-extension/src/code-model-builder.ts index 7f7f407b9f..a5b6b67ec1 100644 --- a/typespec-extension/src/code-model-builder.ts +++ b/typespec-extension/src/code-model-builder.ts @@ -2376,25 +2376,34 @@ export class CodeModelBuilder { // } const format = getFormat(this.program, prop); if (format) { + // TODO: deprecate format if (prop.type.kind === "Scalar" && schema instanceof StringSchema) { schema = this.processFormatString(prop.type, format, nameHint); } - } else if (prop.type.kind === "Scalar") { + } else { + // encode const encode = getEncode(this.program, prop); if (encode) { - if (encode.encoding === "seconds" && hasScalarAsBase(prop.type, "duration")) { - schema = this.processDurationSchema(prop.type, nameHint, getDurationFormat(encode)); - } else if ( - (encode.encoding === "rfc3339" || encode.encoding === "rfc7231" || encode.encoding === "unixTimestamp") && - (hasScalarAsBase(prop.type, "utcDateTime") || hasScalarAsBase(prop.type, "offsetDateTime")) - ) { - if (encode.encoding === "unixTimestamp") { - return this.processUnixTimeSchema(prop.type, nameHint); - } else { - return this.processDateTimeSchema(prop.type, nameHint, encode.encoding === "rfc7231"); + let type = prop.type; + if (prop.type.kind === "Union" && isNullableType(prop.type)) { + const nonNullVariants = Array.from(prop.type.variants.values()).filter((it) => !isNullType(it.type)); + type = nonNullVariants[0].type; + } + if (type && type.kind === "Scalar") { + if (encode.encoding === "seconds" && hasScalarAsBase(type, "duration")) { + schema = this.processDurationSchema(type, nameHint, getDurationFormat(encode)); + } else if ( + (encode.encoding === "rfc3339" || encode.encoding === "rfc7231" || encode.encoding === "unixTimestamp") && + (hasScalarAsBase(type, "utcDateTime") || hasScalarAsBase(type, "offsetDateTime")) + ) { + if (encode.encoding === "unixTimestamp") { + return this.processUnixTimeSchema(type, nameHint); + } else { + return this.processDateTimeSchema(type, nameHint, encode.encoding === "rfc7231"); + } + } else if (encode.encoding === "base64url" && hasScalarAsBase(type, "bytes")) { + return this.processByteArraySchema(type, nameHint, true); } - } else if (encode.encoding === "base64url" && hasScalarAsBase(prop.type, "bytes")) { - return this.processByteArraySchema(prop.type, nameHint, true); } } } diff --git a/typespec-tests/package.json b/typespec-tests/package.json index 1c127787c4..8c46766538 100644 --- a/typespec-tests/package.json +++ b/typespec-tests/package.json @@ -9,8 +9,8 @@ "testserver-run": "npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./cadl-ranch-coverage-java.json" }, "dependencies": { - "@azure-tools/cadl-ranch-specs": "0.31.6", - "@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.15.7.tgz" + "@azure-tools/cadl-ranch-specs": "0.31.7", + "@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.15.8.tgz" }, "devDependencies": { "@typespec/prettier-plugin-typespec": "~0.55.0", diff --git a/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java b/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java index 32511bf21c..fdd2479f06 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java @@ -18,13 +18,19 @@ import com.azure.core.util.FluxUtil; import com.cadl.flatten.implementation.FlattenClientImpl; import com.cadl.flatten.implementation.JsonMergePatchHelper; +import com.cadl.flatten.implementation.MultipartFormDataHelper; import com.cadl.flatten.implementation.models.SendLongRequest; import com.cadl.flatten.implementation.models.SendProjectedNameRequest; import com.cadl.flatten.implementation.models.SendRequest; +import com.cadl.flatten.implementation.models.UploadFileRequest; +import com.cadl.flatten.implementation.models.UploadTodoRequest; +import com.cadl.flatten.models.FileDataFileDetails; import com.cadl.flatten.models.SendLongOptions; import com.cadl.flatten.models.TodoItem; import com.cadl.flatten.models.UpdatePatchRequest; +import com.cadl.flatten.models.UploadTodoOptions; import com.cadl.flatten.models.User; +import java.util.Objects; import reactor.core.publisher.Mono; /** @@ -194,6 +200,43 @@ public Mono> updateWithResponse(long id, BinaryData request return this.serviceClient.updateWithResponseAsync(id, request, requestOptions); } + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response} on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + Mono> uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { + // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadFile' is 'multipart/form-data' + return this.serviceClient.uploadFileWithResponseAsync(name, request, requestOptions); + } + + /** + * The uploadTodo operation. + * + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response} on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + Mono> uploadTodoWithResponse(BinaryData request, RequestOptions requestOptions) { + // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadTodo' is 'multipart/form-data' + return this.serviceClient.uploadTodoWithResponseAsync(request, requestOptions); + } + /** * The send operation. * @@ -323,4 +366,68 @@ public Mono update(long id, UpdatePatchRequest request) { return updateWithResponse(id, requestInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(TodoItem.class)); } + + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param fileData The file details for the "file_data" field. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return A {@link Mono} that completes when a successful response is received. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono uploadFile(String name, FileDataFileDetails fileData) { + // Generated convenience method for uploadFileWithResponse + RequestOptions requestOptions = new RequestOptions(); + UploadFileRequest requestObj = new UploadFileRequest(fileData); + BinaryData request = new MultipartFormDataHelper(requestOptions) + .serializeFileField("file_data", requestObj.getFileData().getContent(), + requestObj.getFileData().getContentType(), requestObj.getFileData().getFilename()) + .serializeTextField("constant", requestObj.getConstant()) + .end() + .getRequestBody(); + return uploadFileWithResponse(name, request, requestOptions).flatMap(FluxUtil::toMono); + } + + /** + * The uploadTodo operation. + * + * @param options Options for uploadTodo API. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return A {@link Mono} that completes when a successful response is received. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono uploadTodo(UploadTodoOptions options) { + // Generated convenience method for uploadTodoWithResponse + RequestOptions requestOptions = new RequestOptions(); + UploadTodoRequest requestObj + = new UploadTodoRequest(options.getTitle(), options.getStatus()).setDescription(options.getDescription()) + .setDummy(options.getDummy()) + .setProp1(options.getProp1()) + .setProp2(options.getProp2()) + .setProp3(options.getProp3()); + BinaryData request + = new MultipartFormDataHelper(requestOptions).serializeTextField("title", requestObj.getTitle()) + .serializeTextField("description", requestObj.getDescription()) + .serializeTextField("status", Objects.toString(requestObj.getStatus())) + .serializeTextField("_dummy", requestObj.getDummy()) + .serializeTextField("prop1", requestObj.getProp1()) + .serializeTextField("prop2", requestObj.getProp2()) + .serializeTextField("prop3", requestObj.getProp3()) + .end() + .getRequestBody(); + return uploadTodoWithResponse(request, requestOptions).flatMap(FluxUtil::toMono); + } } diff --git a/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java b/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java index 740343f86f..156ee84af5 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java @@ -17,13 +17,19 @@ import com.azure.core.util.BinaryData; import com.cadl.flatten.implementation.FlattenClientImpl; import com.cadl.flatten.implementation.JsonMergePatchHelper; +import com.cadl.flatten.implementation.MultipartFormDataHelper; import com.cadl.flatten.implementation.models.SendLongRequest; import com.cadl.flatten.implementation.models.SendProjectedNameRequest; import com.cadl.flatten.implementation.models.SendRequest; +import com.cadl.flatten.implementation.models.UploadFileRequest; +import com.cadl.flatten.implementation.models.UploadTodoRequest; +import com.cadl.flatten.models.FileDataFileDetails; import com.cadl.flatten.models.SendLongOptions; import com.cadl.flatten.models.TodoItem; import com.cadl.flatten.models.UpdatePatchRequest; +import com.cadl.flatten.models.UploadTodoOptions; import com.cadl.flatten.models.User; +import java.util.Objects; /** * Initializes a new instance of the synchronous FlattenClient type. @@ -191,6 +197,43 @@ public Response updateWithResponse(long id, BinaryData request, Requ return this.serviceClient.updateWithResponse(id, request, requestOptions); } + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + Response uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { + // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadFile' is 'multipart/form-data' + return this.serviceClient.uploadFileWithResponse(name, request, requestOptions); + } + + /** + * The uploadTodo operation. + * + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + Response uploadTodoWithResponse(BinaryData request, RequestOptions requestOptions) { + // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadTodo' is 'multipart/form-data' + return this.serviceClient.uploadTodoWithResponse(request, requestOptions); + } + /** * The send operation. * @@ -315,4 +358,66 @@ public TodoItem update(long id, UpdatePatchRequest request) { JsonMergePatchHelper.getUpdatePatchRequestAccessor().prepareModelForJsonMergePatch(request, false); return updateWithResponse(id, requestInBinaryData, requestOptions).getValue().toObject(TodoItem.class); } + + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param fileData The file details for the "file_data" field. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public void uploadFile(String name, FileDataFileDetails fileData) { + // Generated convenience method for uploadFileWithResponse + RequestOptions requestOptions = new RequestOptions(); + UploadFileRequest requestObj = new UploadFileRequest(fileData); + BinaryData request = new MultipartFormDataHelper(requestOptions) + .serializeFileField("file_data", requestObj.getFileData().getContent(), + requestObj.getFileData().getContentType(), requestObj.getFileData().getFilename()) + .serializeTextField("constant", requestObj.getConstant()) + .end() + .getRequestBody(); + uploadFileWithResponse(name, request, requestOptions).getValue(); + } + + /** + * The uploadTodo operation. + * + * @param options Options for uploadTodo API. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public void uploadTodo(UploadTodoOptions options) { + // Generated convenience method for uploadTodoWithResponse + RequestOptions requestOptions = new RequestOptions(); + UploadTodoRequest requestObj + = new UploadTodoRequest(options.getTitle(), options.getStatus()).setDescription(options.getDescription()) + .setDummy(options.getDummy()) + .setProp1(options.getProp1()) + .setProp2(options.getProp2()) + .setProp3(options.getProp3()); + BinaryData request + = new MultipartFormDataHelper(requestOptions).serializeTextField("title", requestObj.getTitle()) + .serializeTextField("description", requestObj.getDescription()) + .serializeTextField("status", Objects.toString(requestObj.getStatus())) + .serializeTextField("_dummy", requestObj.getDummy()) + .serializeTextField("prop1", requestObj.getProp1()) + .serializeTextField("prop2", requestObj.getProp2()) + .serializeTextField("prop3", requestObj.getProp3()) + .end() + .getRequestBody(); + uploadTodoWithResponse(request, requestOptions).getValue(); + } } diff --git a/typespec-tests/src/main/java/com/cadl/flatten/implementation/FlattenClientImpl.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/FlattenClientImpl.java index 7489a5012a..e221d16124 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/implementation/FlattenClientImpl.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/FlattenClientImpl.java @@ -205,7 +205,7 @@ Response sendLongSync(@HostParam("endpoint") String endpoint, @QueryParam( @QueryParam("api-version") String apiVersion, @HeaderParam("accept") String accept, @BodyParam("application/json") BinaryData request, RequestOptions requestOptions, Context context); - @Patch("/flatten/{id}") + @Patch("/flatten/patch/{id}") @ExpectedResponses({ 200 }) @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) @@ -216,7 +216,7 @@ Mono> update(@HostParam("endpoint") String endpoint, @HeaderParam("accept") String accept, @BodyParam("application/merge-patch+json") BinaryData request, RequestOptions requestOptions, Context context); - @Patch("/flatten/{id}") + @Patch("/flatten/patch/{id}") @ExpectedResponses({ 200 }) @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) @@ -226,6 +226,50 @@ Response updateSync(@HostParam("endpoint") String endpoint, @HeaderParam("content-type") String contentType, @PathParam("id") long id, @HeaderParam("accept") String accept, @BodyParam("application/merge-patch+json") BinaryData request, RequestOptions requestOptions, Context context); + + // @Multipart not supported by RestProxy + @Post("/flatten/upload/{name}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Mono> uploadFile(@HostParam("endpoint") String endpoint, @PathParam("name") String name, + @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, + @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); + + // @Multipart not supported by RestProxy + @Post("/flatten/upload/{name}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Response uploadFileSync(@HostParam("endpoint") String endpoint, @PathParam("name") String name, + @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, + @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); + + // @Multipart not supported by RestProxy + @Post("/flatten/upload-todo") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Mono> uploadTodo(@HostParam("endpoint") String endpoint, + @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, + @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); + + // @Multipart not supported by RestProxy + @Post("/flatten/upload-todo") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Response uploadTodoSync(@HostParam("endpoint") String endpoint, + @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, + @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); } /** @@ -534,4 +578,82 @@ public Response updateWithResponse(long id, BinaryData request, Requ final String accept = "application/json"; return service.updateSync(this.getEndpoint(), contentType, id, accept, request, requestOptions, Context.NONE); } + + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> uploadFileWithResponseAsync(String name, BinaryData request, + RequestOptions requestOptions) { + final String contentType = "multipart/form-data"; + final String accept = "application/json"; + return FluxUtil.withContext(context -> service.uploadFile(this.getEndpoint(), name, contentType, accept, + request, requestOptions, context)); + } + + /** + * The uploadFile operation. + * + * @param name A sequence of textual characters. + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { + final String contentType = "multipart/form-data"; + final String accept = "application/json"; + return service.uploadFileSync(this.getEndpoint(), name, contentType, accept, request, requestOptions, + Context.NONE); + } + + /** + * The uploadTodo operation. + * + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> uploadTodoWithResponseAsync(BinaryData request, RequestOptions requestOptions) { + final String contentType = "multipart/form-data"; + final String accept = "application/json"; + return FluxUtil.withContext( + context -> service.uploadTodo(this.getEndpoint(), contentType, accept, request, requestOptions, context)); + } + + /** + * The uploadTodo operation. + * + * @param request The request parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response uploadTodoWithResponse(BinaryData request, RequestOptions requestOptions) { + final String contentType = "multipart/form-data"; + final String accept = "application/json"; + return service.uploadTodoSync(this.getEndpoint(), contentType, accept, request, requestOptions, Context.NONE); + } } diff --git a/typespec-tests/src/main/java/com/cadl/flatten/implementation/MultipartFormDataHelper.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/MultipartFormDataHelper.java new file mode 100644 index 0000000000..fae4b0725c --- /dev/null +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/MultipartFormDataHelper.java @@ -0,0 +1,210 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package com.cadl.flatten.implementation; + +import com.azure.core.http.HttpHeaderName; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.util.BinaryData; +import com.azure.core.util.CoreUtils; + +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.List; +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"; + + private static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + + /** + * 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=\"" + escapeName(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=\"" + escapeName(fieldName) + "\"" + CRLF + + "Content-Type: application/json" + CRLF + CRLF + BinaryData.fromObject(jsonObject) + CRLF; + byte[] data = serialized.getBytes(encoderCharset); + appendBytes(data); + } + return this; + } + + /** + * 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 contentType, + String filename) { + if (file != null) { + if (CoreUtils.isNullOrEmpty(contentType)) { + contentType = APPLICATION_OCTET_STREAM; + } + writeFileField(fieldName, file, contentType, filename); + } + return this; + } + + /** + * 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 (CoreUtils.isNullOrEmpty(contentType)) { + contentType = APPLICATION_OCTET_STREAM; + } + String filename = filenames.get(i); + writeFileField(fieldName, file, contentType, filename); + } + } + 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(HttpHeaderName.CONTENT_TYPE, "multipart/form-data; boundary=" + this.boundary) + .setHeader(HttpHeaderName.CONTENT_LENGTH, String.valueOf(requestLength)); + + return this; + } + + private void writeFileField(String fieldName, BinaryData file, String contentType, String filename) { + String contentDispositionFilename = ""; + if (!CoreUtils.isNullOrEmpty(filename)) { + 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-tests/src/main/java/com/cadl/multipart/implementation/models/UploadFileRequest.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadFileRequest.java similarity index 93% rename from typespec-tests/src/main/java/com/cadl/multipart/implementation/models/UploadFileRequest.java rename to typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadFileRequest.java index 2b6c504967..5e94969db4 100644 --- a/typespec-tests/src/main/java/com/cadl/multipart/implementation/models/UploadFileRequest.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadFileRequest.java @@ -2,11 +2,11 @@ // Licensed under the MIT License. // Code generated by Microsoft (R) TypeSpec Code Generator. -package com.cadl.multipart.implementation.models; +package com.cadl.flatten.implementation.models; import com.azure.core.annotation.Generated; import com.azure.core.annotation.Immutable; -import com.cadl.multipart.models.FileDataFileDetails; +import com.cadl.flatten.models.FileDataFileDetails; /** * The UploadFileRequest model. diff --git a/typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadTodoRequest.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadTodoRequest.java new file mode 100644 index 0000000000..295b73d958 --- /dev/null +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/models/UploadTodoRequest.java @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package com.cadl.flatten.implementation.models; + +import com.azure.core.annotation.Fluent; +import com.azure.core.annotation.Generated; +import com.cadl.flatten.models.Status; +import java.time.OffsetDateTime; + +/** + * The UploadTodoRequest model. + */ +@Fluent +public final class UploadTodoRequest { + /* + * The item's unique id + */ + @Generated + private long id; + + /* + * The item's title + */ + @Generated + private final String title; + + /* + * A longer description of the todo item in markdown format + */ + @Generated + private String description; + + /* + * The status of the todo item + */ + @Generated + private final Status status; + + /* + * When the todo item was created. + */ + @Generated + private OffsetDateTime createdAt; + + /* + * When the todo item was last updated + */ + @Generated + private OffsetDateTime updatedAt; + + /* + * When the todo item was makred as completed + */ + @Generated + private OffsetDateTime completedAt; + + /* + * The _dummy property. + */ + @Generated + private String dummy; + + /* + * The prop1 property. + */ + @Generated + private String prop1; + + /* + * The prop2 property. + */ + @Generated + private String prop2; + + /* + * The prop3 property. + */ + @Generated + private String prop3; + + /** + * Creates an instance of UploadTodoRequest class. + * + * @param title the title value to set. + * @param status the status value to set. + */ + @Generated + public UploadTodoRequest(String title, Status status) { + this.title = title; + this.status = status; + } + + /** + * Get the id property: The item's unique id. + * + * @return the id value. + */ + @Generated + public long getId() { + return this.id; + } + + /** + * Get the title property: The item's title. + * + * @return the title value. + */ + @Generated + public String getTitle() { + return this.title; + } + + /** + * Get the description property: A longer description of the todo item in markdown format. + * + * @return the description value. + */ + @Generated + public String getDescription() { + return this.description; + } + + /** + * Set the description property: A longer description of the todo item in markdown format. + * + * @param description the description value to set. + * @return the UploadTodoRequest object itself. + */ + @Generated + public UploadTodoRequest setDescription(String description) { + this.description = description; + return this; + } + + /** + * Get the status property: The status of the todo item. + * + * @return the status value. + */ + @Generated + public Status getStatus() { + return this.status; + } + + /** + * Get the createdAt property: When the todo item was created. + * + * @return the createdAt value. + */ + @Generated + public OffsetDateTime getCreatedAt() { + return this.createdAt; + } + + /** + * Get the updatedAt property: When the todo item was last updated. + * + * @return the updatedAt value. + */ + @Generated + public OffsetDateTime getUpdatedAt() { + return this.updatedAt; + } + + /** + * Get the completedAt property: When the todo item was makred as completed. + * + * @return the completedAt value. + */ + @Generated + public OffsetDateTime getCompletedAt() { + return this.completedAt; + } + + /** + * Get the dummy property: The _dummy property. + * + * @return the dummy value. + */ + @Generated + public String getDummy() { + return this.dummy; + } + + /** + * Set the dummy property: The _dummy property. + * + * @param dummy the dummy value to set. + * @return the UploadTodoRequest object itself. + */ + @Generated + public UploadTodoRequest setDummy(String dummy) { + this.dummy = dummy; + return this; + } + + /** + * Get the prop1 property: The prop1 property. + * + * @return the prop1 value. + */ + @Generated + public String getProp1() { + return this.prop1; + } + + /** + * Set the prop1 property: The prop1 property. + * + * @param prop1 the prop1 value to set. + * @return the UploadTodoRequest object itself. + */ + @Generated + public UploadTodoRequest setProp1(String prop1) { + this.prop1 = prop1; + return this; + } + + /** + * Get the prop2 property: The prop2 property. + * + * @return the prop2 value. + */ + @Generated + public String getProp2() { + return this.prop2; + } + + /** + * Set the prop2 property: The prop2 property. + * + * @param prop2 the prop2 value to set. + * @return the UploadTodoRequest object itself. + */ + @Generated + public UploadTodoRequest setProp2(String prop2) { + this.prop2 = prop2; + return this; + } + + /** + * Get the prop3 property: The prop3 property. + * + * @return the prop3 value. + */ + @Generated + public String getProp3() { + return this.prop3; + } + + /** + * Set the prop3 property: The prop3 property. + * + * @param prop3 the prop3 value to set. + * @return the UploadTodoRequest object itself. + */ + @Generated + public UploadTodoRequest setProp3(String prop3) { + this.prop3 = prop3; + return this; + } +} diff --git a/typespec-tests/src/main/java/com/cadl/multipart/models/FileDataFileDetails.java b/typespec-tests/src/main/java/com/cadl/flatten/models/FileDataFileDetails.java similarity index 98% rename from typespec-tests/src/main/java/com/cadl/multipart/models/FileDataFileDetails.java rename to typespec-tests/src/main/java/com/cadl/flatten/models/FileDataFileDetails.java index 914c17a0ce..ec250ada2a 100644 --- a/typespec-tests/src/main/java/com/cadl/multipart/models/FileDataFileDetails.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/FileDataFileDetails.java @@ -2,7 +2,7 @@ // Licensed under the MIT License. // Code generated by Microsoft (R) TypeSpec Code Generator. -package com.cadl.multipart.models; +package com.cadl.flatten.models; import com.azure.core.annotation.Fluent; import com.azure.core.annotation.Generated; diff --git a/typespec-tests/src/main/java/com/cadl/flatten/models/UploadTodoOptions.java b/typespec-tests/src/main/java/com/cadl/flatten/models/UploadTodoOptions.java new file mode 100644 index 0000000000..68870cd89d --- /dev/null +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/UploadTodoOptions.java @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package com.cadl.flatten.models; + +import com.azure.core.annotation.Fluent; +import com.azure.core.annotation.Generated; + +/** + * Options for uploadTodo API. + */ +@Fluent +public final class UploadTodoOptions { + /* + * The item's title + */ + @Generated + private final String title; + + /* + * A longer description of the todo item in markdown format + */ + @Generated + private String description; + + /* + * The status of the todo item + */ + @Generated + private final Status status; + + /* + * The _dummy property. + */ + @Generated + private String dummy; + + /* + * The prop1 property. + */ + @Generated + private String prop1; + + /* + * The prop2 property. + */ + @Generated + private String prop2; + + /* + * The prop3 property. + */ + @Generated + private String prop3; + + /** + * Creates an instance of UploadTodoOptions class. + * + * @param title the title value to set. + * @param status the status value to set. + */ + @Generated + public UploadTodoOptions(String title, Status status) { + this.title = title; + this.status = status; + } + + /** + * Get the title property: The item's title. + * + * @return the title value. + */ + @Generated + public String getTitle() { + return this.title; + } + + /** + * Get the description property: A longer description of the todo item in markdown format. + * + * @return the description value. + */ + @Generated + public String getDescription() { + return this.description; + } + + /** + * Set the description property: A longer description of the todo item in markdown format. + * + * @param description the description value to set. + * @return the UploadTodoOptions object itself. + */ + @Generated + public UploadTodoOptions setDescription(String description) { + this.description = description; + return this; + } + + /** + * Get the status property: The status of the todo item. + * + * @return the status value. + */ + @Generated + public Status getStatus() { + return this.status; + } + + /** + * Get the dummy property: The _dummy property. + * + * @return the dummy value. + */ + @Generated + public String getDummy() { + return this.dummy; + } + + /** + * Set the dummy property: The _dummy property. + * + * @param dummy the dummy value to set. + * @return the UploadTodoOptions object itself. + */ + @Generated + public UploadTodoOptions setDummy(String dummy) { + this.dummy = dummy; + return this; + } + + /** + * Get the prop1 property: The prop1 property. + * + * @return the prop1 value. + */ + @Generated + public String getProp1() { + return this.prop1; + } + + /** + * Set the prop1 property: The prop1 property. + * + * @param prop1 the prop1 value to set. + * @return the UploadTodoOptions object itself. + */ + @Generated + public UploadTodoOptions setProp1(String prop1) { + this.prop1 = prop1; + return this; + } + + /** + * Get the prop2 property: The prop2 property. + * + * @return the prop2 value. + */ + @Generated + public String getProp2() { + return this.prop2; + } + + /** + * Set the prop2 property: The prop2 property. + * + * @param prop2 the prop2 value to set. + * @return the UploadTodoOptions object itself. + */ + @Generated + public UploadTodoOptions setProp2(String prop2) { + this.prop2 = prop2; + return this; + } + + /** + * Get the prop3 property: The prop3 property. + * + * @return the prop3 value. + */ + @Generated + public String getProp3() { + return this.prop3; + } + + /** + * Set the prop3 property: The prop3 property. + * + * @param prop3 the prop3 value to set. + * @return the UploadTodoOptions object itself. + */ + @Generated + public UploadTodoOptions setProp3(String prop3) { + this.prop3 = prop3; + return this; + } +} diff --git a/typespec-tests/src/main/java/com/cadl/multipart/MultipartAsyncClient.java b/typespec-tests/src/main/java/com/cadl/multipart/MultipartAsyncClient.java index 6f1b7db328..37410f1a25 100644 --- a/typespec-tests/src/main/java/com/cadl/multipart/MultipartAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/multipart/MultipartAsyncClient.java @@ -18,8 +18,6 @@ import com.azure.core.util.FluxUtil; import com.cadl.multipart.implementation.MultipartClientImpl; import com.cadl.multipart.implementation.MultipartFormDataHelper; -import com.cadl.multipart.implementation.models.UploadFileRequest; -import com.cadl.multipart.models.FileDataFileDetails; import com.cadl.multipart.models.FileDetails; import com.cadl.multipart.models.FormData; import java.util.Objects; @@ -70,25 +68,6 @@ Mono> uploadWithResponse(String name, BinaryData data, RequestOpt return this.serviceClient.uploadWithResponseAsync(name, data, requestOptions); } - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param request The request parameter. - * @param requestOptions The options to configure the HTTP request before HTTP client sends it. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @return the {@link Response} on successful completion of {@link Mono}. - */ - @Generated - @ServiceMethod(returns = ReturnType.SINGLE) - Mono> uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { - // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadFile' is 'multipart/form-data' - return this.serviceClient.uploadFileWithResponseAsync(name, request, requestOptions); - } - /** * The upload operation. * @@ -172,32 +151,4 @@ public Mono upload(String name, FormData data) { .getRequestBody(), requestOptions).flatMap(FluxUtil::toMono); } - - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param fileData The file details for the "file_data" field. - * @throws IllegalArgumentException thrown if parameters fail the validation. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return A {@link Mono} that completes when a successful response is received. - */ - @Generated - @ServiceMethod(returns = ReturnType.SINGLE) - public Mono uploadFile(String name, FileDataFileDetails fileData) { - // Generated convenience method for uploadFileWithResponse - RequestOptions requestOptions = new RequestOptions(); - UploadFileRequest requestObj = new UploadFileRequest(fileData); - BinaryData request = new MultipartFormDataHelper(requestOptions) - .serializeFileField("file_data", requestObj.getFileData().getContent(), - requestObj.getFileData().getContentType(), requestObj.getFileData().getFilename()) - .serializeTextField("constant", requestObj.getConstant()) - .end() - .getRequestBody(); - return uploadFileWithResponse(name, request, requestOptions).flatMap(FluxUtil::toMono); - } } diff --git a/typespec-tests/src/main/java/com/cadl/multipart/MultipartClient.java b/typespec-tests/src/main/java/com/cadl/multipart/MultipartClient.java index 078ba76401..a50e7dec9b 100644 --- a/typespec-tests/src/main/java/com/cadl/multipart/MultipartClient.java +++ b/typespec-tests/src/main/java/com/cadl/multipart/MultipartClient.java @@ -17,8 +17,6 @@ import com.azure.core.util.BinaryData; import com.cadl.multipart.implementation.MultipartClientImpl; import com.cadl.multipart.implementation.MultipartFormDataHelper; -import com.cadl.multipart.implementation.models.UploadFileRequest; -import com.cadl.multipart.models.FileDataFileDetails; import com.cadl.multipart.models.FileDetails; import com.cadl.multipart.models.FormData; import java.util.Objects; @@ -68,25 +66,6 @@ Response uploadWithResponse(String name, BinaryData data, RequestOptions r return this.serviceClient.uploadWithResponse(name, data, requestOptions); } - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param request The request parameter. - * @param requestOptions The options to configure the HTTP request before HTTP client sends it. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @return the {@link Response}. - */ - @Generated - @ServiceMethod(returns = ReturnType.SINGLE) - Response uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { - // Protocol API requires serialization of parts with content-disposition and data, as operation 'uploadFile' is 'multipart/form-data' - return this.serviceClient.uploadFileWithResponse(name, request, requestOptions); - } - /** * The upload operation. * @@ -168,31 +147,4 @@ public void upload(String name, FormData data) { .getRequestBody(), requestOptions).getValue(); } - - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param fileData The file details for the "file_data" field. - * @throws IllegalArgumentException thrown if parameters fail the validation. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - */ - @Generated - @ServiceMethod(returns = ReturnType.SINGLE) - public void uploadFile(String name, FileDataFileDetails fileData) { - // Generated convenience method for uploadFileWithResponse - RequestOptions requestOptions = new RequestOptions(); - UploadFileRequest requestObj = new UploadFileRequest(fileData); - BinaryData request = new MultipartFormDataHelper(requestOptions) - .serializeFileField("file_data", requestObj.getFileData().getContent(), - requestObj.getFileData().getContentType(), requestObj.getFileData().getFilename()) - .serializeTextField("constant", requestObj.getConstant()) - .end() - .getRequestBody(); - uploadFileWithResponse(name, request, requestOptions).getValue(); - } } diff --git a/typespec-tests/src/main/java/com/cadl/multipart/implementation/MultipartClientImpl.java b/typespec-tests/src/main/java/com/cadl/multipart/implementation/MultipartClientImpl.java index 357ff2dcf9..360a52a5f2 100644 --- a/typespec-tests/src/main/java/com/cadl/multipart/implementation/MultipartClientImpl.java +++ b/typespec-tests/src/main/java/com/cadl/multipart/implementation/MultipartClientImpl.java @@ -146,28 +146,6 @@ Mono> upload(@HostParam("endpoint") String endpoint, @PathParam(" Response uploadSync(@HostParam("endpoint") String endpoint, @PathParam("name") String name, @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, @BodyParam("multipart/form-data") BinaryData data, RequestOptions requestOptions, Context context); - - // @Multipart not supported by RestProxy - @Post("/upload/files/{name}") - @ExpectedResponses({ 200 }) - @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) - @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) - @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) - @UnexpectedResponseExceptionType(HttpResponseException.class) - Mono> uploadFile(@HostParam("endpoint") String endpoint, @PathParam("name") String name, - @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, - @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); - - // @Multipart not supported by RestProxy - @Post("/upload/files/{name}") - @ExpectedResponses({ 200 }) - @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) - @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) - @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) - @UnexpectedResponseExceptionType(HttpResponseException.class) - Response uploadFileSync(@HostParam("endpoint") String endpoint, @PathParam("name") String name, - @HeaderParam("content-type") String contentType, @HeaderParam("accept") String accept, - @BodyParam("multipart/form-data") BinaryData request, RequestOptions requestOptions, Context context); } /** @@ -222,45 +200,4 @@ public Response uploadWithResponse(String name, BinaryData data, RequestOp final String accept = "application/json"; return service.uploadSync(this.getEndpoint(), name, contentType, accept, data, requestOptions, Context.NONE); } - - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param request The request parameter. - * @param requestOptions The options to configure the HTTP request before HTTP client sends it. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @return the {@link Response} on successful completion of {@link Mono}. - */ - @ServiceMethod(returns = ReturnType.SINGLE) - public Mono> uploadFileWithResponseAsync(String name, BinaryData request, - RequestOptions requestOptions) { - final String contentType = "multipart/form-data"; - final String accept = "application/json"; - return FluxUtil.withContext(context -> service.uploadFile(this.getEndpoint(), name, contentType, accept, - request, requestOptions, context)); - } - - /** - * The uploadFile operation. - * - * @param name A sequence of textual characters. - * @param request The request parameter. - * @param requestOptions The options to configure the HTTP request before HTTP client sends it. - * @throws HttpResponseException thrown if the request is rejected by server. - * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. - * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. - * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. - * @return the {@link Response}. - */ - @ServiceMethod(returns = ReturnType.SINGLE) - public Response uploadFileWithResponse(String name, BinaryData request, RequestOptions requestOptions) { - final String contentType = "multipart/form-data"; - final String accept = "application/json"; - return service.uploadFileSync(this.getEndpoint(), name, contentType, accept, request, requestOptions, - Context.NONE); - } } diff --git a/typespec-tests/src/main/java/com/cadl/multipart/implementation/models/package-info.java b/typespec-tests/src/main/java/com/cadl/multipart/implementation/models/package-info.java deleted file mode 100644 index 8d62afee6d..0000000000 --- a/typespec-tests/src/main/java/com/cadl/multipart/implementation/models/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// Code generated by Microsoft (R) TypeSpec Code Generator. - -/** - * - * Package containing the data models for Multipart. - * - */ -package com.cadl.multipart.implementation.models; diff --git a/typespec-tests/src/main/java/com/cadl/optional/models/Optional.java b/typespec-tests/src/main/java/com/cadl/optional/models/Optional.java index 89521feb9e..8efd0c185e 100644 --- a/typespec-tests/src/main/java/com/cadl/optional/models/Optional.java +++ b/typespec-tests/src/main/java/com/cadl/optional/models/Optional.java @@ -155,7 +155,11 @@ public Optional(boolean booleanRequired, Boolean booleanRequiredNullable, String this.booleanRequiredNullable = booleanRequiredNullable; this.stringRequired = stringRequired; this.stringRequiredNullable = stringRequiredNullable; - this.epochDateTimeRequiredNullable = epochDateTimeRequiredNullable.toEpochSecond(); + if (epochDateTimeRequiredNullable == null) { + this.epochDateTimeRequiredNullable = null; + } else { + this.epochDateTimeRequiredNullable = epochDateTimeRequiredNullable.toEpochSecond(); + } } /** diff --git a/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassBothMismatch.java b/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassBothMismatch.java index 6a01f046e4..6979c40eb3 100644 --- a/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassBothMismatch.java +++ b/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassBothMismatch.java @@ -35,7 +35,11 @@ public final class SubClassBothMismatch extends SuperClassMismatch { @Generated public SubClassBothMismatch(OffsetDateTime dateTimeRfc7231, byte[] base64url) { super(dateTimeRfc7231); - this.base64url = Base64Url.encode(base64url); + if (base64url == null) { + this.base64url = null; + } else { + this.base64url = Base64Url.encode(base64url); + } } /** diff --git a/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassMismatch.java b/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassMismatch.java index 5f9be5ee5a..9ab8b49a02 100644 --- a/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassMismatch.java +++ b/typespec-tests/src/main/java/com/cadl/wiretype/models/SubClassMismatch.java @@ -35,7 +35,11 @@ public final class SubClassMismatch extends SuperClass { @Generated public SubClassMismatch(OffsetDateTime dateTime, OffsetDateTime dateTimeRfc7231) { super(dateTime); - this.dateTimeRfc7231 = new DateTimeRfc1123(dateTimeRfc7231); + if (dateTimeRfc7231 == null) { + this.dateTimeRfc7231 = null; + } else { + this.dateTimeRfc7231 = new DateTimeRfc1123(dateTimeRfc7231); + } } /** diff --git a/typespec-tests/src/main/java/com/cadl/wiretype/models/SuperClassMismatch.java b/typespec-tests/src/main/java/com/cadl/wiretype/models/SuperClassMismatch.java index ddfc1f6115..31e904b081 100644 --- a/typespec-tests/src/main/java/com/cadl/wiretype/models/SuperClassMismatch.java +++ b/typespec-tests/src/main/java/com/cadl/wiretype/models/SuperClassMismatch.java @@ -33,7 +33,11 @@ public class SuperClassMismatch implements JsonSerializable */ @Generated public SuperClassMismatch(OffsetDateTime dateTimeRfc7231) { - this.dateTimeRfc7231 = new DateTimeRfc1123(dateTimeRfc7231); + if (dateTimeRfc7231 == null) { + this.dateTimeRfc7231 = null; + } else { + this.dateTimeRfc7231 = new DateTimeRfc1123(dateTimeRfc7231); + } } /** diff --git a/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlArrayBytesProperty.java b/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlArrayBytesProperty.java index 819e30e400..d1da537656 100644 --- a/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlArrayBytesProperty.java +++ b/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlArrayBytesProperty.java @@ -33,7 +33,11 @@ public final class Base64urlArrayBytesProperty implements JsonSerializable value) { - this.value = value.stream().map(el -> Base64Url.encode(el)).collect(java.util.stream.Collectors.toList()); + if (value == null) { + this.value = null; + } else { + this.value = value.stream().map(el -> Base64Url.encode(el)).collect(java.util.stream.Collectors.toList()); + } } /** diff --git a/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlBytesProperty.java b/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlBytesProperty.java index 752cd6a48b..38789ff8e5 100644 --- a/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlBytesProperty.java +++ b/typespec-tests/src/main/java/com/encode/bytes/models/Base64urlBytesProperty.java @@ -32,7 +32,11 @@ public final class Base64urlBytesProperty implements JsonSerializable value) { - this.value = value.stream().map(el -> el.toEpochSecond()).collect(java.util.stream.Collectors.toList()); + if (value == null) { + this.value = null; + } else { + this.value = value.stream().map(el -> el.toEpochSecond()).collect(java.util.stream.Collectors.toList()); + } } /** diff --git a/typespec-tests/src/main/java/com/encode/datetime/models/UnixTimestampDatetimeProperty.java b/typespec-tests/src/main/java/com/encode/datetime/models/UnixTimestampDatetimeProperty.java index fd7e74decc..9ae4f679ec 100644 --- a/typespec-tests/src/main/java/com/encode/datetime/models/UnixTimestampDatetimeProperty.java +++ b/typespec-tests/src/main/java/com/encode/datetime/models/UnixTimestampDatetimeProperty.java @@ -33,7 +33,11 @@ public final class UnixTimestampDatetimeProperty implements JsonSerializable value) { - this.value = value.stream() - .map(el -> (double) el.toNanos() / 1000_000_000L) - .collect(java.util.stream.Collectors.toList()); + if (value == null) { + this.value = null; + } else { + this.value = value.stream() + .map(el -> (double) el.toNanos() / 1000_000_000L) + .collect(java.util.stream.Collectors.toList()); + } } /** diff --git a/typespec-tests/src/main/java/com/encode/duration/models/FloatSecondsDurationProperty.java b/typespec-tests/src/main/java/com/encode/duration/models/FloatSecondsDurationProperty.java index 3e723ede91..ca02988845 100644 --- a/typespec-tests/src/main/java/com/encode/duration/models/FloatSecondsDurationProperty.java +++ b/typespec-tests/src/main/java/com/encode/duration/models/FloatSecondsDurationProperty.java @@ -31,7 +31,11 @@ public final class FloatSecondsDurationProperty implements JsonSerializable; - epochDateTimeRequiredNullable: epochDateTime | null; - epochDateTimeNullable?: epochDateTime; + + @encode(DateTimeKnownEncoding.unixTimestamp, int64) + epochDateTimeRequiredNullable: utcDateTime | null; + + @encode(DateTimeKnownEncoding.unixTimestamp, int64) + epochDateTimeNullable?: utcDateTime; } model Immutable { diff --git a/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsParentRequiredFields.java b/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsParentRequiredFields.java index 5f3466b423..b9ae40c7b2 100644 --- a/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsParentRequiredFields.java +++ b/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsParentRequiredFields.java @@ -50,7 +50,11 @@ private TransformationAsParentRequiredFields(OffsetDateTime rfc1123Required, Str byte[] urlBase64EncodedRequired, OffsetDateTime unixTimeLongRequired, OffsetDateTime unixTimeDateTimeRequired, OffsetDateTime rfc1123RequiredChild) { super(rfc1123Required, nameRequired, urlBase64EncodedRequired, unixTimeLongRequired, unixTimeDateTimeRequired); - this.rfc1123RequiredChild = new DateTimeRfc1123(rfc1123RequiredChild); + if (rfc1123RequiredChild == null) { + this.rfc1123RequiredChild = null; + } else { + this.rfc1123RequiredChild = new DateTimeRfc1123(rfc1123RequiredChild); + } } /** diff --git a/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsRequiredFields.java b/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsRequiredFields.java index 8fc6f39d17..31a9ed4f1c 100644 --- a/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsRequiredFields.java +++ b/vanilla-tests/src/main/java/fixtures/requiredfieldsascotrargstransformation/models/TransformationAsRequiredFields.java @@ -68,10 +68,22 @@ public class TransformationAsRequiredFields implements JsonSerializable