@Nonnull
    @Override
    public Optional<PasswordBasedEncryption> parse(
            @Nullable final String str, @Nonnull DetectionLocation detectionLocation) {
        if (str == null) {
            return Optional.empty();
        }

        final String generalizedStr = str.toLowerCase().trim();
        if (!generalizedStr.contains("pbewith")) {
            return Optional.empty();
        }

        String hmacOrDigestStr;
        String cipherStr = null;
        int algoStartIndex = generalizedStr.indexOf("pbewith") + 7;
        if (generalizedStr.contains("and")) {
            int encIndex = generalizedStr.indexOf("and") + 3;
            cipherStr = str.substring(encIndex);
            hmacOrDigestStr = str.substring(algoStartIndex, generalizedStr.indexOf("and"));
        } else {
            hmacOrDigestStr = str.substring(algoStartIndex);
        }

        // cipher
        Optional<? extends Algorithm> cipherOptional = Optional.empty();
        if (cipherStr != null) {
            JcaCipherMapper cipherMapper = new JcaCipherMapper();
            cipherOptional = cipherMapper.parse(cipherStr, detectionLocation);
        }

        // hmac
        JcaMacMapper macMapper = new JcaMacMapper();
        Optional<? extends Algorithm> macOptional =
                macMapper.parse(hmacOrDigestStr, detectionLocation);
        if (macOptional.isPresent() && macOptional.get() instanceof Mac mac) {
            if (cipherOptional.isPresent() && cipherOptional.get() instanceof Cipher cipher) {
                return Optional.of(new PasswordBasedEncryption(mac, cipher));
            } else {
                return Optional.of(new PasswordBasedEncryption(mac));
            }
        }

        // digest
        JcaMessageDigestMapper messageDigestMapper = new JcaMessageDigestMapper();
        Optional<MessageDigest> messageDigestOptional =
                messageDigestMapper.parse(hmacOrDigestStr, detectionLocation);
        if (messageDigestOptional.isPresent()
                && cipherOptional.isPresent()
                && cipherOptional.get() instanceof Cipher cipher) {
            return Optional.of(new PasswordBasedEncryption(messageDigestOptional.get(), cipher));
        }

        return Optional.empty();
    }
@Test
    void base() {
        DetectionLocation testDetectionLocation =
                new DetectionLocation("testfile", 1, 1, List.of("test"), () -> "SSL");

        JcaPasswordBasedEncryptionMapper jcaPasswordBasedEncryptionMapper =
                new JcaPasswordBasedEncryptionMapper();
        Optional<PasswordBasedEncryption> pbeOpt =
                jcaPasswordBasedEncryptionMapper.parse(
                        "PBEWithHmacSHA256AndAES", testDetectionLocation);

        assertThat(pbeOpt).isPresent();
        PasswordBasedEncryption pbe = pbeOpt.get();
        assertThat(pbe.getName()).isEqualTo("PBEWithHmacSHA256AndAES");

        assertThat(pbe.getChildren()).hasSize(2);
        assertThat(pbe.getDigest()).isEmpty();
        assertThat(pbe.getCipher()).isPresent();
        assertThat(pbe.getMac()).isPresent();

        Mac mac = pbe.getMac().get();
        assertThat(mac.getName()).isEqualTo("HmacSHA256");
        assertThat(mac.getChildren()).hasSize(1);

        Cipher cipher = pbe.getCipher().get();
        assertThat(cipher).isInstanceOf(AES.class);
    }