-
Notifications
You must be signed in to change notification settings - Fork 216
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
http-client-java, accessor to subclient #5027
base: main
Are you sure you want to change the base?
Changes from all commits
73ba7b8
ee6ece7
573d4ae
3080a8b
a27756c
d377855
703d968
26357b0
6b1c7b4
7f5530f
f073867
4299f4f
80e0b10
da412d3
f201ee2
63edeb5
928eeb7
f1c5f9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -496,106 +496,120 @@ export class CodeModelBuilder { | |
|
||
const sdkPackage = this.sdkContext.sdkPackage; | ||
for (const client of sdkPackage.clients) { | ||
let clientName = client.name; | ||
let javaNamespace = this.getJavaNamespace(this.namespace); | ||
const clientFullName = client.name; | ||
const clientNameSegments = clientFullName.split("."); | ||
if (clientNameSegments.length > 1) { | ||
clientName = clientNameSegments.at(-1)!; | ||
const clientSubNamespace = clientNameSegments.slice(0, -1).join("."); | ||
javaNamespace = this.getJavaNamespace(this.namespace + "." + clientSubNamespace); | ||
} | ||
|
||
const codeModelClient = new CodeModelClient(clientName, client.doc ?? "", { | ||
summary: client.summary, | ||
language: { | ||
default: { | ||
namespace: this.namespace, | ||
}, | ||
java: { | ||
namespace: javaNamespace, | ||
}, | ||
this.processClient(client); | ||
} | ||
} | ||
|
||
private processClient(client: SdkClientType<SdkHttpOperation>): CodeModelClient { | ||
let clientName = client.name; | ||
let javaNamespace = this.getJavaNamespace(this.namespace); | ||
const clientFullName = client.name; | ||
const clientNameSegments = clientFullName.split("."); | ||
if (clientNameSegments.length > 1) { | ||
clientName = clientNameSegments.at(-1)!; | ||
const clientSubNamespace = clientNameSegments.slice(0, -1).join("."); | ||
javaNamespace = this.getJavaNamespace(this.namespace + "." + clientSubNamespace); | ||
} | ||
|
||
const codeModelClient = new CodeModelClient(clientName, client.doc ?? "", { | ||
summary: client.summary, | ||
language: { | ||
default: { | ||
namespace: this.namespace, | ||
}, | ||
java: { | ||
namespace: javaNamespace, | ||
}, | ||
}, | ||
|
||
// at present, use global security definition | ||
security: this.codeModel.security, | ||
}); | ||
codeModelClient.crossLanguageDefinitionId = client.crossLanguageDefinitionId; | ||
// at present, use global security definition | ||
security: this.codeModel.security, | ||
}); | ||
codeModelClient.crossLanguageDefinitionId = client.crossLanguageDefinitionId; | ||
|
||
// versioning | ||
const versions = client.apiVersions; | ||
if (versions && versions.length > 0) { | ||
if (!this.sdkContext.apiVersion || ["all", "latest"].includes(this.sdkContext.apiVersion)) { | ||
this.apiVersion = versions[versions.length - 1]; | ||
} else { | ||
this.apiVersion = versions.find((it: string) => it === this.sdkContext.apiVersion); | ||
if (!this.apiVersion) { | ||
throw new Error("Unrecognized api-version: " + this.sdkContext.apiVersion); | ||
} | ||
// versioning | ||
const versions = client.apiVersions; | ||
if (versions && versions.length > 0) { | ||
if (!this.sdkContext.apiVersion || ["all", "latest"].includes(this.sdkContext.apiVersion)) { | ||
this.apiVersion = versions[versions.length - 1]; | ||
} else { | ||
this.apiVersion = versions.find((it: string) => it === this.sdkContext.apiVersion); | ||
if (!this.apiVersion) { | ||
throw new Error("Unrecognized api-version: " + this.sdkContext.apiVersion); | ||
} | ||
} | ||
|
||
codeModelClient.apiVersions = []; | ||
for (const version of this.getFilteredApiVersions( | ||
this.apiVersion, | ||
versions, | ||
this.options["service-version-exclude-preview"], | ||
)) { | ||
const apiVersion = new ApiVersion(); | ||
apiVersion.version = version; | ||
codeModelClient.apiVersions.push(apiVersion); | ||
} | ||
codeModelClient.apiVersions = []; | ||
for (const version of this.getFilteredApiVersions( | ||
this.apiVersion, | ||
versions, | ||
this.options["service-version-exclude-preview"], | ||
)) { | ||
const apiVersion = new ApiVersion(); | ||
apiVersion.version = version; | ||
codeModelClient.apiVersions.push(apiVersion); | ||
} | ||
} | ||
|
||
// client initialization | ||
let baseUri = "{endpoint}"; | ||
let hostParameters: Parameter[] = []; | ||
client.initialization.properties.forEach((initializationProperty) => { | ||
if (initializationProperty.kind === "endpoint") { | ||
let sdkPathParameters: SdkPathParameter[] = []; | ||
if (initializationProperty.type.kind === "union") { | ||
if (initializationProperty.type.variantTypes.length === 2) { | ||
// only get the sdkPathParameters from the endpoint whose serverUrl is not {"endpoint"} | ||
for (const endpointType of initializationProperty.type.variantTypes) { | ||
if (endpointType.kind === "endpoint" && endpointType.serverUrl !== "{endpoint}") { | ||
sdkPathParameters = endpointType.templateArguments; | ||
baseUri = endpointType.serverUrl; | ||
} | ||
// client initialization | ||
let baseUri = "{endpoint}"; | ||
let hostParameters: Parameter[] = []; | ||
client.initialization.properties.forEach((initializationProperty) => { | ||
if (initializationProperty.kind === "endpoint") { | ||
let sdkPathParameters: SdkPathParameter[] = []; | ||
if (initializationProperty.type.kind === "union") { | ||
if (initializationProperty.type.variantTypes.length === 2) { | ||
// only get the sdkPathParameters from the endpoint whose serverUrl is not {"endpoint"} | ||
for (const endpointType of initializationProperty.type.variantTypes) { | ||
if (endpointType.kind === "endpoint" && endpointType.serverUrl !== "{endpoint}") { | ||
sdkPathParameters = endpointType.templateArguments; | ||
baseUri = endpointType.serverUrl; | ||
} | ||
} else if (initializationProperty.type.variantTypes.length > 2) { | ||
throw new Error("Multiple server url defined for one client is not supported yet."); | ||
} | ||
} else if (initializationProperty.type.kind === "endpoint") { | ||
sdkPathParameters = initializationProperty.type.templateArguments; | ||
baseUri = initializationProperty.type.serverUrl; | ||
} else if (initializationProperty.type.variantTypes.length > 2) { | ||
throw new Error("Multiple server url defined for one client is not supported yet."); | ||
} | ||
|
||
hostParameters = this.processHostParameters(sdkPathParameters); | ||
codeModelClient.addGlobalParameters(hostParameters); | ||
} else if (initializationProperty.type.kind === "endpoint") { | ||
sdkPathParameters = initializationProperty.type.templateArguments; | ||
baseUri = initializationProperty.type.serverUrl; | ||
} | ||
}); | ||
|
||
const clientContext = new ClientContext( | ||
baseUri, | ||
hostParameters, | ||
codeModelClient.globalParameters!, | ||
codeModelClient.apiVersions, | ||
); | ||
|
||
// preprocess operation groups and operations | ||
// operations without operation group | ||
const serviceMethodsWithoutSubClient = this.listServiceMethodsUnderClient(client); | ||
let codeModelGroup = new OperationGroup(""); | ||
for (const serviceMethod of serviceMethodsWithoutSubClient) { | ||
if (!this.needToSkipProcessingOperation(serviceMethod.__raw, clientContext)) { | ||
codeModelGroup.addOperation(this.processOperation(serviceMethod, clientContext, "")); | ||
} | ||
hostParameters = this.processHostParameters(sdkPathParameters); | ||
codeModelClient.addGlobalParameters(hostParameters); | ||
} | ||
if (codeModelGroup.operations?.length > 0) { | ||
codeModelClient.operationGroups.push(codeModelGroup); | ||
}); | ||
|
||
const clientContext = new ClientContext( | ||
baseUri, | ||
hostParameters, | ||
codeModelClient.globalParameters!, | ||
codeModelClient.apiVersions, | ||
); | ||
|
||
const enableSubclient: boolean = Boolean(this.options["enable-subclient"]); | ||
|
||
// preprocess operation groups and operations | ||
// operations without operation group | ||
const serviceMethodsWithoutSubClient = this.listServiceMethodsUnderClient(client); | ||
let codeModelGroup = new OperationGroup(""); | ||
for (const serviceMethod of serviceMethodsWithoutSubClient) { | ||
if (!this.needToSkipProcessingOperation(serviceMethod.__raw, clientContext)) { | ||
codeModelGroup.addOperation(this.processOperation(serviceMethod, clientContext, "")); | ||
} | ||
} | ||
if (codeModelGroup.operations?.length > 0 || enableSubclient) { | ||
codeModelClient.operationGroups.push(codeModelGroup); | ||
} | ||
|
||
const subClients = this.listSubClientsUnderClient(client, !enableSubclient); | ||
if (enableSubclient) { | ||
// subclient, no operation group | ||
for (const subClient of subClients) { | ||
const codeModelSubclient = this.processClient(subClient); | ||
codeModelClient.addSubClient(codeModelSubclient); | ||
} | ||
} else { | ||
// operations under operation groups | ||
const subClients = this.listSubClientsUnderClient(client, true, true); | ||
for (const subClient of subClients) { | ||
const serviceMethods = this.listServiceMethodsUnderClient(subClient); | ||
// operation group with no operation is skipped | ||
|
@@ -611,48 +625,51 @@ export class CodeModelBuilder { | |
codeModelClient.operationGroups.push(codeModelGroup); | ||
} | ||
} | ||
this.codeModel.clients.push(codeModelClient); | ||
} | ||
|
||
this.codeModel.clients.push(codeModelClient); | ||
|
||
// postprocess for ServiceVersion | ||
let apiVersionSameForAllClients = true; | ||
let sharedApiVersions = undefined; | ||
// postprocess for ServiceVersion | ||
let apiVersionSameForAllClients = true; | ||
let sharedApiVersions = undefined; | ||
for (const client of this.codeModel.clients) { | ||
const apiVersions = client.apiVersions; | ||
if (!apiVersions) { | ||
// client does not have apiVersions | ||
apiVersionSameForAllClients = false; | ||
} else if (!sharedApiVersions) { | ||
// first client, set it to sharedApiVersions | ||
sharedApiVersions = apiVersions; | ||
} else { | ||
apiVersionSameForAllClients = isEqual(sharedApiVersions, apiVersions); | ||
} | ||
if (!apiVersionSameForAllClients) { | ||
break; | ||
} | ||
} | ||
if (apiVersionSameForAllClients) { | ||
const serviceVersion = getServiceVersion(this.codeModel); | ||
for (const client of this.codeModel.clients) { | ||
const apiVersions = client.apiVersions; | ||
if (!apiVersions) { | ||
// client does not have apiVersions | ||
apiVersionSameForAllClients = false; | ||
} else if (!sharedApiVersions) { | ||
// first client, set it to sharedApiVersions | ||
sharedApiVersions = apiVersions; | ||
} else { | ||
apiVersionSameForAllClients = isEqual(sharedApiVersions, apiVersions); | ||
} | ||
if (!apiVersionSameForAllClients) { | ||
break; | ||
} | ||
client.serviceVersion = serviceVersion; | ||
} | ||
if (apiVersionSameForAllClients) { | ||
const serviceVersion = getServiceVersion(this.codeModel); | ||
for (const client of this.codeModel.clients) { | ||
client.serviceVersion = serviceVersion; | ||
} | ||
} else { | ||
for (const client of this.codeModel.clients) { | ||
const apiVersions = client.apiVersions; | ||
if (apiVersions) { | ||
client.serviceVersion = getServiceVersion(client); | ||
} | ||
} else { | ||
for (const client of this.codeModel.clients) { | ||
const apiVersions = client.apiVersions; | ||
if (apiVersions) { | ||
client.serviceVersion = getServiceVersion(client); | ||
} | ||
} | ||
} | ||
|
||
return codeModelClient; | ||
} | ||
|
||
private listSubClientsUnderClient( | ||
client: SdkClientType<SdkHttpOperation>, | ||
includeNestedOperationGroups: boolean, | ||
isRootClient: boolean, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
includeNestedSubClients: boolean, | ||
): SdkClientType<SdkHttpOperation>[] { | ||
const operationGroups: SdkClientType<SdkHttpOperation>[] = []; | ||
const isRootClient = !client.parent; | ||
const subClients: SdkClientType<SdkHttpOperation>[] = []; | ||
for (const method of client.methods) { | ||
if (method.kind === "clientaccessor") { | ||
const subClient = method.response; | ||
|
@@ -661,19 +678,18 @@ export class CodeModelBuilder { | |
subClient.name = | ||
removeClientSuffix(client.name) + removeClientSuffix(pascalCase(subClient.name)); | ||
} | ||
operationGroups.push(subClient); | ||
if (includeNestedOperationGroups) { | ||
subClients.push(subClient); | ||
if (includeNestedSubClients) { | ||
for (const operationGroup of this.listSubClientsUnderClient( | ||
subClient, | ||
includeNestedOperationGroups, | ||
false, | ||
includeNestedSubClients, | ||
)) { | ||
operationGroups.push(operationGroup); | ||
subClients.push(operationGroup); | ||
} | ||
} | ||
} | ||
} | ||
return operationGroups; | ||
return subClients; | ||
} | ||
|
||
private listServiceMethodsUnderClient( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,8 @@ export interface EmitterOptions { | |
|
||
"group-etag-headers"?: boolean; | ||
|
||
"enable-subclient"?: boolean; | ||
|
||
"advanced-versioning"?: boolean; | ||
"api-version"?: string; | ||
"service-version-exclude-preview"?: boolean; | ||
|
@@ -78,7 +80,7 @@ const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = { | |
|
||
"enable-sync-stack": { type: "boolean", nullable: true, default: true }, | ||
"stream-style-serialization": { type: "boolean", nullable: true, default: true }, | ||
"use-object-for-unknown": { type: "boolean", nullable: true, default: true }, | ||
"use-object-for-unknown": { type: "boolean", nullable: true, default: false }, | ||
|
||
// customization | ||
"partial-update": { type: "boolean", nullable: true, default: false }, | ||
|
@@ -90,6 +92,8 @@ const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = { | |
|
||
"group-etag-headers": { type: "boolean", nullable: true }, | ||
|
||
"enable-subclient": { type: "boolean", nullable: true, default: false }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to set the option to true in our test to see the impact? (at least for some of the tests) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we'd plan to set it to true for the subclient related tests (and for the whole unbranded too, if we separate the flavors). Currently my cadl-ranch PR is not merged, so we don't have them now. (test case, the basic one, is written before the http-specs package, I would need to migrate it first; and we will need more tests on advanced cases) |
||
|
||
"advanced-versioning": { type: "boolean", nullable: true, default: false }, | ||
"api-version": { type: "string", nullable: true }, | ||
"service-version-exclude-preview": { type: "boolean", nullable: true, default: false }, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most is refactor (extract code to
processClient
, as we now need to call it recursively).Here is the main change, with the option, we would not do operation group, and every client is a client (or subclient).