class KeyDataUtil {

    public static ConfigKeyPair unmarshal(final KeyData keyData, final KeyEncryptor keyEncryptor) {

        // case 1, the keys are provided inline
        if (isDirect(keyData)) {
            return new DirectKeyPair(keyData.getPublicKey(), keyData.getPrivateKey());
        }

        // case 2, the config is provided inline
        if (isInline(keyData)) {
            InlineKeypair keyPair = new InlineKeypair(keyData.getPublicKey(), keyData.getConfig(), keyEncryptor);
            keyPair.withPassword(keyData.getPassword());
            return keyPair;
        }

        // case 3, the Azure Key Vault data is provided
        if (isAzure(keyData)) {
            return new AzureVaultKeyPair(
                    keyData.getAzureVaultPublicKeyId(),
                    keyData.getAzureVaultPrivateKeyId(),
                    keyData.getAzureVaultPublicKeyVersion(),
                    keyData.getAzureVaultPrivateKeyVersion());
        }

        // case 4, the Hashicorp Vault data is provided
        if (isHashicorp(keyData)) {

            Integer hashicorpVaultSecretVersion;

            Optional<String> hashicorpVaultSecretVersionStr =
                    Optional.of(keyData).map(KeyData::getHashicorpVaultSecretVersion);

            if (hashicorpVaultSecretVersionStr.isPresent()) {
                hashicorpVaultSecretVersion =
                        hashicorpVaultSecretVersionStr
                                .filter(Pattern.compile("^\\d*$").asPredicate())
                                .map(Integer::parseInt)
                                .orElse(-1);
            } else {
                hashicorpVaultSecretVersion = 0;
            }

            return new HashicorpVaultKeyPair(
                    keyData.getHashicorpVaultPublicKeyId(),
                    keyData.getHashicorpVaultPrivateKeyId(),
                    keyData.getHashicorpVaultSecretEngineName(),
                    keyData.getHashicorpVaultSecretName(),
                    hashicorpVaultSecretVersion);
        }

        // case 5, the AWS Secrets Manager data is provided
        if (isAws(keyData)) {
            return new AWSKeyPair(
                    keyData.getAwsSecretsManagerPublicKeyId(), keyData.getAwsSecretsManagerPrivateKeyId());
        }

        // case 6, the keys are provided inside a file
        if (isFileSystem(keyData)) {
            FilesystemKeyPair fileSystemKeyPair =
                    new FilesystemKeyPair(keyData.getPublicKeyPath(), keyData.getPrivateKeyPath(), keyEncryptor);
            fileSystemKeyPair.withPassword(keyData.getPassword());
            return fileSystemKeyPair;
        }

        // case 7, the key config specified is invalid
        return new UnsupportedKeyPair(
                keyData.getConfig(),
                keyData.getPrivateKey(),
                keyData.getPublicKey(),
                keyData.getPrivateKeyPath(),
                keyData.getPublicKeyPath(),
                keyData.getAzureVaultPublicKeyId(),
                keyData.getAzureVaultPrivateKeyId(),
                keyData.getAzureVaultPublicKeyVersion(),
                keyData.getAzureVaultPrivateKeyVersion(),
                keyData.getHashicorpVaultPublicKeyId(),
                keyData.getHashicorpVaultPrivateKeyId(),
                keyData.getHashicorpVaultSecretEngineName(),
                keyData.getHashicorpVaultSecretName(),
                keyData.getHashicorpVaultSecretVersion(),
                keyData.getAwsSecretsManagerPublicKeyId(),
                keyData.getAwsSecretsManagerPrivateKeyId());
    }

    private  KeyDataUtil();

}