Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java generator, support non-string expandable enum for TypeSpec #4492

Merged
merged 24 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core</artifactId>
<version>1.51.0</version>
<version>1.52.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.microsoft.typespec.http.client.generator.core.mapper;

import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.ChoiceSchema;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.EnumType;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.IType;

Expand Down Expand Up @@ -47,6 +48,6 @@ public IType map(ChoiceSchema enumType) {
}

private IType createChoiceType(ChoiceSchema enumType) {
return MapperUtils.createEnumType(enumType, true, true);
return MapperUtils.createEnumType(enumType, true, true, "getValue", null, ClassType.STRING);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,28 @@
public final class MapperUtils {
/**
* Create enum client type from code model.
* @param enumType code model schema for enum
* @param expandable whether it's expandable enum
*
* @param enumType code model schema for enum
* @param expandable whether it's expandable enum
* @param useCodeModelNameForEnumMember whether to use code model enum member name for client enum member name
* @return enum client type
*/
public static IType createEnumType(ChoiceSchema enumType, boolean expandable, boolean useCodeModelNameForEnumMember) {
return createEnumType(enumType, expandable, useCodeModelNameForEnumMember, null, null, null);
}

/**
* Create enum client type from code model.
*
* @param enumType code model schema for enum
* @param expandable whether it's expandable enum
* @param useCodeModelNameForEnumMember whether to use code model enum member name for client enum member name
* @param serializationMethodName method name for serialization
* @param deserializationMethodName method name for deserialization
* @param wireType wire type for serialization, if null, will default to element type of the enum
* @return enum client type
*/
public static IType createEnumType(ChoiceSchema enumType, boolean expandable, boolean useCodeModelNameForEnumMember, String serializationMethodName, String deserializationMethodName, IType wireType) {
JavaSettings settings = JavaSettings.getInstance();
String enumTypeName = enumType.getLanguage().getJava().getName();

Expand Down Expand Up @@ -82,17 +98,20 @@ public static IType createEnumType(ChoiceSchema enumType, boolean expandable, bo
}

return new EnumType.Builder()
.packageName(enumPackage)
.name(enumTypeName)
.description(description)
.expandable(expandable)
.values(enumValues)
.elementType(Mappers.getSchemaMapper().map(enumType.getChoiceType()))
.implementationDetails(new ImplementationDetails.Builder()
.usages(SchemaUtil.mapSchemaContext(enumType.getUsage()))
.build())
.crossLanguageDefinitionId(enumType.getCrossLanguageDefinitionId())
.build();
.packageName(enumPackage)
.name(enumTypeName)
.description(description)
.expandable(expandable)
.values(enumValues)
.elementType(Mappers.getSchemaMapper().map(enumType.getChoiceType()))
.implementationDetails(new ImplementationDetails.Builder()
.usages(SchemaUtil.mapSchemaContext(enumType.getUsage()))
.build())
.crossLanguageDefinitionId(enumType.getCrossLanguageDefinitionId())
.fromMethodName(deserializationMethodName)
.toMethodName(serializationMethodName)
.wireType(wireType)
.build();
}
}

Expand Down
weidongxu-microsoft marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public IType map(Schema value) {
private IType createSchemaType(Schema value) {
if (value instanceof PrimitiveSchema) {
return Mappers.getPrimitiveMapper().map((PrimitiveSchema) value);
} else if (value instanceof ChoiceSchema) {
return Mappers.getChoiceMapper().map((ChoiceSchema) value);
} else if (value instanceof SealedChoiceSchema) {
return Mappers.getSealedChoiceMapper().map((SealedChoiceSchema) value);
} else if (value instanceof ChoiceSchema) {
XiaofeiCao marked this conversation as resolved.
Show resolved Hide resolved
return Mappers.getChoiceMapper().map((ChoiceSchema) value);
} else if (value instanceof ArraySchema) {
return Mappers.getArrayMapper().map((ArraySchema) value);
} else if (value instanceof DictionarySchema) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.microsoft.typespec.http.client.generator.core.model.clientmodel;

import com.azure.core.util.ExpandableEnum;
import com.microsoft.typespec.http.client.generator.core.extension.model.extensionmodel.XmsExtensions;
import com.microsoft.typespec.http.client.generator.core.extension.plugin.JavaSettings;
import com.microsoft.typespec.http.client.generator.core.util.TemplateUtil;
Expand Down Expand Up @@ -159,6 +160,7 @@ private static ClassType.Builder getClassTypeBuilder(Class<?> classKey) {
public static final ClassType RESPONSE = getClassTypeBuilder(Response.class).build();
public static final ClassType SIMPLE_RESPONSE = getClassTypeBuilder(SimpleResponse.class).build();
public static final ClassType EXPANDABLE_STRING_ENUM = getClassTypeBuilder(ExpandableStringEnum.class).build();
public static final ClassType EXPANDABLE_ENUM = getClassTypeBuilder(ExpandableEnum.class).build();
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.microsoft.typespec.http.client.generator.core.model.clientmodel;

import com.azure.core.util.CoreUtils;
import com.microsoft.typespec.http.client.generator.core.util.CodeNamer;

import java.util.List;
Expand Down Expand Up @@ -35,19 +36,26 @@ public class EnumType implements IType {
private final ImplementationDetails implementationDetails;

private String crossLanguageDefinitionId;
private final String fromMethodName;
private final String toMethodName;
private final IType wireType;

/**
* Create a new Enum with the provided properties.
* @param name The name of the new Enum.
* @param description The description of the Enum.
* @param expandable Whether this will be an ExpandableStringEnum type.
* @param values The values of the Enum.
*
* @param name The name of the new Enum.
* @param description The description of the Enum.
* @param expandable Whether this will be an ExpandableStringEnum type.
* @param values The values of the Enum.
* @param fromMethodName The method name used to convert JSON to the enum type.
* @param toMethodName The method name used to convert the enum type to JSON.
* @param wireType The actual wire type in JSON form.
*/
private EnumType(String packageKeyword, String name, String description,
boolean expandable, List<ClientEnumValue> values,
IType elementType,
ImplementationDetails implementationDetails,
String crossLanguageDefinitionId) {
String crossLanguageDefinitionId, String fromMethodName, String toMethodName, IType wireType) {
this.name = name;
this.packageName = packageKeyword;
this.description = description;
Expand All @@ -56,6 +64,9 @@ private EnumType(String packageKeyword, String name, String description,
this.elementType = elementType;
this.implementationDetails = implementationDetails;
this.crossLanguageDefinitionId = crossLanguageDefinitionId;
this.fromMethodName = fromMethodName;
this.toMethodName = toMethodName;
this.wireType = wireType;
}

public String getCrossLanguageDefinitionId() {
Expand Down Expand Up @@ -134,7 +145,9 @@ public final String defaultValueExpression(String sourceExpression) {
* @return The method name used to convert JSON to the enum type.
*/
public final String getFromMethodName() {
return "from" + CodeNamer.toPascalCase(elementType.getClientType().toString());
return CoreUtils.isNullOrEmpty(fromMethodName)
? "from" + CodeNamer.toPascalCase(elementType.getClientType().toString())
: fromMethodName;
}

/**
Expand All @@ -143,7 +156,9 @@ public final String getFromMethodName() {
* @return The method name used to convert the enum type to JSON.
*/
public final String getToMethodName() {
return "to" + CodeNamer.toPascalCase(elementType.getClientType().toString());
return CoreUtils.isNullOrEmpty(toMethodName)
? "to" + CodeNamer.toPascalCase(elementType.getClientType().toString())
: toMethodName;
}

@Override
Expand Down Expand Up @@ -190,7 +205,7 @@ public String jsonSerializationMethodCall(String jsonWriterName, String fieldNam
? valueGetter + "." + getToMethodName() + "()"
: valueGetter + " == null ? null : " + valueGetter + "." + getToMethodName() + "()";

return elementType.asNullable().jsonSerializationMethodCall(jsonWriterName, fieldName, actualValueGetter,
return wireType.asNullable().jsonSerializationMethodCall(jsonWriterName, fieldName, actualValueGetter,
jsonMergePatch);
weidongxu-microsoft marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -231,6 +246,9 @@ public static class Builder {
private ImplementationDetails implementationDetails;

private String crossLanguageDefinitionId;
private String fromMethodName;
private String toMethodName;
private IType wireType;

/**
* Sets the name of the Enum.
Expand Down Expand Up @@ -309,10 +327,29 @@ public Builder crossLanguageDefinitionId(String crossLanguageDefinitionId) {
return this;
}

public Builder fromMethodName(String fromMethodName) {
this.fromMethodName = fromMethodName;
return this;
}

public Builder toMethodName(String toMethodName) {
this.toMethodName = toMethodName;
return this;
}

public Builder wireType(IType wireType) {
this.wireType = wireType;
return this;
}

/**
* @return an immutable EnumType instance with the configurations on this builder.
*/
public EnumType build() {
IType wireType = this.wireType;
if (wireType == null) {
wireType = elementType;
}
return new EnumType(
packageName,
name,
Expand All @@ -321,8 +358,10 @@ public EnumType build() {
values,
elementType,
implementationDetails,
crossLanguageDefinitionId
);
crossLanguageDefinitionId,
fromMethodName,
toMethodName,
wireType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final void write(EnumType enumType, JavaFile javaFile) {

if (enumType.getExpandable()) {
if(settings.isBranded()) {
writeExpandableStringEnum(enumType, javaFile, settings);
writeBrandedExpandableEnum(enumType, javaFile, settings);
} else {
writeExpandableStringEnumInterface(enumType, javaFile, settings);
}
Expand All @@ -49,6 +49,17 @@ public final void write(EnumType enumType, JavaFile javaFile) {
}
}

/**
* Extension point for expandable enum implementation of branded flavor.
*
* @param enumType enumType to write implementation
* @param javaFile javaFile to write into
* @param settings {@link JavaSettings} instance
*/
protected void writeBrandedExpandableEnum(EnumType enumType, JavaFile javaFile, JavaSettings settings) {
writeExpandableStringEnum(enumType, javaFile, settings);
}

private void writeExpandableStringEnumInterface(EnumType enumType, JavaFile javaFile, JavaSettings settings) {
Set<String> imports = new HashSet<>();
imports.add("java.util.Collection");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.ChoiceSchema;
import com.microsoft.typespec.http.client.generator.core.mapper.ChoiceMapper;
import com.microsoft.typespec.http.client.generator.core.mapper.MapperUtils;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.IType;

public class FluentChoiceMapper extends ChoiceMapper {
Expand All @@ -18,6 +19,6 @@ public static FluentChoiceMapper getInstance() {

@Override
public IType map(ChoiceSchema enumType) {
return MapperUtils.createEnumType(enumType, true, false);
return MapperUtils.createEnumType(enumType, true, false, "getValue", null, ClassType.STRING);
weidongxu-microsoft marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,28 +113,7 @@ $generateScript = {
}
}

Set-Location (Resolve-Path (Join-Path $PSScriptRoot '..' '..'))

npm install
npm run build
npm pack

Set-Location $PSScriptRoot


if (Test-Path node_modules) {
Remove-Item node_modules -Recurse -Force
}

if (Test-Path package-lock.json) {
Remove-Item package-lock.json
}

# delete output
if (Test-Path tsp-output) {
Remove-Item tsp-output -Recurse -Force
}
npm install
./Setup.ps1

New-Item -Path ./existingcode/src/main/java/com/cadl/ -ItemType Directory -Force | Out-Null

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# re-build http-client-java
Set-Location (Resolve-Path (Join-Path $PSScriptRoot '..' '..'))

./Setup.ps1

Set-Location $PSScriptRoot

npm run clean && npm install
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core</artifactId>
<version>1.51.0</version>
<version>1.52.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
Expand Down
Loading
Loading