public static String getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
        FileChecksums fileChecksums = CHECKSUM_CACHE.get(file);
        if (fileChecksums == null) {
            try (InputStream stream = Files.newInputStream(file.toPath())) {
                final MessageDigest md5Digest = getMessageDigest(MD5);
                final MessageDigest sha1Digest = getMessageDigest(SHA1);
                final MessageDigest sha256Digest = getMessageDigest(SHA256);
                final byte[] buffer = new byte[BUFFER_SIZE];
                int read = stream.read(buffer, 0, BUFFER_SIZE);
                while (read > -1) {
                    // update all checksums together instead of reading the file multiple times
                    md5Digest.update(buffer, 0, read);
                    sha1Digest.update(buffer, 0, read);
                    sha256Digest.update(buffer, 0, read);
                    read = stream.read(buffer, 0, BUFFER_SIZE);
                }
                fileChecksums = new FileChecksums(
                        getHex(md5Digest.digest()),
                        getHex(sha1Digest.digest()),
                        getHex(sha256Digest.digest())
                );
                CHECKSUM_CACHE.put(file, fileChecksums);
            }
        }
        switch (algorithm.toUpperCase()) {
            case MD5:
                return fileChecksums.md5;
            case SHA1:
                return fileChecksums.sha1;
            case SHA256:
                return fileChecksums.sha256;
            default:
                throw new NoSuchAlgorithmException(algorithm);
        }
    }
@Test
    public void testGetChecksum_FileNotFound() throws Exception {
        String algorithm = "MD5";
        File file = new File("not a valid file");
        Exception exception = Assert.assertThrows(IOException.class, () -> Checksum.getChecksum(algorithm, file));
        assertTrue(exception.getMessage().contains("not a valid file"));
    }