import java.util.HashMap;
import java.util.Map;

public class ContohRollback {

    // ---- lapisan akses data dengan dukungan transaksi ----

    static final class RepoSaldo {

        private final Map<String, Long> tabel = new HashMap<>();
        private Map<String, Long> snapshot;

        void mulaiTransaksi() {
            snapshot = new HashMap<>(tabel);
        }

        void commit() {
            snapshot = null;
        }

        void rollback() {
            tabel.clear();
            tabel.putAll(snapshot);
            snapshot = null;
        }

        void simpan(String pemilik, long jumlah) {
            if (jumlah < 0) {
                throw new IllegalArgumentException("saldo tidak boleh negatif: " + jumlah);
            }
            tabel.put(pemilik, jumlah);
        }

        Long cari(String pemilik) {
            return tabel.get(pemilik);
        }

        int jumlah() {
            return tabel.size();
        }
    }

    public static void main(String[] args) {
        RepoSaldo repo = new RepoSaldo();
        repo.simpan("Budi", 100_000L);
        repo.simpan("Siti", 250_000L);
        System.out.println("penyiapan       : 2 baris data awal");

        // ---- test 1: transfer di dalam transaksi yang digulung ----
        repo.mulaiTransaksi();
        repo.simpan("Budi", repo.cari("Budi") - 50_000L);
        repo.simpan("Siti", repo.cari("Siti") + 50_000L);
        System.out.println("dalam transaksi : Budi=" + repo.cari("Budi")
            + ", Siti=" + repo.cari("Siti"));
        repo.rollback();
        System.out.println("setelah digulung: Budi=" + repo.cari("Budi")
            + ", Siti=" + repo.cari("Siti"));

        // ---- test 2: pelanggaran aturan digulung otomatis ----
        repo.mulaiTransaksi();
        try {
            repo.simpan("Budi", -1L);
        } catch (IllegalArgumentException e) {
            repo.rollback();
            System.out.println("pelanggaran     : " + e.getMessage());
        }
        System.out.println("data akhir      : " + repo.jumlah()
            + " baris, Budi=" + repo.cari("Budi"));
    }
}
