Jump to: navigation, search


ATM with different treatment of accounts

 * This team realizes the ATM.
 * An ATM belongs to a certain bank and only for withdrawal from a foreign account
 * an additional fee is debited. Furthermore it is not possible to query the balance
 * of a foreign account.
public team class ATM {
    private Bank myBank;
    private Account feeAccount;

    public ATM(Bank bank) {
        myBank = bank;
        feeAccount = new Account(bank);

     * Returns the balance of the fee account.
    int getFeeAccountBalance() {
        return feeAccount.getBalance();

     * Pays the given amount of cash from the given account, if it contains enough money.
    public int payCash(Account account, int amount) {
        boolean ok = account.debit(amount);
        if (ok)
            return amount;
            return 0;

     * Returns the balance of the given Account object. If an exception is thrown while 
     * accessing the balance of the account this method throws an AccessDeniedException.
    public int getBalance(Account account) throws AccessDeniedException {
        try {
            return account.getBalance();
        } catch (Exception e) {
            throw new AccessDeniedException();

     * This role is responsible for the different handling of accounts belonging to a 
     * different bank than the ATM does (foreign accounts).
     * The guard predicate attached to the ForeignAccount role ensures that this role 
     * and therefore all its callin bindings are only effective for foreign accounts. 
     * It checks, if the bank of the base object to be lifted is different from the bank
     * of the ATM.
    public class ForeignAccount playedBy Account
        base when (!(ATM.this.myBank.equals(base.getBank())))
         * This callin method calls its base method with the given amount plus an 
         * additional fee.
        callin boolean debitWithFee(int amount) {
            int fee = calculateFee(amount);
            if (base.debitWithFee(fee+amount)) {
                System.out.println("Debiting from a foreign account: " + 
                                   "Additional fee of "+fee+" Euro will be debited!");
                return true;
            return false;
         * Binds the role method debitWithFee to the base method debit of the
         * base class Account.
        debitWithFee <- replace debit;

         * Restricting the query of balance, is realized as another callin method
         * denying the call to getBalance for foreign accounts. Because of the role
         * predicate, this callin method is not called for own accounts.
        callin int checkedGetBalance() {
            throw new RuntimeException("Access to balance of foreign account not allowed!");

         * Binds the role method checkedGetBalance to the base method getBalance of
         * the base class Account.
        checkedGetBalance <- replace getBalance;

         * Returns the fee for debiting the given amount from a foreign account.
         * Here this is a fixed fee of 5%.
        public int calculateFee(int amount) {
            int feePercent = 5;
            return (amount/100)*feePercent;


  • Lines 1-44 apply straight-forward Java programming for implementing the basic behaviour of the ATM.
  • Role ForeignAccount (l.55ff) implements the following adaptions for its base class Account:
    • When method debit(int) is invoked the amount is increased by a variable fee (see calculateFee(int)), and the account is debited with the resulting total. The fee is then credited to a fixed feeAccount.
    • Any attempt to query the balance of the account will be prohibited by throwing a RuntimeException.
  • The above conditions are, however, not applied to all accounts but only to those belonging to a different Bank than the ATM's Bank.
    • Different Accounts are distinguished by the guard predicate in the role's header (line 56) (OTJLD §5.4).
    • This guard is evaluated whenever any callin binding of this role is about to fire. Thus for accounts of the local bank all callins are simply blocked.
  • A frequent question regards line 64: this base call (OTJLD §4.3) invokes the original behaviour that has been intercepted by the current callin method. Note, that a base call always uses the name and signature of the enclosing method. Only by the callin method binding (line 76) the callin method and its base call are both bound to the method debit(int) of Account. This indirection is needed so that the same callin method can be bound to several base methods. The base call will always invoke the base method on which a callin binding fired.