The task:
There is an AccountManager that makes transfers. It receives 2 arrays of the same size: accounts and sums. They need to be transferred to the accounts correspondingly.
public interface AccountManager {
public boolean transfer(Account[] accounts, int[] deltas);
}
There is also an Account interface:
public interface Account {
public void change(int delta) throws TryAgainException, BlockAccountException;
}
If change() throws TryAgainException, we just need to repeat the transfer operation. If change() throws BlockAccountException, we need to roll back the transfer operation. That is, reverse all changes to previous accounts.
AccountClass
public class AccountClass implements Account {
// setting initial value to 100. so that account would not be empty
private int accountNum;
private int currentAccount = 100;
public AccountClass(int accountNum) {
this.accountNum = accountNum;
}
@Override
public void change(int delta) throws TryAgainException,
BlockAccountException {
System.out.println("account before change" + toString());
int newBalance = getCurrentAccount() + delta;
if (newBalance < 0) {
throw new BlockAccountException(
"money cannot be withdrawn as balance will be negative");
} else if (delta == 100) {
throw new TryAgainException();
}
setCurrentAccount(getCurrentAccount() + delta);
System.out.println("account after change" + toString());
}
public int getCurrentAccount() {
return currentAccount;
}
@Override
public String toString() {
return "Account" + accountNum + " [currentAccount=" + currentAccount + "]";
}
// making setter private so it will be impossible to modify account from
// outside
private void setCurrentAccount(int currentAccount) {
this.currentAccount = currentAccount;
}
AccountManagerClass
public class AccountManagerClass implements AccountManager {
@Override
public boolean transfer(Account[] accounts, int[] deltas) {
for (int i = 0; i < accounts.length; i++) {
int tryNum = 0;
while (true) {
try {
accounts[i].change(deltas[i]);
break;
} catch (TryAgainException e) {
tryNum++;
if (tryNum == 5) {
break;
}
System.out.println("trying again");
} catch (BlockAccountException e) {
// rollback
System.out.println(e.getMessage());
System.out.println("rolling back");
if (i > 0) {
for (int j = i - 1; j >= 0; j--) {
try {
accounts[j].change(-deltas[j]);
} catch (TryAgainException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (BlockAccountException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
return false;
}
}
}
return true;
}
Main
public class Main {
public static void main(String[] args) {
AccountManagerClass accountManagerClass = new AccountManagerClass();
Account[] accounts = {new AccountClass(1), new AccountClass(2), new AccountClass(3), new AccountClass(4)};
int[] deltas = {100, 200, -200, 99};
accountManagerClass.transfer(accounts, deltas);
}
}