class KeyGenCommand implements Callable<CliResult> {

    @Override
    public CliResult call() throws IOException {
        // TODO(cjh) this check shouldn't be required as --configfile is marked as 'required' in KeyGenFileUpdateOptions
        if (Objects.nonNull(fileUpdateOptions) && Objects.isNull(fileUpdateOptions.getConfig())) {
            throw new CliException("Missing required argument(s): --configfile=<config>");
        }

        final EncryptorConfig encryptorConfig = this.encryptorConfig().orElse(EncryptorConfig.getDefault());
        final KeyVaultOptions keyVaultOptions = this.keyVaultOptions().orElse(null);
        final KeyVaultConfig keyVaultConfig = this.keyVaultConfig().orElse(null);

        KeyEncryptor keyEncryptor = KeyEncryptorFactory.newFactory().create(encryptorConfig);
        final KeyGenerator generator = factory.create(keyVaultConfig, encryptorConfig);

        final List<String> newKeyNames = new ArrayList<>();

        if (Objects.isNull(keyOut) || keyOut.isEmpty()) {
            newKeyNames.add("");
        } else {
            newKeyNames.addAll(keyOut);
        }

        final List<ConfigKeyPair> newConfigKeyPairs =
                newKeyNames.stream()
                        .map(name -> generator.generate(name, argonOptions, keyVaultOptions))
                        .collect(Collectors.toList());

        final List<char[]> newPasswords =
                newConfigKeyPairs.stream()
                        .filter(Objects::nonNull)
                        .map(ConfigKeyPair::getPassword)
                        .collect(Collectors.toList());

        final List<KeyData> newKeyData =
                newConfigKeyPairs.stream().map(pair -> keyDataMarshaller.marshal(pair)).collect(Collectors.toList());

        if (Objects.isNull(fileUpdateOptions)) {
            return new CliResult(0, true, null);
        }

        // prepare config for addition of new keys if required
        if (Objects.isNull(fileUpdateOptions.getConfig().getKeys())) {
            fileUpdateOptions.getConfig().setKeys(new KeyConfiguration());
        }
        if (Objects.isNull(fileUpdateOptions.getConfig().getKeys().getKeyData())) {
            fileUpdateOptions.getConfig().getKeys().setKeyData(new ArrayList<>());
        }

        if (Objects.nonNull(fileUpdateOptions.getConfigOut())) {
            if (Objects.nonNull(fileUpdateOptions.getPwdOut())) {
                passwordFileUpdaterWriter.updateAndWrite(
                        newPasswords, fileUpdateOptions.getConfig(), fileUpdateOptions.getPwdOut());
                fileUpdateOptions.getConfig().getKeys().setPasswordFile(fileUpdateOptions.getPwdOut());
            }
            configFileUpdaterWriter.updateAndWrite(
                    newKeyData, keyVaultConfig, fileUpdateOptions.getConfig(), fileUpdateOptions.getConfigOut());
        } else {
            configFileUpdaterWriter.updateAndWriteToCLI(newKeyData, keyVaultConfig, fileUpdateOptions.getConfig());
        }

        return new CliResult(0, true, null);
    }

      KeyGenCommand(
            KeyGeneratorFactory keyGeneratorFactory,
            ConfigFileUpdaterWriter configFileUpdaterWriter,
            PasswordFileUpdaterWriter passwordFileUpdaterWriter);

}