Skip to content

Commit

Permalink
tsp, improve multipart, ignore readonly field (#2614)
Browse files Browse the repository at this point in the history
* ignore read-only field in multipart

* bump version 0.15.2
  • Loading branch information
weidongxu-microsoft authored Mar 8, 2024
1 parent 20a8da4 commit 72ce304
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -655,74 +655,76 @@ private static String expressionMultipartFormDataToBinaryData(String name, Clien
StringBuilder builder = new StringBuilder().append("new MultipartFormDataHelper(requestOptions)");
for (ClientModelProperty property : model.getProperties()) {
String propertyGetExpression = name + "." + property.getGetterName() + "()";
if (isMultipartModel(property.getWireType())) {
// file, usually application/octet-stream

String fileExpression = propertyGetExpression + ".getContent()";
String contentTypeExpression = propertyGetExpression + ".getContentType()";
String filenameExpression = propertyGetExpression + ".getFilename()";
if (!property.isRequired()) {
fileExpression = nullableExpression.apply(propertyGetExpression, fileExpression);
contentTypeExpression = nullableExpression.apply(propertyGetExpression, contentTypeExpression);
filenameExpression = nullableExpression.apply(propertyGetExpression, filenameExpression);
}
if (!property.isReadOnly()) {
if (isMultipartModel(property.getWireType())) {
// file, usually application/octet-stream

String fileExpression = propertyGetExpression + ".getContent()";
String contentTypeExpression = propertyGetExpression + ".getContentType()";
String filenameExpression = propertyGetExpression + ".getFilename()";
if (!property.isRequired()) {
fileExpression = nullableExpression.apply(propertyGetExpression, fileExpression);
contentTypeExpression = nullableExpression.apply(propertyGetExpression, contentTypeExpression);
filenameExpression = nullableExpression.apply(propertyGetExpression, filenameExpression);
}

builder.append(String.format(
".serializeFileField(%1$s, %2$s, %3$s, %4$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
fileExpression,
contentTypeExpression,
filenameExpression
));
} else if (property.getWireType() instanceof ListType && isMultipartModel(((ListType) property.getWireType()).getElementType())) {
// file array

// For now, we use 3 List, as we do not wish the Helper class refer to different ##FileDetails model.
// Later, if we switch to a shared class in azure-core, we can change the implementation.
String className = ((ListType) property.getWireType()).getElementType().toString();
String streamExpressionFormat = "%1$s.stream().map(%2$s::%3$s).collect(Collectors.toList())";
String fileExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getContent");
String contentTypeExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getContentType");
String filenameExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getFilename");
if (!property.isRequired()) {
fileExpression = nullableExpression.apply(propertyGetExpression, fileExpression);
contentTypeExpression = nullableExpression.apply(propertyGetExpression, contentTypeExpression);
filenameExpression = nullableExpression.apply(propertyGetExpression, filenameExpression);
}
builder.append(String.format(
".serializeFileField(%1$s, %2$s, %3$s, %4$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
fileExpression,
contentTypeExpression,
filenameExpression
));
} else if (property.getWireType() instanceof ListType && isMultipartModel(((ListType) property.getWireType()).getElementType())) {
// file array

// For now, we use 3 List, as we do not wish the Helper class refer to different ##FileDetails model.
// Later, if we switch to a shared class in azure-core, we can change the implementation.
String className = ((ListType) property.getWireType()).getElementType().toString();
String streamExpressionFormat = "%1$s.stream().map(%2$s::%3$s).collect(Collectors.toList())";
String fileExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getContent");
String contentTypeExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getContentType");
String filenameExpression = String.format(streamExpressionFormat,
propertyGetExpression, className, "getFilename");
if (!property.isRequired()) {
fileExpression = nullableExpression.apply(propertyGetExpression, fileExpression);
contentTypeExpression = nullableExpression.apply(propertyGetExpression, contentTypeExpression);
filenameExpression = nullableExpression.apply(propertyGetExpression, filenameExpression);
}

builder.append(String.format(
".serializeFileFields(%1$s, %2$s, %3$s, %4$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
fileExpression,
contentTypeExpression,
filenameExpression
));
} else if (ClientModelUtil.isClientModel(property.getWireType())
|| property.getWireType() instanceof MapType
|| property.getWireType() instanceof IterableType) {
// application/json
builder.append(String.format(
".serializeJsonField(%1$s, %2$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
propertyGetExpression
));
} else {
// text/plain
String stringExpression = propertyGetExpression;
// convert to String
if (property.getWireType() instanceof PrimitiveType) {
stringExpression = String.format("String.valueOf(%s)", stringExpression);
} else if (property.getWireType() != ClassType.STRING) {
stringExpression = String.format("Objects.toString(%s)", stringExpression);
builder.append(String.format(
".serializeFileFields(%1$s, %2$s, %3$s, %4$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
fileExpression,
contentTypeExpression,
filenameExpression
));
} else if (ClientModelUtil.isClientModel(property.getWireType())
|| property.getWireType() instanceof MapType
|| property.getWireType() instanceof IterableType) {
// application/json
builder.append(String.format(
".serializeJsonField(%1$s, %2$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
propertyGetExpression
));
} else {
// text/plain
String stringExpression = propertyGetExpression;
// convert to String
if (property.getWireType() instanceof PrimitiveType) {
stringExpression = String.format("String.valueOf(%s)", stringExpression);
} else if (property.getWireType() != ClassType.STRING) {
stringExpression = String.format("Objects.toString(%s)", stringExpression);
}
builder.append(String.format(
".serializeTextField(%1$s, %2$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
stringExpression
));
}
builder.append(String.format(
".serializeTextField(%1$s, %2$s)",
ClassType.STRING.defaultValueExpression(property.getSerializedName()),
stringExpression
));
}
}
builder.append(".end().getRequestBody()");
Expand Down
4 changes: 4 additions & 0 deletions typespec-extension/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release History

## 0.15.2 (2024-03-08)

Compatible with compiler 0.54.

## 0.15.1 (2024-03-08)

Compatible with compiler 0.54.
Expand Down
4 changes: 2 additions & 2 deletions typespec-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion typespec-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure-tools/typespec-java",
"version": "0.15.1",
"version": "0.15.2",
"description": "TypeSpec library for emitting Java client from the TypeSpec REST protocol binding",
"keywords": [
"TypeSpec"
Expand Down
2 changes: 1 addition & 1 deletion typespec-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@azure-tools/cadl-ranch-specs": "0.31.2",
"@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.15.1.tgz"
"@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.15.2.tgz"
},
"devDependencies": {
"@typespec/prettier-plugin-typespec": "~0.54.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ public Mono<Void> uploadFile(String name, FileDataFileDetails 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public void uploadFile(String name, FileDataFileDetails 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ public final class UploadFileRequest {
@Generated
private final FileDataFileDetails fileData;

/*
* The readOnly property.
*/
@Generated
private String readOnly;

/*
* The constant property.
*/
@Generated
private final String constant = "constant";

/**
* Creates an instance of UploadFileRequest class.
*
Expand All @@ -38,4 +50,24 @@ public UploadFileRequest(FileDataFileDetails fileData) {
public FileDataFileDetails getFileData() {
return this.fileData;
}

/**
* Get the readOnly property: The readOnly property.
*
* @return the readOnly value.
*/
@Generated
public String getReadOnly() {
return this.readOnly;
}

/**
* Get the constant property: The constant property.
*
* @return the constant value.
*/
@Generated
public String getConstant() {
return this.constant;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"user": {
"user": "myOptionalUser"
},
"input": "myRequiredInput"
"input": "myRequiredInput",
"constant": "constant"
}
},
"responses": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"data_float": 14.0,
"title": "title",
"description": "description",
"status": "NotStarted"
"status": "NotStarted",
"constant": "constant"
}
},
"responses": {
Expand Down
5 changes: 5 additions & 0 deletions typespec-tests/tsp/multipart.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ op uploadFile(
@path name: string,
@header contentType: "multipart/form-data",
file_data: bytes,

// this field should not be serialized to form-data
@visibility("read") readOnly: string,

constant: "constant",
): OkResponse;

0 comments on commit 72ce304

Please sign in to comment.