Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -286,7 +286,7 @@ public static String getFieldsHashCode(final List<Field> fields, String generate
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Integer.hashCode($fieldName.protoOrdinal());
result = 31 * result + Integer.hashCode(EnumWithProtoMetadata.protoOrdinal($fieldName));
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
Expand Down Expand Up @@ -320,55 +320,62 @@ public static String getFieldsHashCode(final List<Field> fields, String generate
@NonNull
private static String getPrimitiveWrapperHashCodeGeneration(String generatedCodeSoFar, Field f) {
switch (f.messageType()) {
case "StringValue" -> generatedCodeSoFar +=
("""
case "StringValue" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + $fieldName.hashCode();
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "BoolValue" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "BoolValue" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Boolean.hashCode($fieldName);
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "Int32Value", "UInt32Value" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "Int32Value", "UInt32Value" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Integer.hashCode($fieldName);
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "Int64Value", "UInt64Value" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "Int64Value", "UInt64Value" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Long.hashCode($fieldName);
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "FloatValue" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "FloatValue" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Float.hashCode($fieldName);
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "DoubleValue" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "DoubleValue" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + Double.hashCode($fieldName);
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
case "BytesValue" -> generatedCodeSoFar +=
("""
.replace("$fieldName", f.nameCamelFirstLower());
case "BytesValue" ->
generatedCodeSoFar +=
("""
if ($fieldName != null && !$fieldName.equals(DEFAULT.$fieldName)) {
result = 31 * result + ($fieldName == null ? 0 : $fieldName.hashCode());
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
.replace("$fieldName", f.nameCamelFirstLower());
default -> throw new UnsupportedOperationException("Unhandled optional message type:" + f.messageType());
}
return generatedCodeSoFar;
Expand Down Expand Up @@ -543,16 +550,17 @@ private static String getPrimitiveWrapperEqualsGeneration(String generatedCodeSo
"UInt64Value",
"FloatValue",
"DoubleValue",
"BytesValue" -> generatedCodeSoFar +=
("""
"BytesValue" ->
generatedCodeSoFar +=
("""
if (this.$fieldName == null && thatObj.$fieldName != null) {
return false;
}
if (this.$fieldName != null && !$fieldName.equals(thatObj.$fieldName)) {
return false;
}
""")
.replace("$fieldName", f.nameCamelFirstLower());
.replace("$fieldName", f.nameCamelFirstLower());
default -> throw new UnsupportedOperationException("Unhandled optional message type:" + f.messageType());
}
return generatedCodeSoFar;
Expand Down Expand Up @@ -693,12 +701,17 @@ private static String generateCompareToForObject(Field f) {
return 1;
}
if ($fieldName != null) {
result = $fieldName.compareTo(thatObj.$fieldName);
result = $doCompare;
}
if (result != 0) {
return result;
}
"""
.replace(
"$doCompare",
f.type() == Field.FieldType.ENUM
? f.javaFieldType() + ".compare($fieldName, thatObj.$fieldName)"
: "$fieldName.compareTo(thatObj.$fieldName)")
.replace("$fieldName", f.nameCamelFirstLower());
}

Expand Down Expand Up @@ -760,8 +773,8 @@ private static String getPrimitiveWrapperCompareToGeneration(Field f) {
case "UInt64Value" -> "java.lang.Long.compareUnsigned($fieldName, thatObj.$fieldName)";
case "FloatValue" -> "java.lang.Float.compare($fieldName, thatObj.$fieldName)";
case "DoubleValue" -> "java.lang.Double.compare($fieldName, thatObj.$fieldName)";
default -> throw new UnsupportedOperationException(
"Unhandled optional message type:" + f.messageType());
default ->
throw new UnsupportedOperationException("Unhandled optional message type:" + f.messageType());
};

return template.replace("$compareStatement", compareStatement).replace("$fieldName", f.nameCamelFirstLower());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public static void generateEnum(
}
}

writer.addImport("java.util.List");
writer.append(createEnum(javaDocComment, deprecated, enumName, enumValues, false));
}

Expand Down Expand Up @@ -146,18 +147,30 @@ static String createEnum(
// spotless:on
});
// spotless:off

if (!addUnknown) { // !addUnknown to avoid a clash with OneOf UNSET above.
// spotless:off
enumValuesCode.add(
"""
/**
* Enum value for unrecognized protoOrdinal values.
*/
UNRECOGNIZED(-1, "UNRECOGNIZED")""");
// spotless:on
}

return """
$javaDocComment
$deprecated$public enum $enumName
implements com.hedera.pbj.runtime.EnumWithProtoMetadata {
$enumValues;

/** The field ordinal in protobuf for this type */
private final int protoOrdinal;

/** The original field name in protobuf for this type */
private final String protoName;

/**
* OneOf Type Enum Constructor
*
Expand All @@ -168,7 +181,7 @@ static String createEnum(
this.protoOrdinal = protoOrdinal;
this.protoName = protoName;
}

/**
* Get the oneof field ordinal in protobuf for this type
*
Expand All @@ -177,7 +190,7 @@ static String createEnum(
public int protoOrdinal() {
return protoOrdinal;
}

/**
* Get the original field name in protobuf for this type
*
Expand All @@ -186,7 +199,7 @@ public int protoOrdinal() {
public String protoName() {
return protoName;
}

/**
* Get enum from protobuf ordinal
*
Expand All @@ -197,10 +210,10 @@ public String protoName() {
public static $enumName fromProtobufOrdinal(int ordinal) {
return switch(ordinal) {
$caseStatements
default -> throw new IllegalArgumentException("Unknown protobuf ordinal "+ordinal);
default -> $unknownValue;
};
}

/**
* Get enum from string name, supports the enum or protobuf format name
*
Expand All @@ -213,29 +226,122 @@ public String protoName() {
default -> throw new IllegalArgumentException("Unknown token kyc status "+name);
};
}

/**
* Get enum from an $enumName or an unrecognized object (likely an Integer, but we don't check here.)
*
* @param obj an object
* @return enum for matching ordinal, or UNRECOGNIZED/UNSET value
*/
public static $enumName fromObject(Object obj) {
if (obj instanceof $enumName pbjEnum) {
return pbjEnum;
} else {
return $enumName.$unknownValue;
}
}

/**
* Get a list of enums from a list of $enumName or unrecognized objects (likely Integers, but we don't check here.)
* Note that this method creates a new list, so it's best to cache the result.
*
* @param list a list of objects
* @return a list of enum or UNRECOGNIZED/UNSET values
*/
public static List<$enumName> fromObjects(List<?> list) {
return list.stream().map($enumName::fromObject).toList();
}

/**
* Get protoOrdinal for an enum or Integer object, or throw IllegalArgumentException.
*
* @param obj an object
* @return protoOrdinal of the object
*/
public static int toProtoOrdinal(Object obj) {
if (obj instanceof $enumName pbjEnum) {
return pbjEnum.protoOrdinal();
} else if (obj instanceof Integer i) {
return i;
} else {
throw new IllegalArgumentException("Neither $enumName, nor Integer, but: " + obj.getClass().getName());
}
}

/**
* Get protoOrdinals for enums or Integers objects, or throw IllegalArgumentException.
* Note that this method creates a new list, so it's best to cache the result.
*
* @param list a list of enum or Integer objects
* @return a list of their protoOrdinals
*/
public static List<Integer> toProtoOrdinals(List<?> list) {
return list.stream().map($enumName::toProtoOrdinal).toList();
}

/**
* Compare two objects, each of them could be an enum or an Integer representing a protoOrdinal value.
*/
public static int compare(final Object o1, final Object o2) {
if (o1 instanceof $enumName e1 && o2 instanceof $enumName e2) {
return e1.compareTo(e2);
}
if (o1 == null && o2 != null) {
return -1;
}
if (o1 != null && o2 == null) {
return 1;
}
// Both non-null here
final int i1, i2;
if (o1 instanceof $enumName e1) {
i1 = e1.protoOrdinal();
} else if (o1 instanceof Integer ii1) {
i1 = ii1.intValue();
} else {
throw new IllegalArgumentException("o1 is neither $enumName, nor Integer. It's: " + o1.getClass().getName());
}
if (o2 instanceof $enumName e2) {
i2 = e2.protoOrdinal();
} else if (o2 instanceof Integer ii2) {
i2 = ii2.intValue();
} else {
throw new IllegalArgumentException("o2 is neither $enumName, nor Integer. It's: " + o2.getClass().getName());
}
return Integer.compare(i1, i2);
}
}
"""
.replace("$javaDocComment", javaDocComment)
.replace("$deprecated$", deprecated)
.replace("$enumName", enumName)
.replace("$enumValues", String.join(",\n\n", enumValuesCode).indent(DEFAULT_INDENT))
.replace("$caseStatements", enumValues.entrySet()
.stream()
.map((entry) -> "case %s -> %s;"
.formatted(entry.getKey(), camelToUpperSnake(entry.getValue().name))
.indent(DEFAULT_INDENT * 3))
.collect(Collectors.joining("\n")))
.replace("$fromStringCaseStatements", enumValues.values().stream().map(enumValue -> {
if (camelToUpperSnake(enumValue.name).equals(enumValue.name)) {
return "case \"%s\" -> %s;"
.formatted(enumValue.name, camelToUpperSnake(enumValue.name))
.indent(DEFAULT_INDENT * 3);
} else {
return "case \"%s\", \"%s\" -> %s;"
.formatted(enumValue.name, camelToUpperSnake(enumValue.name),
camelToUpperSnake(enumValue.name)).indent(DEFAULT_INDENT * 3);
}
}).collect(Collectors.joining("\n")));
.replace(
"$caseStatements",
enumValues.entrySet().stream()
.map((entry) -> "case %s -> %s;"
.formatted(entry.getKey(), camelToUpperSnake(entry.getValue().name))
.indent(DEFAULT_INDENT * 3))
.collect(Collectors.joining("\n")))
.replace(
"$fromStringCaseStatements",
enumValues.values().stream()
.map(enumValue -> {
if (camelToUpperSnake(enumValue.name).equals(enumValue.name)) {
return "case \"%s\" -> %s;"
.formatted(enumValue.name, camelToUpperSnake(enumValue.name))
.indent(DEFAULT_INDENT * 3);
} else {
return "case \"%s\", \"%s\" -> %s;"
.formatted(
enumValue.name,
camelToUpperSnake(enumValue.name),
camelToUpperSnake(enumValue.name))
.indent(DEFAULT_INDENT * 3);
}
})
.collect(Collectors.joining("\n")))
.replace("$unknownValue", addUnknown ? "UNSET" : "UNRECOGNIZED");
// spotless:on
}
}
Loading
Loading