/*
* @author : Charlie Lee
* @date : 2020-08-31
* @email : find1086@gmail.com
* @conf : openJDK 11.0.2
*
* @comment: simple national bank account management program.
* UUID.randomUUID() logically equals account number in this program.
* @to-do : save data to RDB or some place.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;
enum BankList {
AMERICA, INDIA, SINGAPORE, CHINA, KOREA
}
public class BankService {
private final static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private final static Map<String, List<Account>> map = new HashMap<>();
private final static List<User> users = new ArrayList<>();
private static final BankService bankService = getInstance();
private BankService() {}
public static BankService getInstance() {
if(bankService == null) return new BankService();
return bankService;
}
private static Long accountId = 0L;
public static void main(String[] args) throws IOException {
runBankService();
}
public static void runBankService() throws IOException {
createUsers();
createAccounts();
printInformation();
manageAccount();
}
private static void createUsers() throws IOException {
System.out.print("how many user you want to create? : ");
int n = parseToInt(br.readLine());
for (int i = 0; i < n; i++) {
createUser();
}
}
private static void createAccounts() throws IOException {
System.out.print("how many account you want to create? : ");
int m = parseToInt(br.readLine());
for (User user : users) {
for (int j = 0; j < m; j++) {
createAccount(user);
}
System.out.println("complete creating account.");
}
}
private static void createUser() throws IOException {
System.out.print("type username to create: ");
String username = br.readLine();
users.add(new User(username));
}
private static void createAccount(User user) throws IOException {
System.out.println("Which bank account would you like to create?");
printBanksList();
chooseBankName(user);
}
private static void printBanksList() {
System.out.print("[ ");
String banks = Arrays.stream(BankList.values())
.map(String::valueOf)
.collect(Collectors.joining(", "));
System.out.print(banks);
System.out.println(" ]");
}
private static void chooseBankName(User user) throws IOException {
System.out.print("choose bankname you want to create: ");
String src = (br.readLine()).toUpperCase();
boolean isValidBankName = checkValidBankName(src);
if (isValidBankName) {
Account account = new Account(++accountId, src, String.valueOf(UUID.randomUUID()));
checkDuplicateAccount(user, account);
user.addAccount(account);
map.put(user.getUsername(), user.getAccountList());
} else {
throw new Error("sorry. could not find bank in the list. please try later.");
}
}
private static boolean checkValidBankName(String src) {
for (BankList bank : BankList.values()) {
if (src.equals(bank.toString())) return true;
}
return false;
}
private static void checkDuplicateAccount(User user, Account account) {
if (map.isEmpty()) return;
if (map.get(user.getUsername()) == null || map.get(user.getUsername()).size() <= 0) return;
boolean check = findDuplicatedAccount(user, account);
if (check) throw new Error("this account already exists. please check right account registration.");
}
private static boolean findDuplicatedAccount(User user, Account account) {
return map.get(user.getUsername())
.stream()
.anyMatch(acc -> acc.equals(account));
}
private static void printInformation() {
Set<String> key = map.keySet();
for (User u : users) {
for (Iterator<String> iterator = key.iterator(); iterator.hasNext(); ) {
System.out.println("username: " + iterator.next() + ", account: " + map.get(u.getUsername()));
}
}
}
private static boolean validateRegisteredUser(String name) {
if (!map.containsKey(name)) {
System.out.println("this user seems not registered yet. check your query right please.");
return false;
}
return true;
}
private static void manageAccount() throws IOException {
boolean flag = true;
while (flag) {
String name = chooseUserAccount();
List<Account> accountsOfanUser = map.get(name);
printUserAccount(accountsOfanUser);
// 4-1. specify which account state change.
Account account = chooseOneAccount(accountsOfanUser);
controlAccount(account);
flag = continueToManage();
}
}
private static boolean continueToManage() throws IOException {
System.out.println("would you like to continue to manage account? (y/n)");
String value = br.readLine();
if (value.equals("n")) {
System.out.println("okay. program will be shut down.");
return false;
}
return true;
}
private static Account chooseOneAccount(List<Account> accountsOfanUser) throws IOException {
System.out.println("which account's balance do you want to change?");
System.out.print("please choose number in [], not account id : ");
int accountId = parseToInt(br.readLine()) - 1;
return accountsOfanUser.get(accountId);
}
private static void printUserAccount(List<Account> accountsOfanUser) {
System.out.println("The user has : ");
for (int i = 1; i <= accountsOfanUser.size(); i++) {
System.out.println("[" + i + "] " + accountsOfanUser.get(i - 1));
}
}
private static String chooseUserAccount() throws IOException {
String name;
do {
System.out.println("::: user account list :::");
Set<String> key = map.keySet();
for (String o : key) {
System.out.print(o + " ");
}
System.out.println("\nwhich users account do you want manage? : ");
name = br.readLine();
} while (!validateRegisteredUser(name));
return name;
}
private static void controlAccount(Account account) throws IOException {
boolean changeMoneyProcess = true;
int chooseNum;
while (changeMoneyProcess) {
System.out.println("what would you want to do? choose number please.");
System.out.println("[1] deposit [2] withdraw [3] show money balance");
chooseNum = parseToInt(br.readLine());
switch (chooseNum) {
case 1: {
System.out.println("how much money do you want to deposit ?");
account.depositMoney(parseToDouble(br.readLine()));
break;
}
case 2: {
System.out.println("how much money do you want to withdraw ?");
account.withdrawMoney(parseToDouble(br.readLine()));
break;
}
case 3:
break;
default:
System.out.println("not service this number yet.");
}
System.out.printf("money balance : %5.2f\n", account.getMoney());
changeMoneyProcess = wantToContinueChangeMoney();
}
}
private static Integer parseToInt(String text) throws IOException {
boolean isAbleToParseInt = false;
int parsedInt = 0;
while (!isAbleToParseInt) {
try {
parsedInt = Integer.parseInt(text);
isAbleToParseInt = true;
} catch (NumberFormatException nfe) {
System.out.println("it seems not number! please check again.");
System.out.print("how many user you want to create? : ");
text = br.readLine();
}
}
return parsedInt;
}
private static Double parseToDouble(String text) throws IOException {
boolean isAbleToParseDouble = false;
double parsedDouble = 0;
while (!isAbleToParseDouble) {
try {
parsedDouble = Double.parseDouble(text);
isAbleToParseDouble = true;
} catch (NumberFormatException nfe) {
System.out.println("it seems not number! please check again.");
System.out.print("how many user you want to create? : ");
text = br.readLine();
}
}
return parsedDouble;
}
private static boolean wantToContinueChangeMoney() throws IOException {
System.out.println("would you want to continue changing money balance ? (y/n)");
return !(br.readLine()).equals("n");
}
}
class User {
private final String username;
private final List<Account> accountList;
public User(String username) {
this.username = username;
accountList = new ArrayList<>();
}
public String getUsername() {
return username;
}
public void addAccount(Account account) {
accountList.add(account);
}
public List<Account> getAccountList() {
return accountList;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", accountList=" + accountList +
'}';
}
}
class Account {
private final Long id;
private final String bankName;
private final String accountNumber;
private double money;
public Account(Long id, String bankName, String accountNumber) {
this.id = id;
this.bankName = bankName;
this.accountNumber = accountNumber;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Account)) return false;
Account account = (Account) o;
return Objects.equals(id, account.id) &&
Objects.equals(bankName, account.bankName) &&
Objects.equals(accountNumber, account.accountNumber);
}
@Override
public int hashCode() {
return Objects.hash(id, bankName, accountNumber);
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", bankName='" + bankName + '\'' +
", accountNumber='" + accountNumber + '\'' +
'}';
}
public double getMoney() {
return money;
}
public void depositMoney(double money) {
this.money += money;
}
public void withdrawMoney(double money) {
if ((this.money -= money) < 0) {
throw new Error("you can't withdraw that money.");
}
this.money -= money;
}
}
// http://colorscripter.com/s/YX09IfQ