]> nmode's Git Repositories - signal-cli/commitdiff
Use pattern matching switch cases
authorAsamK <asamk@gmx.de>
Tue, 17 Oct 2023 17:52:35 +0000 (19:52 +0200)
committerAsamK <asamk@gmx.de>
Tue, 24 Oct 2023 15:36:32 +0000 (17:36 +0200)
27 files changed:
lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java
src/main/java/org/asamk/signal/Main.java
src/main/java/org/asamk/signal/commands/Commands.java
src/main/java/org/asamk/signal/commands/DaemonCommand.java
src/main/java/org/asamk/signal/commands/GetAttachmentCommand.java
src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java
src/main/java/org/asamk/signal/commands/JoinGroupCommand.java
src/main/java/org/asamk/signal/commands/ListAccountsCommand.java
src/main/java/org/asamk/signal/commands/ListContactsCommand.java
src/main/java/org/asamk/signal/commands/ListDevicesCommand.java
src/main/java/org/asamk/signal/commands/ListGroupsCommand.java
src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java
src/main/java/org/asamk/signal/commands/ListStickerPacksCommand.java
src/main/java/org/asamk/signal/commands/ReceiveCommand.java
src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java
src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java
src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java
src/main/java/org/asamk/signal/commands/VersionCommand.java
src/main/java/org/asamk/signal/dbus/DbusProperties.java
src/main/java/org/asamk/signal/jsonrpc/JsonRpcReader.java
src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java
src/main/java/org/asamk/signal/output/JsonWriter.java
src/main/java/org/asamk/signal/output/OutputWriter.java
src/main/java/org/asamk/signal/output/PlainTextWriter.java
src/main/java/org/asamk/signal/util/SendMessageResultUtils.java

index 5991202e5e43fc081a42138b8a2ccd18c8909be5..532cd3e760086ea0db7631169fce054d44d1f966 100644 (file)
@@ -224,52 +224,55 @@ public class GroupHelper {
         var group = getGroupForUpdating(groupId);
         final var avatarBytes = readAvatarBytes(avatarFile);
 
-        if (group instanceof GroupInfoV2) {
-            try {
-                return updateGroupV2((GroupInfoV2) group,
-                        name,
-                        description,
-                        members,
-                        removeMembers,
-                        admins,
-                        removeAdmins,
-                        banMembers,
-                        unbanMembers,
-                        resetGroupLink,
-                        groupLinkState,
-                        addMemberPermission,
-                        editDetailsPermission,
-                        avatarBytes,
-                        expirationTimer,
-                        isAnnouncementGroup);
-            } catch (ConflictException e) {
-                // Detected conflicting update, refreshing group and trying again
-                group = getGroup(groupId, true);
-                return updateGroupV2((GroupInfoV2) group,
-                        name,
-                        description,
-                        members,
-                        removeMembers,
-                        admins,
-                        removeAdmins,
-                        banMembers,
-                        unbanMembers,
-                        resetGroupLink,
-                        groupLinkState,
-                        addMemberPermission,
-                        editDetailsPermission,
-                        avatarBytes,
-                        expirationTimer,
-                        isAnnouncementGroup);
+        switch (group) {
+            case GroupInfoV2 gv2 -> {
+                try {
+                    return updateGroupV2(gv2,
+                            name,
+                            description,
+                            members,
+                            removeMembers,
+                            admins,
+                            removeAdmins,
+                            banMembers,
+                            unbanMembers,
+                            resetGroupLink,
+                            groupLinkState,
+                            addMemberPermission,
+                            editDetailsPermission,
+                            avatarBytes,
+                            expirationTimer,
+                            isAnnouncementGroup);
+                } catch (ConflictException e) {
+                    // Detected conflicting update, refreshing group and trying again
+                    group = getGroup(groupId, true);
+                    return updateGroupV2((GroupInfoV2) group,
+                            name,
+                            description,
+                            members,
+                            removeMembers,
+                            admins,
+                            removeAdmins,
+                            banMembers,
+                            unbanMembers,
+                            resetGroupLink,
+                            groupLinkState,
+                            addMemberPermission,
+                            editDetailsPermission,
+                            avatarBytes,
+                            expirationTimer,
+                            isAnnouncementGroup);
+                }
             }
-        }
 
-        final var gv1 = (GroupInfoV1) group;
-        final var result = updateGroupV1(gv1, name, members, avatarBytes);
-        if (expirationTimer != null) {
-            setExpirationTimer(gv1, expirationTimer);
+            case GroupInfoV1 gv1 -> {
+                final var result = updateGroupV1(gv1, name, members, avatarBytes);
+                if (expirationTimer != null) {
+                    setExpirationTimer(gv1, expirationTimer);
+                }
+                return result;
+            }
         }
-        return result;
     }
 
     public void updateGroupProfileKey(GroupIdV2 groupId) throws GroupNotFoundException, NotAGroupMemberException, IOException {
index 3b3a5c6f9bcc359a40a99f6212e1364e378d1df7..de7e4dafcd3ebcdfafa0d7af3a33685707052335 100644 (file)
@@ -25,19 +25,19 @@ public class PinHelper {
             String pin, MasterKey masterKey
     ) throws IOException {
         final var backupResponse = secureValueRecoveryV2.setPin(pin, masterKey).execute();
-        if (backupResponse instanceof SecureValueRecovery.BackupResponse.Success) {
-        } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ServerRejected) {
-            logger.warn("Backup svr2 failed: ServerRejected");
-        } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.EnclaveNotFound) {
-            logger.warn("Backup svr2 failed: EnclaveNotFound");
-        } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ExposeFailure) {
-            logger.warn("Backup svr2 failed: ExposeFailure");
-        } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ApplicationError error) {
-            throw new IOException(error.getException());
-        } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.NetworkError error) {
-            throw error.getException();
-        } else {
-            throw new AssertionError("Unexpected response");
+        switch (backupResponse) {
+            case SecureValueRecovery.BackupResponse.Success success -> {
+            }
+            case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
+                    logger.warn("Backup svr2 failed: ServerRejected");
+            case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
+                    logger.warn("Backup svr2 failed: EnclaveNotFound");
+            case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
+                    logger.warn("Backup svr2 failed: ExposeFailure");
+            case SecureValueRecovery.BackupResponse.ApplicationError error ->
+                    throw new IOException(error.getException());
+            case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
+            case null, default -> throw new AssertionError("Unexpected response");
         }
     }
 
@@ -47,17 +47,17 @@ public class PinHelper {
 
     public void removeRegistrationLockPin() throws IOException {
         final var deleteResponse = secureValueRecoveryV2.deleteData();
-        if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.Success) {
-        } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.ServerRejected) {
-            logger.warn("Delete svr2 failed: ServerRejected");
-        } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.EnclaveNotFound) {
-            logger.warn("Delete svr2 failed: EnclaveNotFound");
-        } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.ApplicationError error) {
-            throw new IOException(error.getException());
-        } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.NetworkError error) {
-            throw error.getException();
-        } else {
-            throw new AssertionError("Unexpected response");
+        switch (deleteResponse) {
+            case SecureValueRecovery.DeleteResponse.Success success -> {
+            }
+            case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
+                    logger.warn("Delete svr2 failed: ServerRejected");
+            case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
+                    logger.warn("Delete svr2 failed: EnclaveNotFound");
+            case SecureValueRecovery.DeleteResponse.ApplicationError error ->
+                    throw new IOException(error.getException());
+            case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
+            case null, default -> throw new AssertionError("Unexpected response");
         }
     }
 
@@ -77,19 +77,21 @@ public class PinHelper {
     ) throws IOException, IncorrectPinException {
         final var restoreResponse = secureValueRecovery.restoreDataPreRegistration(authCredentials, pin);
 
-        if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.Success s) {
-            return s;
-        } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.PinMismatch pinMismatch) {
-            throw new IncorrectPinException(pinMismatch.getTriesRemaining());
-        } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.ApplicationError error) {
-            throw new IOException(error.getException());
-        } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.NetworkError error) {
-            throw error.getException();
-        } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.Missing) {
-            logger.debug("No SVR data stored for the given credentials.");
-            return null;
-        } else {
-            throw new AssertionError("Unexpected response: " + restoreResponse.getClass().getSimpleName());
+        switch (restoreResponse) {
+            case SecureValueRecovery.RestoreResponse.Success s -> {
+                return s;
+            }
+            case SecureValueRecovery.RestoreResponse.PinMismatch pinMismatch ->
+                    throw new IncorrectPinException(pinMismatch.getTriesRemaining());
+            case SecureValueRecovery.RestoreResponse.ApplicationError error ->
+                    throw new IOException(error.getException());
+            case SecureValueRecovery.RestoreResponse.NetworkError error -> throw error.getException();
+            case SecureValueRecovery.RestoreResponse.Missing missing -> {
+                logger.debug("No SVR data stored for the given credentials.");
+                return null;
+            }
+            case null, default ->
+                    throw new AssertionError("Unexpected response: " + restoreResponse.getClass().getSimpleName());
         }
     }
 }
index a2c90aa4d13d9d2f3ee9b563f446b42e1eb705ea..3feed994cb38fd934ea65549484fff7e4dec7a7e 100644 (file)
@@ -1252,18 +1252,15 @@ public class ManagerImpl implements Manager {
     public boolean trustIdentityVerified(
             RecipientIdentifier.Single recipient, IdentityVerificationCode verificationCode
     ) throws UnregisteredRecipientException {
-        if (verificationCode instanceof IdentityVerificationCode.Fingerprint fingerprint) {
-            return trustIdentity(recipient,
+        return switch (verificationCode) {
+            case IdentityVerificationCode.Fingerprint fingerprint -> trustIdentity(recipient,
                     r -> context.getIdentityHelper().trustIdentityVerified(r, fingerprint.fingerprint()));
-        } else if (verificationCode instanceof IdentityVerificationCode.SafetyNumber safetyNumber) {
-            return trustIdentity(recipient,
+            case IdentityVerificationCode.SafetyNumber safetyNumber -> trustIdentity(recipient,
                     r -> context.getIdentityHelper().trustIdentityVerifiedSafetyNumber(r, safetyNumber.safetyNumber()));
-        } else if (verificationCode instanceof IdentityVerificationCode.ScannableSafetyNumber safetyNumber) {
-            return trustIdentity(recipient,
+            case IdentityVerificationCode.ScannableSafetyNumber safetyNumber -> trustIdentity(recipient,
                     r -> context.getIdentityHelper().trustIdentityVerifiedSafetyNumber(r, safetyNumber.safetyNumber()));
-        } else {
-            throw new AssertionError("Invalid verification code type");
-        }
+            case null, default -> throw new AssertionError("Invalid verification code type");
+        };
     }
 
     @Override
index 0a30d20231d004a9fb836f5fe4f485fd00e60d6b..00d9d7a9fbe2944becb05037d7922b81d96a2494 100644 (file)
@@ -109,18 +109,13 @@ public class Main {
     }
 
     private static int getStatusForError(final CommandException e) {
-        if (e instanceof UserErrorException) {
-            return 1;
-        } else if (e instanceof UnexpectedErrorException) {
-            return 2;
-        } else if (e instanceof IOErrorException) {
-            return 3;
-        } else if (e instanceof UntrustedKeyErrorException) {
-            return 4;
-        } else if (e instanceof RateLimitErrorException) {
-            return 5;
-        } else {
-            return 2;
-        }
+        return switch (e) {
+            case UserErrorException userErrorException -> 1;
+            case UnexpectedErrorException unexpectedErrorException -> 2;
+            case IOErrorException ioErrorException -> 3;
+            case UntrustedKeyErrorException untrustedKeyErrorException -> 4;
+            case RateLimitErrorException rateLimitErrorException -> 5;
+            case null, default -> 2;
+        };
     }
 }
index 719ba132ac681f4857b6fb87c09e7bcf658fdcbd..0f26c9945828a586a69c10a270d51bac909a90dd 100644 (file)
@@ -72,8 +72,8 @@ public class Commands {
 
     private static void addCommand(Command command) {
         commands.put(command.getName(), command);
-        if (command instanceof CliCommand) {
-            commandSubparserAttacher.put(command.getName(), ((CliCommand) command)::attachToSubparser);
+        if (command instanceof CliCommand cliCommand) {
+            commandSubparserAttacher.put(command.getName(), cliCommand::attachToSubparser);
         }
     }
 }
index d32dc69ca809f6f6a7d44f902dde972b933dbaa4..5c1fac53499553cc0f76973ee88bfdc6704a71c6 100644 (file)
@@ -249,11 +249,11 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
     }
 
     private void addDefaultReceiveHandler(Manager m, OutputWriter outputWriter, final boolean isWeakListener) {
-        final var handler = outputWriter instanceof JsonWriter o
-                ? new JsonReceiveMessageHandler(m, o)
-                : outputWriter instanceof PlainTextWriter o
-                        ? new ReceiveMessageHandler(m, o)
-                        : Manager.ReceiveMessageHandler.EMPTY;
+        final var handler = switch (outputWriter) {
+            case PlainTextWriter writer -> new ReceiveMessageHandler(m, writer);
+            case JsonWriter writer -> new JsonReceiveMessageHandler(m, writer);
+            case null -> Manager.ReceiveMessageHandler.EMPTY;
+        };
         m.addReceiveHandler(handler, isWeakListener);
     }
 
index f2f0450ca7f5236537d49e9871db92523031ce71..160e53bcfd6423528dcc71d63c900fa2c5d79384 100644 (file)
@@ -42,10 +42,9 @@ public class GetAttachmentCommand implements JsonRpcLocalCommand {
         try (InputStream attachment = m.retrieveAttachment(id)) {
             final var bytes = attachment.readAllBytes();
             final var base64 = Base64.getEncoder().encodeToString(bytes);
-            if (outputWriter instanceof PlainTextWriter writer) {
-                writer.println(base64);
-            } else if (outputWriter instanceof JsonWriter writer) {
-                writer.write(new JsonAttachmentData(base64));
+            switch (outputWriter) {
+                case PlainTextWriter writer -> writer.println(base64);
+                case JsonWriter writer -> writer.write(new JsonAttachmentData(base64));
             }
         } catch (FileNotFoundException ex) {
             throw new UserErrorException("Could not find attachment with ID: " + id, ex);
index 30fe7bf2d64b9b7cc854549fccf5dbe13569e49f..70a55393d99d79990da3530cc072b44a7d566c4b 100644 (file)
@@ -55,24 +55,26 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
         }
 
         // Output
-        if (outputWriter instanceof JsonWriter jsonWriter) {
-
-            var jsonUserStatuses = registered.entrySet().stream().map(entry -> {
-                final var number = entry.getValue().number();
-                final var uuid = entry.getValue().uuid();
-                return new JsonUserStatus(entry.getKey(), number, uuid == null ? null : uuid.toString(), uuid != null);
-            }).toList();
-
-            jsonWriter.write(jsonUserStatuses);
-        } else {
-            final var writer = (PlainTextWriter) outputWriter;
-
-            for (var entry : registered.entrySet()) {
-                final var userStatus = entry.getValue();
-                writer.println("{}: {}{}",
-                        entry.getKey(),
-                        userStatus.uuid() != null,
-                        userStatus.unrestrictedUnidentifiedAccess() ? " (unrestricted sealed sender)" : "");
+        switch (outputWriter) {
+            case JsonWriter writer -> {
+                var jsonUserStatuses = registered.entrySet().stream().map(entry -> {
+                    final var number = entry.getValue().number();
+                    final var uuid = entry.getValue().uuid();
+                    return new JsonUserStatus(entry.getKey(),
+                            number,
+                            uuid == null ? null : uuid.toString(),
+                            uuid != null);
+                }).toList();
+                writer.write(jsonUserStatuses);
+            }
+            case PlainTextWriter writer -> {
+                for (var entry : registered.entrySet()) {
+                    final var userStatus = entry.getValue();
+                    writer.println("{}: {}{}",
+                            entry.getKey(),
+                            userStatus.uuid() != null,
+                            userStatus.unrestrictedUnidentifiedAccess() ? " (unrestricted sealed sender)" : "");
+                }
             }
         }
     }
index 3c3562ae4f97791927c84bdbf4954261d07f4935..7a5b2601f3057fb1884a3e4eee33ff9de7e5224d 100644 (file)
@@ -54,35 +54,38 @@ public class JoinGroupCommand implements JsonRpcLocalCommand {
         try {
             final var results = m.joinGroup(linkUrl);
             var newGroupId = results.first();
-            if (outputWriter instanceof JsonWriter writer) {
-                var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.second().results());
-                if (!m.getGroup(newGroupId).isMember()) {
-                    writer.write(Map.of("timestamp",
-                            results.second().timestamp(),
-                            "results",
-                            jsonResults,
-                            "groupId",
-                            newGroupId.toBase64(),
-                            "onlyRequested",
-                            true));
-                } else {
-                    writer.write(Map.of("timestamp",
-                            results.second().timestamp(),
-                            "results",
-                            jsonResults,
-                            "groupId",
-                            newGroupId.toBase64()));
+            switch (outputWriter) {
+                case JsonWriter writer -> {
+                    var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.second().results());
+                    if (!m.getGroup(newGroupId).isMember()) {
+                        writer.write(Map.of("timestamp",
+                                results.second().timestamp(),
+                                "results",
+                                jsonResults,
+                                "groupId",
+                                newGroupId.toBase64(),
+                                "onlyRequested",
+                                true));
+                    } else {
+                        writer.write(Map.of("timestamp",
+                                results.second().timestamp(),
+                                "results",
+                                jsonResults,
+                                "groupId",
+                                newGroupId.toBase64()));
+                    }
                 }
-            } else {
-                final var writer = (PlainTextWriter) outputWriter;
-                if (!m.getGroup(newGroupId).isMember()) {
-                    writer.println("Requested to join group \"{}\"", newGroupId.toBase64());
-                } else {
-                    writer.println("Joined group \"{}\"", newGroupId.toBase64());
+                case PlainTextWriter writer -> {
+                    if (!m.getGroup(newGroupId).isMember()) {
+                        writer.println("Requested to join group \"{}\"", newGroupId.toBase64());
+                    } else {
+                        writer.println("Joined group \"{}\"", newGroupId.toBase64());
+                    }
+                    var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.second()
+                            .results());
+                    SendMessageResultUtils.printSendMessageResultErrors(writer, errors);
+                    writer.println("{}", results.second().timestamp());
                 }
-                var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.second().results());
-                SendMessageResultUtils.printSendMessageResultErrors(writer, errors);
-                writer.println("{}", results.second().timestamp());
             }
         } catch (IOException e) {
             throw new IOErrorException("Failed to send message: "
index 68b56f290491e7dc00d36a7a2fbd792b50c0e3ce..b19a16864eab2181f445a4e3374609b0cfc8436f 100644 (file)
@@ -26,12 +26,15 @@ public class ListAccountsCommand implements JsonRpcMultiLocalCommand {
             final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter
     ) throws CommandException {
         final var accountNumbers = c.getAccountNumbers();
-        if (outputWriter instanceof JsonWriter jsonWriter) {
-            final var jsonAccounts = accountNumbers.stream().map(JsonAccount::new).toList();
-            jsonWriter.write(jsonAccounts);
-        } else if (outputWriter instanceof PlainTextWriter plainTextWriter) {
-            for (final var number : accountNumbers) {
-                plainTextWriter.println("Number: {}", number);
+        switch (outputWriter) {
+            case JsonWriter jsonWriter -> {
+                final var jsonAccounts = accountNumbers.stream().map(JsonAccount::new).toList();
+                jsonWriter.write(jsonAccounts);
+            }
+            case PlainTextWriter plainTextWriter -> {
+                for (final var number : accountNumbers) {
+                    plainTextWriter.println("Number: {}", number);
+                }
             }
         }
     }
index 997e31dd5b6af41c50f376a736e2e2c0b0ed2db6..42a33a14842b32c6fd54caf492b746c115a7b858 100644 (file)
@@ -51,48 +51,49 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
                 recipientIdentifiers,
                 Optional.ofNullable(name));
 
-        if (outputWriter instanceof PlainTextWriter writer) {
-            for (var r : recipients) {
-                final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
-                final var profile = r.getProfile() == null ? Profile.newBuilder().build() : r.getProfile();
-                writer.println(
-                        "Number: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
-                        r.getAddress().getLegacyIdentifier(),
-                        contact.getName(),
-                        profile.getDisplayName(),
-                        r.getAddress().username().orElse(""),
-                        contact.getColor(),
-                        contact.isBlocked(),
-                        contact.getMessageExpirationTime() == 0
-                                ? "disabled"
-                                : contact.getMessageExpirationTime() + "s");
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                for (var r : recipients) {
+                    final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
+                    final var profile = r.getProfile() == null ? Profile.newBuilder().build() : r.getProfile();
+                    writer.println(
+                            "Number: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
+                            r.getAddress().getLegacyIdentifier(),
+                            contact.getName(),
+                            profile.getDisplayName(),
+                            r.getAddress().username().orElse(""),
+                            contact.getColor(),
+                            contact.isBlocked(),
+                            contact.getMessageExpirationTime() == 0
+                                    ? "disabled"
+                                    : contact.getMessageExpirationTime() + "s");
+                }
+            }
+            case JsonWriter writer -> {
+                final var jsonContacts = recipients.stream().map(r -> {
+                    final var address = r.getAddress();
+                    final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
+                    return new JsonContact(address.number().orElse(null),
+                            address.uuid().map(UUID::toString).orElse(null),
+                            address.username().orElse(null),
+                            contact.getName(),
+                            contact.getColor(),
+                            contact.isBlocked(),
+                            contact.getMessageExpirationTime(),
+                            r.getProfile() == null
+                                    ? null
+                                    : new JsonContact.JsonProfile(r.getProfile().getLastUpdateTimestamp(),
+                                            r.getProfile().getGivenName(),
+                                            r.getProfile().getFamilyName(),
+                                            r.getProfile().getAbout(),
+                                            r.getProfile().getAboutEmoji(),
+                                            r.getProfile().getMobileCoinAddress() == null
+                                                    ? null
+                                                    : Base64.getEncoder()
+                                                            .encodeToString(r.getProfile().getMobileCoinAddress())));
+                }).toList();
+                writer.write(jsonContacts);
             }
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            final var jsonContacts = recipients.stream().map(r -> {
-                final var address = r.getAddress();
-                final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
-                return new JsonContact(address.number().orElse(null),
-                        address.uuid().map(UUID::toString).orElse(null),
-                        address.username().orElse(null),
-                        contact.getName(),
-                        contact.getColor(),
-                        contact.isBlocked(),
-                        contact.getMessageExpirationTime(),
-                        r.getProfile() == null
-                                ? null
-                                : new JsonContact.JsonProfile(r.getProfile().getLastUpdateTimestamp(),
-                                        r.getProfile().getGivenName(),
-                                        r.getProfile().getFamilyName(),
-                                        r.getProfile().getAbout(),
-                                        r.getProfile().getAboutEmoji(),
-                                        r.getProfile().getMobileCoinAddress() == null
-                                                ? null
-                                                : Base64.getEncoder()
-                                                        .encodeToString(r.getProfile().getMobileCoinAddress())));
-            }).toList();
-
-            writer.write(jsonContacts);
         }
     }
 
index 7920243e3c9113990b787c16188b79bce9f0a9e0..7adc8611cef3030a346d527072c02439af2fb021 100644 (file)
@@ -42,21 +42,23 @@ public class ListDevicesCommand implements JsonRpcLocalCommand {
             throw new IOErrorException("Failed to get linked devices: " + e.getMessage(), e);
         }
 
-        if (outputWriter instanceof PlainTextWriter writer) {
-            for (var d : devices) {
-                writer.println("- Device {}{}:", d.id(), (d.isThisDevice() ? " (this device)" : ""));
-                writer.indent(w -> {
-                    w.println("Name: {}", d.name());
-                    w.println("Created: {}", DateUtils.formatTimestamp(d.created()));
-                    w.println("Last seen: {}", DateUtils.formatTimestamp(d.lastSeen()));
-                });
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                for (var d : devices) {
+                    writer.println("- Device {}{}:", d.id(), (d.isThisDevice() ? " (this device)" : ""));
+                    writer.indent(w -> {
+                        w.println("Name: {}", d.name());
+                        w.println("Created: {}", DateUtils.formatTimestamp(d.created()));
+                        w.println("Last seen: {}", DateUtils.formatTimestamp(d.lastSeen()));
+                    });
+                }
+            }
+            case JsonWriter writer -> {
+                final var jsonDevices = devices.stream()
+                        .map(d -> new JsonDevice(d.id(), d.name(), d.created(), d.lastSeen()))
+                        .toList();
+                writer.write(jsonDevices);
             }
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            final var jsonDevices = devices.stream()
-                    .map(d -> new JsonDevice(d.id(), d.name(), d.created(), d.lastSeen()))
-                    .toList();
-            writer.write(jsonDevices);
         }
     }
 
index b22ace6cbc8f51438f1faf91aa9a36cc4fc759c3..eb53516f518375f365a034a6fd380d38239ee152 100644 (file)
@@ -89,34 +89,34 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
             groups = groups.stream().filter(g -> groupIds.contains(g.groupId())).toList();
         }
 
-        if (outputWriter instanceof JsonWriter jsonWriter) {
-
-            var jsonGroups = groups.stream().map(group -> {
-                final var groupInviteLink = group.groupInviteLinkUrl();
-
-                return new JsonGroup(group.groupId().toBase64(),
-                        group.title(),
-                        group.description(),
-                        group.isMember(),
-                        group.isBlocked(),
-                        group.messageExpirationTimer(),
-                        resolveJsonMembers(group.members()),
-                        resolveJsonMembers(group.pendingMembers()),
-                        resolveJsonMembers(group.requestingMembers()),
-                        resolveJsonMembers(group.adminMembers()),
-                        resolveJsonMembers(group.bannedMembers()),
-                        group.permissionAddMember().name(),
-                        group.permissionEditDetails().name(),
-                        group.permissionSendMessage().name(),
-                        groupInviteLink == null ? null : groupInviteLink.getUrl());
-            }).toList();
-
-            jsonWriter.write(jsonGroups);
-        } else {
-            final var writer = (PlainTextWriter) outputWriter;
-            boolean detailed = Boolean.TRUE.equals(ns.getBoolean("detailed"));
-            for (var group : groups) {
-                printGroupPlainText(writer, group, detailed);
+        switch (outputWriter) {
+            case JsonWriter jsonWriter -> {
+                var jsonGroups = groups.stream().map(group -> {
+                    final var groupInviteLink = group.groupInviteLinkUrl();
+
+                    return new JsonGroup(group.groupId().toBase64(),
+                            group.title(),
+                            group.description(),
+                            group.isMember(),
+                            group.isBlocked(),
+                            group.messageExpirationTimer(),
+                            resolveJsonMembers(group.members()),
+                            resolveJsonMembers(group.pendingMembers()),
+                            resolveJsonMembers(group.requestingMembers()),
+                            resolveJsonMembers(group.adminMembers()),
+                            resolveJsonMembers(group.bannedMembers()),
+                            group.permissionAddMember().name(),
+                            group.permissionEditDetails().name(),
+                            group.permissionSendMessage().name(),
+                            groupInviteLink == null ? null : groupInviteLink.getUrl());
+                }).toList();
+                jsonWriter.write(jsonGroups);
+            }
+            case PlainTextWriter writer -> {
+                boolean detailed = Boolean.TRUE.equals(ns.getBoolean("detailed"));
+                for (var group : groups) {
+                    printGroupPlainText(writer, group, detailed);
+                }
             }
         }
     }
index 45326fbc5de0b16a314433f2d169e413e1116b89..53d508d8272b6073b988659fcd7fe3166d6cf6a3 100644 (file)
@@ -57,28 +57,29 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
             identities = m.getIdentities(CommandUtil.getSingleRecipientIdentifier(number, m.getSelfNumber()));
         }
 
-        if (outputWriter instanceof PlainTextWriter writer) {
-            for (var id : identities) {
-                printIdentityFingerprint(writer, id);
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                for (var id : identities) {
+                    printIdentityFingerprint(writer, id);
+                }
+            }
+            case JsonWriter writer -> {
+                final var jsonIdentities = identities.stream().map(id -> {
+                    final var address = id.recipient();
+                    var safetyNumber = Util.formatSafetyNumber(id.safetyNumber());
+                    var scannableSafetyNumber = id.scannableSafetyNumber();
+                    return new JsonIdentity(address.number().orElse(null),
+                            address.uuid().map(UUID::toString).orElse(null),
+                            Hex.toString(id.getFingerprint()),
+                            safetyNumber,
+                            scannableSafetyNumber == null
+                                    ? null
+                                    : Base64.getEncoder().encodeToString(scannableSafetyNumber),
+                            id.trustLevel().name(),
+                            id.dateAddedTimestamp());
+                }).toList();
+                writer.write(jsonIdentities);
             }
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            final var jsonIdentities = identities.stream().map(id -> {
-                final var address = id.recipient();
-                var safetyNumber = Util.formatSafetyNumber(id.safetyNumber());
-                var scannableSafetyNumber = id.scannableSafetyNumber();
-                return new JsonIdentity(address.number().orElse(null),
-                        address.uuid().map(UUID::toString).orElse(null),
-                        Hex.toString(id.getFingerprint()),
-                        safetyNumber,
-                        scannableSafetyNumber == null
-                                ? null
-                                : Base64.getEncoder().encodeToString(scannableSafetyNumber),
-                        id.trustLevel().name(),
-                        id.dateAddedTimestamp());
-            }).toList();
-
-            writer.write(jsonIdentities);
         }
     }
 
index 53f3f3527c5afcfa56a87ab22775f45673ca59d4..233eb4b55ef78328ff0ea5cfeed80efda3c428c8 100644 (file)
@@ -30,17 +30,20 @@ public class ListStickerPacksCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager c, final OutputWriter outputWriter
     ) throws CommandException {
         final var stickerPacks = c.getStickerPacks();
-        if (outputWriter instanceof JsonWriter jsonWriter) {
-            final var jsonStickerPacks = stickerPacks.stream().map(JsonStickerPack::new).toList();
-            jsonWriter.write(jsonStickerPacks);
-        } else if (outputWriter instanceof PlainTextWriter plainTextWriter) {
-            for (final var sticker : stickerPacks) {
-                plainTextWriter.println("Pack {}: “{}” by “{}” has {} stickers. {}",
-                        Hex.toStringCondensed(sticker.packId().serialize()),
-                        sticker.title(),
-                        sticker.author(),
-                        sticker.stickers().size(),
-                        sticker.url().getUrl());
+        switch (outputWriter) {
+            case JsonWriter jsonWriter -> {
+                final var jsonStickerPacks = stickerPacks.stream().map(JsonStickerPack::new).toList();
+                jsonWriter.write(jsonStickerPacks);
+            }
+            case PlainTextWriter plainTextWriter -> {
+                for (final var sticker : stickerPacks) {
+                    plainTextWriter.println("Pack {}: “{}” by “{}” has {} stickers. {}",
+                            Hex.toStringCondensed(sticker.packId().serialize()),
+                            sticker.title(),
+                            sticker.author(),
+                            sticker.stickers().size(),
+                            sticker.url().getUrl());
+                }
             }
         }
     }
index 16421b62ca3139c48244149fc6082548d0cfe070..228a05619441ab15ff4e6cd0875c1571922258cb 100644 (file)
@@ -74,8 +74,10 @@ public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand<Receiv
         final var sendReadReceipts = Boolean.TRUE.equals(ns.getBoolean("send-read-receipts"));
         m.setReceiveConfig(new ReceiveConfig(ignoreAttachments, ignoreStories, sendReadReceipts));
         try {
-            final var handler = outputWriter instanceof JsonWriter ? new JsonReceiveMessageHandler(m,
-                    (JsonWriter) outputWriter) : new ReceiveMessageHandler(m, (PlainTextWriter) outputWriter);
+            final var handler = switch (outputWriter) {
+                case JsonWriter writer -> new JsonReceiveMessageHandler(m, writer);
+                case PlainTextWriter writer -> new ReceiveMessageHandler(m, writer);
+            };
             final var duration = timeout < 0 ? null : Duration.ofMillis((long) (timeout * 1000));
             final var maxMessages = maxMessagesRaw < 0 ? null : maxMessagesRaw;
             m.receiveMessages(Optional.ofNullable(duration), Optional.ofNullable(maxMessages), handler);
index 9a67d417c4ed58cd10fe6a7ef336faddd150efdc..d430f49fae581549ba5c1c14e872d3add96dd3fa 100644 (file)
@@ -50,10 +50,9 @@ public class UpdateAccountCommand implements JsonRpcLocalCommand {
         if (username != null) {
             try {
                 final var newUsername = m.setUsername(username);
-                if (outputWriter instanceof PlainTextWriter w) {
-                    w.println("Your new username: {}", newUsername);
-                } else if (outputWriter instanceof JsonWriter w) {
-                    w.write(new JsonAccountResponse(newUsername));
+                switch (outputWriter) {
+                    case PlainTextWriter w -> w.println("Your new username: {}", newUsername);
+                    case JsonWriter w -> w.write(new JsonAccountResponse(newUsername));
                 }
             } catch (IOException e) {
                 throw new IOErrorException("Failed to set username: " + e.getMessage(), e);
index 1f7825fb84a671fd8b7e4feacc65e7885174ffd7..5fe47417dda3462dea24c87519dba03ecab1fdd5 100644 (file)
@@ -182,27 +182,29 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand {
     private void outputResult(
             final OutputWriter outputWriter, final SendGroupMessageResults results, final GroupId groupId
     ) {
-        if (outputWriter instanceof PlainTextWriter writer) {
-            if (groupId != null) {
-                writer.println("Created new group: \"{}\"", groupId.toBase64());
-            }
-            if (results != null) {
-                var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.results());
-                SendMessageResultUtils.printSendMessageResultErrors(writer, errors);
-                writer.println("{}", results.timestamp());
-            }
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            final var response = new HashMap<>();
-            if (results != null) {
-                response.put("timestamp", results.timestamp());
-                var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.results());
-                response.put("results", jsonResults);
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                if (groupId != null) {
+                    writer.println("Created new group: \"{}\"", groupId.toBase64());
+                }
+                if (results != null) {
+                    var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.results());
+                    SendMessageResultUtils.printSendMessageResultErrors(writer, errors);
+                    writer.println("{}", results.timestamp());
+                }
             }
-            if (groupId != null) {
-                response.put("groupId", groupId.toBase64());
+            case JsonWriter writer -> {
+                final var response = new HashMap<>();
+                if (results != null) {
+                    response.put("timestamp", results.timestamp());
+                    var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.results());
+                    response.put("results", jsonResults);
+                }
+                if (groupId != null) {
+                    response.put("groupId", groupId.toBase64());
+                }
+                writer.write(response);
             }
-            writer.write(response);
         }
     }
 }
index aad9a1e5131d54dd31035f9ada291f9a623db706..89f741290c8081ad7ad1c351a151084c762824ea 100644 (file)
@@ -42,11 +42,11 @@ public class UploadStickerPackCommand implements JsonRpcLocalCommand {
 
         try {
             var url = m.uploadStickerPack(path);
-            if (outputWriter instanceof PlainTextWriter writer) {
-                writer.println("{}", url.getUrl());
-            } else {
-                final var writer = (JsonWriter) outputWriter;
-                writer.write(Map.of("url", url.getUrl()));
+            switch (outputWriter) {
+                case PlainTextWriter writer -> writer.println("{}", url.getUrl());
+                case JsonWriter writer -> {
+                    writer.write(Map.of("url", url.getUrl()));
+                }
             }
         } catch (IOException e) {
             throw new IOErrorException("Upload error (maybe image size too large):" + e.getMessage(), e);
index 52099ff3d8f4f7b515892eef014d239ac6ef83a6..01f1a2d7ecbc836a3a02c6bb455713b537bbfa91 100644 (file)
@@ -56,10 +56,9 @@ public class VersionCommand implements JsonRpcLocalCommand, JsonRpcMultiLocalCom
         final var projectName = BaseConfig.PROJECT_NAME == null ? "signal-cli" : BaseConfig.PROJECT_NAME;
         final var version = BaseConfig.PROJECT_VERSION == null ? "unknown" : BaseConfig.PROJECT_VERSION;
 
-        if (outputWriter instanceof JsonWriter jsonWriter) {
-            jsonWriter.write(Map.of("version", version));
-        } else if (outputWriter instanceof PlainTextWriter plainTextWriter) {
-            plainTextWriter.println("{} {}", projectName, version);
+        switch (outputWriter) {
+            case JsonWriter jsonWriter -> jsonWriter.write(Map.of("version", version));
+            case PlainTextWriter plainTextWriter -> plainTextWriter.println("{} {}", projectName, version);
         }
     }
 }
index 256b858d080b4f5679dadb525e7b666ed8b8e0ac..a77ed1648d21243e0ec1fb25d1a6596e857ad2e2 100644 (file)
@@ -65,7 +65,7 @@ public abstract class DbusProperties implements Properties {
                 .filter(p -> p.getGetter() != null)
                 .collect(Collectors.toMap(DbusProperty::getName, p -> {
                     final Object o = p.getGetter().get();
-                    return o instanceof Variant ? (Variant<Object>) o : new Variant<>(o);
+                    return o instanceof Variant<?> variant ? variant : new Variant<>(o);
                 }));
     }
 }
index 25e5c66c5f03d5fb5f6dfbdb1619e97b1587c003..f9ef71a1f05cbc8ca72cba4ee90ab88786d5eeba 100644 (file)
@@ -82,53 +82,55 @@ public class JsonRpcReader {
             final RequestHandler requestHandler,
             final Consumer<JsonRpcResponse> responseHandler
     ) {
-        if (message instanceof final JsonRpcRequest jsonRpcRequest) {
-            logger.debug("Received json rpc request, method: " + jsonRpcRequest.getMethod());
-            final var response = handleRequest(requestHandler, jsonRpcRequest);
-            if (response != null) {
-                jsonRpcSender.sendResponse(response);
+        switch (message) {
+            case JsonRpcRequest jsonRpcRequest -> {
+                logger.debug("Received json rpc request, method: " + jsonRpcRequest.getMethod());
+                final var response = handleRequest(requestHandler, jsonRpcRequest);
+                if (response != null) {
+                    jsonRpcSender.sendResponse(response);
+                }
             }
-        } else if (message instanceof JsonRpcResponse jsonRpcResponse) {
-            responseHandler.accept(jsonRpcResponse);
-        } else {
-            final var messages = ((JsonRpcBatchMessage) message).getMessages();
-            final var responseList = new ArrayList<JsonRpcResponse>(messages.size());
-            final var executor = Executors.newFixedThreadPool(10);
-            try {
-                final var lock = new ReentrantLock();
-                messages.forEach(jsonNode -> {
-                    final JsonRpcRequest request;
-                    try {
-                        request = parseJsonRpcRequest(jsonNode);
-                    } catch (JsonRpcException e) {
-                        final var response = JsonRpcResponse.forError(e.getError(), getId(jsonNode));
-                        lock.lock();
+            case JsonRpcResponse jsonRpcResponse -> responseHandler.accept(jsonRpcResponse);
+            case JsonRpcBatchMessage jsonRpcBatchMessage -> {
+                final var messages = jsonRpcBatchMessage.getMessages();
+                final var responseList = new ArrayList<JsonRpcResponse>(messages.size());
+                final var executor = Executors.newFixedThreadPool(10);
+                try {
+                    final var lock = new ReentrantLock();
+                    messages.forEach(jsonNode -> {
+                        final JsonRpcRequest request;
                         try {
-                            responseList.add(response);
-                        } finally {
-                            lock.unlock();
-                        }
-                        return;
-                    }
-
-                    executor.submit(() -> {
-                        final var response = handleRequest(requestHandler, request);
-                        if (response != null) {
+                            request = parseJsonRpcRequest(jsonNode);
+                        } catch (JsonRpcException e) {
+                            final var response = JsonRpcResponse.forError(e.getError(), getId(jsonNode));
                             lock.lock();
                             try {
                                 responseList.add(response);
                             } finally {
                                 lock.unlock();
                             }
+                            return;
                         }
+
+                        executor.submit(() -> {
+                            final var response = handleRequest(requestHandler, request);
+                            if (response != null) {
+                                lock.lock();
+                                try {
+                                    responseList.add(response);
+                                } finally {
+                                    lock.unlock();
+                                }
+                            }
+                        });
                     });
-                });
-            } finally {
-                Util.closeExecutorService(executor);
-            }
+                } finally {
+                    Util.closeExecutorService(executor);
+                }
 
-            if (!responseList.isEmpty()) {
-                jsonRpcSender.sendBatchResponses(responseList);
+                if (!responseList.isEmpty()) {
+                    jsonRpcSender.sendBatchResponses(responseList);
+                }
             }
         }
     }
@@ -221,7 +223,7 @@ public class JsonRpcReader {
 
     private ValueNode getId(JsonNode jsonNode) {
         final var id = jsonNode.get("id");
-        return id instanceof ValueNode ? (ValueNode) id : null;
+        return id instanceof ValueNode value ? value : null;
     }
 
     private JsonRpcRequest parseJsonRpcRequest(final JsonNode input) throws JsonRpcException {
index 53b876b866a5f6b8fe815f5dbe72632bce57c845..85ed76e68339300200b03720e2d7f3ab43139e39 100644 (file)
@@ -223,13 +223,11 @@ public class SignalJsonRpcDispatcherHandler {
         }
 
         private Integer getSubscriptionId(final JsonNode request) {
-            if (request instanceof ArrayNode req) {
-                return req.get(0).asInt();
-            } else if (request instanceof ObjectNode req) {
-                return req.get("subscription").asInt();
-            } else {
-                return null;
-            }
+            return switch (request) {
+                case ArrayNode req -> req.get(0).asInt();
+                case ObjectNode req -> req.get("subscription").asInt();
+                case null, default -> null;
+            };
         }
     }
 }
index 034d2f9fbe2b1b971ab328857b6efb1e4bad84e6..22c323a85fd68002de66a5bdda320c3e3948ff10 100644 (file)
@@ -1,6 +1,6 @@
 package org.asamk.signal.output;
 
-public interface JsonWriter extends OutputWriter {
+public non-sealed interface JsonWriter extends OutputWriter {
 
     void write(final Object object);
 }
index a32e773dd29423bbf80ee5cd1179d36783195ddf..0d84848e069e0221b68d1925ee1011d28a964633 100644 (file)
@@ -1,5 +1,3 @@
 package org.asamk.signal.output;
 
-public interface OutputWriter {
-
-}
+public sealed interface OutputWriter permits JsonWriter, PlainTextWriter {}
index 29ac87af2087ba50ac168d28b1caab82648be41f..eb42bed11bce85c2a86d0a27fddd26264bc5b093 100644 (file)
@@ -2,7 +2,7 @@ package org.asamk.signal.output;
 
 import java.util.function.Consumer;
 
-public interface PlainTextWriter extends OutputWriter {
+public non-sealed interface PlainTextWriter extends OutputWriter {
 
     void println(String format, Object... args);
 
index e4386b0ecb2df9ab40fbd9eff6ef9c26e90fbb59..108142e32b9990c6978b2fa97cab36ffca9ac7b2 100644 (file)
@@ -27,28 +27,32 @@ public class SendMessageResultUtils {
     }
 
     public static void outputResult(final OutputWriter outputWriter, final SendGroupMessageResults sendMessageResults) {
-        if (outputWriter instanceof PlainTextWriter writer) {
-            var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
-            printSendMessageResultErrors(writer, errors);
-            writer.println("{}", sendMessageResults.timestamp());
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            var results = getJsonSendMessageResults(sendMessageResults.results());
-            writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
+                printSendMessageResultErrors(writer, errors);
+                writer.println("{}", sendMessageResults.timestamp());
+            }
+            case JsonWriter writer -> {
+                var results = getJsonSendMessageResults(sendMessageResults.results());
+                writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
+            }
         }
     }
 
     public static void outputResult(
             final OutputWriter outputWriter, final SendMessageResults sendMessageResults
     ) throws CommandException {
-        if (outputWriter instanceof PlainTextWriter writer) {
-            var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
-            printSendMessageResultErrors(writer, errors);
-            writer.println("{}", sendMessageResults.timestamp());
-        } else {
-            final var writer = (JsonWriter) outputWriter;
-            var results = getJsonSendMessageResults(sendMessageResults.results());
-            writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
+        switch (outputWriter) {
+            case PlainTextWriter writer -> {
+                var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
+                printSendMessageResultErrors(writer, errors);
+                writer.println("{}", sendMessageResults.timestamp());
+            }
+            case JsonWriter writer -> {
+                var results = getJsonSendMessageResults(sendMessageResults.results());
+                writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
+            }
         }
         if (!sendMessageResults.hasSuccess()) {
             if (sendMessageResults.hasOnlyUntrustedIdentity()) {