class CmakeServerExternalNativeJsonGenerator extends CmakeExternalNativeJsonGenerator {

    @VisibleForTesting
    protected NativeBuildConfigValue getNativeBuildConfigValue(
            @NonNull JsonGenerationAbiConfiguration abiConfig, @NonNull Server cmakeServer)
            throws IOException {
        NativeBuildConfigValue nativeBuildConfigValue = createDefaultNativeBuildConfigValue();

        assert nativeBuildConfigValue.stringTable != null;
        StringTable strings = new StringTable(nativeBuildConfigValue.stringTable);

        // Build file
        assert nativeBuildConfigValue.buildFiles != null;
        nativeBuildConfigValue.buildFiles.addAll(getBuildFiles(abiConfig, cmakeServer));

        // Clean commands
        assert nativeBuildConfigValue.cleanCommands != null;
        nativeBuildConfigValue.cleanCommands.add(
                CmakeUtils.getCleanCommand(
                        getCmakeExecutable(), abiConfig.getExternalNativeBuildFolder()));

        CodeModel codeModel = cmakeServer.codemodel();
        if (!ServerUtils.isCodeModelValid(codeModel)) {
            throw new RuntimeException(
                    String.format(
                            "Invalid code model received from Cmake server: \n%s\n%s",
                            getObjectToString(codeModel), getCmakeInfoString(cmakeServer)));
        }

        // C and Cpp extensions
        assert nativeBuildConfigValue.cFileExtensions != null;
        nativeBuildConfigValue.cFileExtensions.addAll(CmakeUtils.getCExtensionSet(codeModel));
        assert nativeBuildConfigValue.cppFileExtensions != null;
        nativeBuildConfigValue.cppFileExtensions.addAll(CmakeUtils.getCppExtensionSet(codeModel));

        // toolchains
        nativeBuildConfigValue.toolchains =
                getNativeToolchains(
                        abiConfig.getAbiName(),
                        cmakeServer,
                        nativeBuildConfigValue.cppFileExtensions,
                        nativeBuildConfigValue.cFileExtensions);

        String toolchainHashString = getOnlyToolchainName(nativeBuildConfigValue.toolchains);

        // Fill in the required fields in NativeBuildConfigValue from the code model obtained from
        // Cmake server.
        for (Configuration config : codeModel.configurations) {
            for (Project project : config.projects) {
                for (Target target : project.targets) {
                    // Ignore targets that aren't valid.
                    if (!canAddTargetToNativeLibrary(target)) {
                        continue;
                    }

                    NativeLibraryValue nativeLibraryValue =
                            getNativeLibraryValue(
                                    abiConfig.getAbiName(),
                                    abiConfig.getExternalNativeBuildFolder(),
                                    target,
                                    strings);
                    nativeLibraryValue.toolchain = toolchainHashString;
                    String libraryName =
                            target.name + "-" + config.name + "-" + abiConfig.getAbiName();
                    assert nativeBuildConfigValue.libraries != null;
                    nativeBuildConfigValue.libraries.put(libraryName, nativeLibraryValue);
                } // target
            } // project
        }
        return nativeBuildConfigValue;
    }

    public  CmakeServerExternalNativeJsonGenerator(
            @NonNull JsonGenerationVariantConfiguration config,
            @NonNull Set<String> configurationFailures,
            @NonNull AndroidBuilder androidBuilder,
            @NonNull File cmakeFolder,
            @NonNull GradleBuildVariant.Builder stats);

}