Skip to content

Commit 257ff42

Browse files
[ggj][codegen](2/2)feat: Add HashCode in resource name (#368)
1 parent f228417 commit 257ff42

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

src/main/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposer.java

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.google.api.core.BetaApi;
1818
import com.google.api.generator.engine.ast.AnnotationNode;
1919
import com.google.api.generator.engine.ast.AssignmentExpr;
20+
import com.google.api.generator.engine.ast.AssignmentOperationExpr;
2021
import com.google.api.generator.engine.ast.CastExpr;
2122
import com.google.api.generator.engine.ast.ClassDefinition;
2223
import com.google.api.generator.engine.ast.CommentStatement;
@@ -274,6 +275,7 @@ private static List<MethodDefinition> createClassMethods(
274275
javaMethods.add(
275276
createToStringMethod(templateFinalVarExprs, patternTokenVarExprs, tokenHierarchies));
276277
javaMethods.add(createEqualsMethod(resourceName, tokenHierarchies, types));
278+
javaMethods.add(createHashCodeMethod(tokenHierarchies));
277279
return javaMethods;
278280
}
279281

@@ -1257,6 +1259,74 @@ private static MethodInvocationExpr createObjectsEqualsForTokenMethodEpxr(
12571259
.build();
12581260
}
12591261

1262+
private static MethodDefinition createHashCodeMethod(List<List<String>> tokenHierarchies) {
1263+
List<Statement> asgmtBody = new ArrayList<>();
1264+
// code: int h = 1;
1265+
Variable hVar = Variable.builder().setType(TypeNode.INT).setName("h").build();
1266+
VariableExpr hVarExpr = VariableExpr.builder().setVariable(hVar).build();
1267+
ValueExpr hValueExpr =
1268+
ValueExpr.withValue(PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build());
1269+
AssignmentExpr hAssignmentExpr =
1270+
AssignmentExpr.builder()
1271+
.setVariableExpr(hVarExpr.toBuilder().setIsDecl(true).build())
1272+
.setValueExpr(hValueExpr)
1273+
.build();
1274+
asgmtBody.add(ExprStatement.withExpr(hAssignmentExpr));
1275+
// code: h *= 1000003;
1276+
// code: h ^= Objects.hashCode(...);
1277+
ValueExpr numValueExpr =
1278+
ValueExpr.withValue(
1279+
PrimitiveValue.builder().setType(TypeNode.INT).setValue("1000003").build());
1280+
AssignmentOperationExpr multiplyAsgmtOpExpr =
1281+
AssignmentOperationExpr.multiplyAssignmentWithExprs(hVarExpr, numValueExpr);
1282+
// If it has variants, add the multiply and xor assignment operation exprs for fixedValue.
1283+
boolean hasVariants = tokenHierarchies.size() > 1;
1284+
if (hasVariants) {
1285+
VariableExpr fixedValueVarExpr = FIXED_CLASS_VARS.get("fixedValue");
1286+
asgmtBody.add(ExprStatement.withExpr(multiplyAsgmtOpExpr));
1287+
asgmtBody.add(
1288+
ExprStatement.withExpr(
1289+
AssignmentOperationExpr.xorAssignmentWithExprs(
1290+
hVarExpr, createObjectsHashCodeForVarMethod(fixedValueVarExpr))));
1291+
}
1292+
// Add the multiply and xor assignment operation exprs for tokens.
1293+
Set<String> tokenSet = getTokenSet(tokenHierarchies);
1294+
tokenSet.stream()
1295+
.forEach(
1296+
token -> {
1297+
VariableExpr tokenVarExpr =
1298+
VariableExpr.withVariable(
1299+
Variable.builder()
1300+
.setName(JavaStyle.toLowerCamelCase(token))
1301+
.setType(TypeNode.STRING)
1302+
.build());
1303+
asgmtBody.add(ExprStatement.withExpr(multiplyAsgmtOpExpr));
1304+
asgmtBody.add(
1305+
ExprStatement.withExpr(
1306+
AssignmentOperationExpr.xorAssignmentWithExprs(
1307+
hVarExpr, createObjectsHashCodeForVarMethod(tokenVarExpr))));
1308+
});
1309+
1310+
return MethodDefinition.builder()
1311+
.setIsOverride(true)
1312+
.setScope(ScopeNode.PUBLIC)
1313+
.setReturnType(TypeNode.INT)
1314+
.setName("hashCode")
1315+
.setBody(asgmtBody)
1316+
.setReturnExpr(hVarExpr)
1317+
.build();
1318+
}
1319+
1320+
private static MethodInvocationExpr createObjectsHashCodeForVarMethod(VariableExpr varExpr) {
1321+
// code: Objects.hashCode(varExpr)
1322+
return MethodInvocationExpr.builder()
1323+
.setMethodName("hashCode")
1324+
.setStaticReferenceType(STATIC_TYPES.get("Objects"))
1325+
.setArguments(varExpr)
1326+
.setReturnType(TypeNode.INT)
1327+
.build();
1328+
}
1329+
12601330
private static List<ClassDefinition> createNestedBuilderClasses(
12611331
ResourceName resourceName,
12621332
List<List<String>> tokenHierarchies,

src/test/java/com/google/api/generator/gapic/composer/goldens/FoobarName.golden

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,22 @@ public class FoobarName implements ResourceName {
264264
return false;
265265
}
266266

267+
@Override
268+
public int hashCode() {
269+
int h = 1;
270+
h *= 1000003;
271+
h ^= Objects.hashCode(fixedValue);
272+
h *= 1000003;
273+
h ^= Objects.hashCode(project);
274+
h *= 1000003;
275+
h ^= Objects.hashCode(foobar);
276+
h *= 1000003;
277+
h ^= Objects.hashCode(variant);
278+
h *= 1000003;
279+
h ^= Objects.hashCode(barFoo);
280+
return h;
281+
}
282+
267283
/** Builder for projects/{project}/foobars/{foobar}. */
268284
public static class Builder {
269285
private String project;

src/test/java/com/google/api/generator/gapic/composer/goldens/SessionName.golden

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ public class SessionName implements ResourceName {
113113
return false;
114114
}
115115

116+
@Override
117+
public int hashCode() {
118+
int h = 1;
119+
h *= 1000003;
120+
h ^= Objects.hashCode(session);
121+
return h;
122+
}
123+
116124
/** Builder for sessions/{session}. */
117125
public static class Builder {
118126
private String session;

0 commit comments

Comments
 (0)