Skip to content

Commit 79c3e7f

Browse files
committed
Introducing PollingMetadata class LRO operations (similar to PagingMetadata for pagable oepration
1 parent cfbbf85 commit 79c3e7f

File tree

2 files changed

+204
-1
lines changed

2 files changed

+204
-1
lines changed

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ClientMethodMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ private List<ClientMethod> createClientMethods(Operation operation, boolean isPr
435435
generateOnlyRequiredParameters, defaultOverloadType);
436436

437437
if (dpgMethodPollingDetailsWithModel != null) {
438-
// additional LRO method for data-plane, with intermediate/final type, for convenience of
438+
// additional LRO method for data-plane, with poll/final type, for convenience of
439439
// grow-up, it is public in implementation, but not exposed in wrapper client
440440
//
441441
final ImplementationDetails implementationDetails;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.typespec.http.client.generator.core.mapper;
5+
6+
import com.azure.core.http.HttpMethod;
7+
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.LongRunningMetadata;
8+
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.Operation;
9+
import com.microsoft.typespec.http.client.generator.core.extension.plugin.JavaSettings;
10+
import com.microsoft.typespec.http.client.generator.core.extension.plugin.PollingSettings;
11+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
12+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.IType;
13+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.MethodPollingDetails;
14+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.PrimitiveType;
15+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ProxyMethod;
16+
import com.microsoft.typespec.http.client.generator.core.util.MethodUtil;
17+
18+
/**
19+
* Type that holds polling information resolved for an {@link Operation}, and exposes a view of the metadata as
20+
* {@link MethodPollingDetails}.
21+
*/
22+
final class PollingMetadata {
23+
private final String pollingStrategy;
24+
private final String syncPollingStrategy;
25+
private final IType pollResultType;
26+
private final IType finalResultType;
27+
private final int pollIntervalInSeconds;
28+
private final HttpMethod httpMethod;
29+
30+
static PollingMetadata create(Operation operation, ProxyMethod proxyMethod, IType syncReturnType) {
31+
final JavaSettings settings = JavaSettings.getInstance();
32+
final PollingSettings pollingSettings = settings.getPollingSettings(proxyMethod.getOperationId());
33+
34+
if (pollingSettings == null) {
35+
return null;
36+
}
37+
38+
final HttpMethod httpMethod = MethodUtil.getHttpMethod(operation);
39+
final LongRunningMetadata lroMetadata = operation.getLroMetadata();
40+
if (lroMetadata == null || operation.getConvenienceApi() == null) {
41+
// Create 'PollingMetadata' from 'PollingSettings'.
42+
//
43+
if (settings.isFluent()) {
44+
return new PollingMetadata(pollingSettings.getStrategy(), pollingSettings.getSyncStrategy(),
45+
syncReturnType.asNullable(), syncReturnType.asNullable(),
46+
pollingSettings.getPollIntervalInSeconds(), httpMethod);
47+
}
48+
49+
final IType pollResultType = getPollResultType(pollingSettings, syncReturnType);
50+
final IType finalResultType;
51+
if (httpMethod == HttpMethod.DELETE) {
52+
finalResultType = PrimitiveType.VOID;
53+
} else {
54+
finalResultType = getFinalResultType(pollingSettings, syncReturnType);
55+
}
56+
return new PollingMetadata(pollingSettings.getStrategy(), pollingSettings.getSyncStrategy(), pollResultType,
57+
finalResultType, pollingSettings.getPollIntervalInSeconds(), httpMethod);
58+
} else {
59+
// Create 'PollingMetadata' from TypeSpec long-running metadata.
60+
// Note: Only TypeSpec would have 'Operation::LongRunningMetadata' available.
61+
//
62+
return create(pollingSettings, lroMetadata, httpMethod);
63+
}
64+
}
65+
66+
MethodPollingDetails asMethodPollingDetails() {
67+
return new MethodPollingDetails(pollingStrategy, syncPollingStrategy, pollResultType, finalResultType,
68+
pollIntervalInSeconds);
69+
}
70+
71+
boolean hasBinaryDataResultTypes() {
72+
if (ClassType.BINARY_DATA.equals(pollResultType)) {
73+
return ClassType.BINARY_DATA.equals(finalResultType) || ClassType.VOID.equals(finalResultType.asNullable());
74+
}
75+
return false;
76+
}
77+
78+
MethodPollingDetails asMethodPollingDetailsForBinaryDataResult() {
79+
final IType pollResultType = ClassType.BINARY_DATA;
80+
final IType finalResultType;
81+
if (httpMethod == HttpMethod.DELETE) {
82+
finalResultType = PrimitiveType.VOID;
83+
} else {
84+
finalResultType = ClassType.BINARY_DATA;
85+
}
86+
return new MethodPollingDetails(pollingStrategy, syncPollingStrategy, pollResultType, finalResultType,
87+
pollIntervalInSeconds);
88+
}
89+
90+
private static IType getPollResultType(PollingSettings pollingSettings, IType syncReturnType) {
91+
final IType pollResultType;
92+
if (pollingSettings.getPollResultType() != null) {
93+
pollResultType = createTypeFromModelName(pollingSettings.getPollResultType());
94+
} else {
95+
pollResultType = syncReturnType.asNullable();
96+
}
97+
if (pollResultType.asNullable() == ClassType.VOID) {
98+
// azure-core requires poll response to be non-null.
99+
return ClassType.BINARY_DATA;
100+
} else {
101+
return pollResultType;
102+
}
103+
}
104+
105+
private static IType getFinalResultType(PollingSettings pollingSettings, IType syncReturnType) {
106+
final IType finalResultType;
107+
if (pollingSettings.getFinalResultType() != null) {
108+
finalResultType = createTypeFromModelName(pollingSettings.getFinalResultType());
109+
} else {
110+
finalResultType = syncReturnType.asNullable();
111+
}
112+
if (finalResultType.asNullable() == ClassType.VOID) {
113+
// azure-core requires poll response to be non-null
114+
return ClassType.BINARY_DATA;
115+
} else {
116+
return finalResultType;
117+
}
118+
}
119+
120+
private static PollingMetadata create(PollingSettings pollingSettings, LongRunningMetadata lroMetadata,
121+
HttpMethod httpMethod) {
122+
assert pollingSettings != null && lroMetadata != null;
123+
124+
// Step_1: Resolve LRO poll and final result types.
125+
//
126+
final ObjectMapper objectMapper = Mappers.getObjectMapper();
127+
final IType pollResultType;
128+
if (pollingSettings.getPollResultType() != null) {
129+
// pollingSettings would take precedence over 'LongRunningMetadata'
130+
pollResultType = createTypeFromModelName(pollingSettings.getPollResultType());
131+
} else {
132+
pollResultType = objectMapper.map(lroMetadata.getPollResultType());
133+
}
134+
135+
final IType finalResultType;
136+
if (pollingSettings.getFinalResultType() != null) {
137+
finalResultType = createTypeFromModelName(pollingSettings.getFinalResultType());
138+
} else {
139+
if (lroMetadata.getFinalResultType() == null) {
140+
finalResultType = PrimitiveType.VOID;
141+
} else {
142+
finalResultType = objectMapper.map(lroMetadata.getFinalResultType());
143+
}
144+
}
145+
146+
// Step_2: Resolve LRO poll strategy.
147+
//
148+
final String pollingStrategy;
149+
final String syncPollingStrategy;
150+
final JavaSettings settings = JavaSettings.getInstance();
151+
final String packageName = settings.getPackage(settings.getImplementationSubpackage());
152+
if (lroMetadata.getPollingStrategy() != null) {
153+
final String strategyName = lroMetadata.getPollingStrategy().getLanguage().getJava().getName();
154+
final String strategyFqdnName = packageName + "." + strategyName;
155+
final String syncStrategyFqdnName = packageName + "." + "Sync" + strategyName;
156+
157+
if (lroMetadata.getFinalResultPropertySerializedName() != null) {
158+
final String finalResultArg
159+
= ClassType.STRING.defaultValueExpression(lroMetadata.getFinalResultPropertySerializedName());
160+
pollingStrategy = String.format(PollingSettings.INSTANTIATE_POLLING_STRATEGY_WITH_RESULT_FORMAT,
161+
strategyFqdnName, finalResultArg);
162+
syncPollingStrategy = String.format(PollingSettings.INSTANTIATE_POLLING_STRATEGY_WITH_RESULT_FORMAT,
163+
syncStrategyFqdnName, finalResultArg);
164+
} else {
165+
pollingStrategy = String.format(PollingSettings.INSTANTIATE_POLLING_STRATEGY_FORMAT, strategyFqdnName);
166+
syncPollingStrategy
167+
= String.format(PollingSettings.INSTANTIATE_POLLING_STRATEGY_FORMAT, syncStrategyFqdnName);
168+
}
169+
} else {
170+
pollingStrategy = pollingSettings.getStrategy();
171+
syncPollingStrategy = pollingSettings.getSyncStrategy();
172+
}
173+
174+
return new PollingMetadata(pollingStrategy, syncPollingStrategy, pollResultType, finalResultType,
175+
pollingSettings.getPollIntervalInSeconds(), httpMethod);
176+
}
177+
178+
private static IType createTypeFromModelName(String modelName) {
179+
final String className;
180+
final String packageName;
181+
final int lastDotIndex = modelName.lastIndexOf('.');
182+
if (lastDotIndex >= 0) {
183+
// model-name is a fully qualified name, extract class and package name from it.
184+
className = modelName.substring(lastDotIndex + 1);
185+
packageName = modelName.substring(0, lastDotIndex);
186+
} else {
187+
// model-name is a simple name, use package name from JavaSettings.
188+
className = modelName;
189+
packageName = JavaSettings.getInstance().getPackage();
190+
}
191+
return new ClassType.Builder().packageName(packageName).name(className).build();
192+
}
193+
194+
private PollingMetadata(String pollingStrategy, String syncPollingStrategy, IType pollResultType,
195+
IType finalResultType, int pollIntervalInSeconds, HttpMethod httpMethod) {
196+
this.pollResultType = pollResultType;
197+
this.finalResultType = finalResultType;
198+
this.pollingStrategy = pollingStrategy;
199+
this.syncPollingStrategy = syncPollingStrategy;
200+
this.pollIntervalInSeconds = pollIntervalInSeconds;
201+
this.httpMethod = httpMethod;
202+
}
203+
}

0 commit comments

Comments
 (0)