class OnlineBackupContextFactory {

    public OnlineBackupContext createContext( String... args ) throws IncorrectUsage, CommandFailed
    {
        try
        {
            Arguments arguments = arguments();
            arguments.parse( args );

            OptionalHostnamePort address = Converters.toOptionalHostnamePortFromRawAddress( arguments.get( ARG_NAME_BACKUP_SOURCE ) );
            Path folder = this.getBackupDirectory( arguments );
            String name = arguments.get( ARG_NAME_BACKUP_NAME );
            boolean fallbackToFull = arguments.getBoolean( ARG_NAME_FALLBACK_FULL );
            boolean doConsistencyCheck = arguments.getBoolean( ARG_NAME_CHECK_CONSISTENCY );
            long timeout = (Long) arguments.get( ARG_NAME_TIMEOUT, TimeUtil.parseTimeMillis );
            SelectedBackupProtocol selectedBackupProtocol = SelectedBackupProtocol.fromUserInput( arguments.get( ARG_NAME_PROTO_OVERRIDE ) );
            String pagecacheMemory = arguments.get( ARG_NAME_PAGECACHE );
            Optional<Path> additionalConfig = arguments.getOptionalPath( ARG_NAME_ADDITIONAL_CONFIG_DIR );
            Path reportDir = (Path) arguments.getOptionalPath( ARG_NAME_REPORT_DIRECTORY ).orElseThrow( () ->
                                                                                                        {
                                                                                                            return new IllegalArgumentException(
                                                                                                                    ARG_NAME_REPORT_DIRECTORY +
                                                                                                                    " must be a path" );
                                                                                                        } );
            OnlineBackupRequiredArguments requiredArguments =
                    new OnlineBackupRequiredArguments( address, folder, name, selectedBackupProtocol, fallbackToFull, doConsistencyCheck, timeout, reportDir );

            Path configFile = configDir.resolve( Config.DEFAULT_CONFIG_FILE_NAME );
            Config.Builder builder = Config.fromFile( configFile );
            Path logPath = requiredArguments.getResolvedLocationFromName();

            Config config = builder.withHome( this.homeDir ).withSetting( GraphDatabaseSettings.logical_logs_location,
                                                                          logPath.toString() ).withConnectorsDisabled().withNoThrowOnFileLoadFailure().build();

            additionalConfig.map( this::loadAdditionalConfigFile ).ifPresent( config::augment );

            // We only replace the page cache memory setting.
            // Any other custom page swapper, etc. settings are preserved and used.
            config.augment( GraphDatabaseSettings.pagecache_memory, pagecacheMemory );

            // Disable prometheus to avoid binding exceptions
            config.augment( "metrics.prometheus.enabled", Settings.FALSE );

            // Build consistency-checker configuration.
            // Note: We can remove the loading from config file in 4.0.
            BiFunction<String,Setting<Boolean>,Boolean> oneOf = ( a, s ) -> arguments.has( a ) ? arguments.getBoolean( a ) : config.get( s );

            ConsistencyFlags consistencyFlags = new ConsistencyFlags( config );

            return new OnlineBackupContext( requiredArguments, config, consistencyFlags );
        }
        catch ( IllegalArgumentException e )
        {
            throw new IncorrectUsage( e.getMessage() );
        }
        catch ( UncheckedIOException e )
        {
            throw new CommandFailed( e.getMessage(), e );
        }
    }

      OnlineBackupContextFactory( Path homeDir, Path configDir );

}