class GenesisImporter {

    @Transactional
    public void importGenesisJson(final boolean loadOnlyPublicKeys) {
        final long start = System.currentTimeMillis();
        createGenesisTaskIdForStatus(); // recreate taskId for task execution status update

        this.blockchainConfigUpdater.reset();

        final TransactionalDataSource dataSource = databaseManager.getDataSource();
        // load 'public Keys' from JSON only
        if (!dataSource.isInTransaction()) {
            dataSource.begin();
        }
        // Always remove possibly previously 'incomplete genesis import' data
        cleanUpGenesisData(); // clean up previous incomplete genesis import (if any)

        final int publicKeyNumber = savePublicKeys(dataSource);

        dataSource.commit(false);
        if (loadOnlyPublicKeys) {
            log.debug("Public Keys were saved in {} ms. The rest of GENESIS is skipped, shard info will be loaded...",
                (System.currentTimeMillis() - start) / 1000);
            return;
        }
        // load 'balances' from JSON only
        final Pair<Long, Integer> balanceStatistics = saveBalances(dataSource);
        final Integer balanceNumber = balanceStatistics.getRight();
        final long total = balanceStatistics.getLeft();

        final long maxBalanceATM = blockchainConfig.getCurrentConfig().getMaxBalanceATM();
        if (total > maxBalanceATM) {
            throw new RuntimeException("Total balance " + total + " exceeds maximum allowed " + maxBalanceATM);
        }
        final String message = String.format("Total balance %f %s", (double) total / Constants.ONE_APL, blockchainConfig.getCoinSymbol());
        final Account creatorAccount = accountService.addGenesisAccount(CREATOR_ID);
        accountPublicKeyService.apply(creatorAccount, CREATOR_PUBLIC_KEY, true);
        accountService.addToBalanceAndUnconfirmedBalanceATM(creatorAccount, null, 0, -total);
        aplAppStatus.durableTaskFinished(genesisTaskId, false, message);
        log.debug("Public Keys [{}] + Balances [{}] were saved in {} ms", publicKeyNumber, balanceNumber,
            (System.currentTimeMillis() - start) / 1000);
        this.genesisTaskId = null;

        final Long usedBytes = null; //Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory(); // to measure in unit tests
        log.debug("ImportGenesisJson is computed in {} milliSec, used {} Kb", System.currentTimeMillis() - start,
            usedBytes != null ? usedBytes / 1024 : "not calculated");
    }

    @Inject public  GenesisImporter(
        BlockchainConfig blockchainConfig,
        BlockchainConfigUpdater blockchainConfigUpdater,
        DatabaseManager databaseManager,
        AplAppStatus aplAppStatus,
        GenesisImporterProducer genesisImporterProducer,
        AccountGuaranteedBalanceTable accountGuaranteedBalanceTable,
        AccountTable accountTable,
        ApplicationJsonFactory jsonFactory,
        PropertiesHolder propertiesHolder,
        AccountService accountService,
        AccountPublicKeyService accountPublicKeyService
    );

}