From bcb0ac1eec59489b7022296f08e1af342223defa Mon Sep 17 00:00:00 2001 From: HenrikJannsen Date: Mon, 25 Mar 2024 15:05:29 +0700 Subject: [PATCH] Add fromProtoEnumStream method to ProtobufUtils. Skip not supported Feature proto enum values to support future updates fo the feature list. --- .../java/bisq/common/util/ProtobufUtils.java | 42 +++++++++++++++---- .../bisq/network/p2p/node/Capability.java | 5 +-- .../java/bisq/network/p2p/node/Feature.java | 2 + 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/bisq/common/util/ProtobufUtils.java b/common/src/main/java/bisq/common/util/ProtobufUtils.java index 9b61f22a0e..17c65de4dd 100644 --- a/common/src/main/java/bisq/common/util/ProtobufUtils.java +++ b/common/src/main/java/bisq/common/util/ProtobufUtils.java @@ -22,25 +22,31 @@ import com.google.protobuf.Any; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.Nullable; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkArgument; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; @Slf4j public class ProtobufUtils { @Nullable public static > E enumFromProto(Class enumType, String name) { String info = "Enum type= " + enumType.getSimpleName() + "; name=" + name; - checkNotNull(name, "Enum name must not be null. "+info); - checkArgument(!name.endsWith("_UNSPECIFIED"), "Unspecified enum. "+info); + checkNotNull(name, "Enum name must not be null. " + info); + checkArgument(!name.endsWith("_UNSPECIFIED"), "Unspecified enum. " + info); //Remove prefix from enum name. Since enum is based on the enum's class name, we use that to extract the prefix - String enumName = name.replace(ProtoEnum.getProtobufEnumPrefix(enumType),""); + String enumName = name.replace(ProtoEnum.getProtobufEnumPrefix(enumType), ""); E result = Enums.getIfPresent(enumType, enumName).orNull(); - checkNotNull(result, "Enum could not be resolved. "+info); + checkNotNull(result, "Enum could not be resolved. " + info); return result; } @@ -55,7 +61,7 @@ public static > E enumFromProto(Class enumType, String name return fallBack; } //Remove prefix from enum name. Since enum is based on the enum's class name, we use that to extract the prefix - String enumName = name.replace(ProtoEnum.getProtobufEnumPrefix(enumType),""); + String enumName = name.replace(ProtoEnum.getProtobufEnumPrefix(enumType), ""); E result = Enums.getIfPresent(enumType, enumName).orNull(); if (result == null) { log.error("Enum could not be resolved. We use the fallback value instead. {}", info); @@ -81,4 +87,26 @@ public static Any toAny(byte[] bytes) throws IOException { return Any.parseDelimitedFrom(inputStream); } } + + // Convert list of proto enums to a stream of Enums. If the enumFromProto fails we skip the enum. + public static , P> Stream fromProtoEnumStream(Class enumType, List

proto) { + return proto.stream() + .map(enumProto -> { + try { + return enumFromProto(enumType, ((Enum) enumProto).name()); + } catch (Exception e) { + log.warn("Could not resolve enum for proto {}.", enumProto, e); + return null; + } + }) + .filter(Objects::nonNull); + } + + public static , P> List fromProtoEnumList(Class enumType, List

proto) { + return fromProtoEnumStream(enumType, proto).collect(Collectors.toList()); + } + + public static , P> Set fromProtoEnumSet(Class enumType, List

proto) { + return fromProtoEnumStream(enumType, proto).collect(Collectors.toSet()); + } } diff --git a/network/network/src/main/java/bisq/network/p2p/node/Capability.java b/network/network/src/main/java/bisq/network/p2p/node/Capability.java index 898acd5177..57305d5128 100644 --- a/network/network/src/main/java/bisq/network/p2p/node/Capability.java +++ b/network/network/src/main/java/bisq/network/p2p/node/Capability.java @@ -74,11 +74,8 @@ public static Capability fromProto(bisq.network.protobuf.Capability proto) { List supportedTransportTypes = proto.getSupportedTransportTypesList().stream() .map(e -> ProtobufUtils.enumFromProto(TransportType.class, e)) .collect(Collectors.toList()); - List features = proto.getFeaturesList().stream() - .map(Feature::fromProto) - .collect(Collectors.toList()); return new Capability(Address.fromProto(proto.getAddress()), supportedTransportTypes, - features); + ProtobufUtils.fromProtoEnumList(Feature.class, proto.getFeaturesList())); } } diff --git a/network/network/src/main/java/bisq/network/p2p/node/Feature.java b/network/network/src/main/java/bisq/network/p2p/node/Feature.java index 99464b03b1..a5da600946 100644 --- a/network/network/src/main/java/bisq/network/p2p/node/Feature.java +++ b/network/network/src/main/java/bisq/network/p2p/node/Feature.java @@ -18,6 +18,8 @@ public bisq.network.protobuf.Feature toProto() { return bisq.network.protobuf.Feature.valueOf(getProtobufEnumPrefix() + name()); } + // Not used. Feature is used as list in Capability thus we use ProtobufUtils.fromProtoEnumList. + // Still keep fromProto for following convention and potential future usage. public static Feature fromProto(bisq.network.protobuf.Feature proto) { return ProtobufUtils.enumFromProto(Feature.class, proto.name()); }