class Config implements DiagnosticsProvider, Configuration {

    private Config( File configFile,
            boolean throwOnFileLoadFailure,
            Map<String,String> initialSettings,
            Map<String,String> overriddenDefaults,
            Collection<ConfigurationValidator> additionalValidators,
            List<LoadableConfig> settingsClasses )
    {
        configOptions = settingsClasses.stream()
                .map( LoadableConfig::getConfigOptions )
                .flatMap( List::stream )
                .collect( Collectors.toList() );

        settingsMap = new HashMap<>();
        configOptions.stream()
                .map( ConfigOptions::settingGroup )
                .filter( BaseSetting.class::isInstance )
                .map( BaseSetting.class::cast )
                .forEach( setting -> settingsMap.put( setting.name(), setting ) );

        validators.addAll( additionalValidators );
        migrator = new AnnotationBasedConfigurationMigrator( settingsClasses );
        this.overriddenDefaults.putAll( overriddenDefaults );

        boolean fromFile = configFile != null;
        if ( fromFile )
        {
            loadFromFile( configFile, log, throwOnFileLoadFailure, initialSettings );
        }

        overriddenDefaults.forEach( initialSettings::putIfAbsent );

        migrateAndValidateAndUpdateSettings( initialSettings, fromFile );

        // Only warn for deprecations if red from a file
        if ( fromFile )
        {
            warnAboutDeprecations( params );
        }
    }

    private  Config( File configFile,
            boolean throwOnFileLoadFailure,
            Map<String,String> initialSettings,
            Map<String,String> overriddenDefaults,
            Collection<ConfigurationValidator> additionalValidators,
            List<LoadableConfig> settingsClasses );

}