Amount
public interface Amount extends Comparable<Amount>{
public Amount add(Amount value);
public Amount subtract(Amount value);
@Override
public int compareTo(Amount amount);
}
Note that anything that implements Amount must be comparable to any other implementation of Amount. This lets us mix implementations without worrying about their details.
The implementation I'm using for Rupiz will be backed by an instance of BigDecimal with a scale of 2 decimal digits.
Transaction
public class Transaction implements Comparable<Transaction>{
public final Amount amount;
public final Account source;
public final Account destination;
public final String description;
public final LocalDate dateStamp;
public Transaction(Amount amt, Account src, Account dest) {
this("", amt, src, dest, new LocalDate());
}
public Transaction(Amount amt, Account src,Account dest, LocalDate date){
this("", amt, src, dest, date);
}
public Transaction(String desc, Amount amt, Account src, Account dest) {
this(desc, amt, src, dest, new LocalDate());
}
public Transaction(String desc, Amount amt, Account src, Account dest, LocalDate date) {
description = desc;
amount = amt;
source = src;
destination = dest;
dateStamp = date;
}
@Override
public int compareTo(Transaction trans) {
int value = dateStamp.compareTo(trans.dateStamp);
if(value != 0)
return value;
value = source.getDescription().compareTo(trans.source.getDescription());
if(value != 0)
return value;
value = destination.getDescription().compareTo(trans.destination.getDescription());
if(value != 0)
return value;
value = amount.compareTo(trans.amount);
if(value != 0)
return value;
return description.compareTo(trans.description);
}
}
The major design decision with the Transaction class was whether to make it immutable. For now, I'm leaning towards immutability mainly because it's a value object and it will be put into ordered sets, at which point modifying the object is a Very Bad Thing.
Account
public class Account {
private String description;
private Amount amount;
private Set<Transaction> transactions;
// Global source account for deposits from unspecified sources
static Account globalSource = new Account("Opening Balances",
new DecimalAmount(new BigDecimal("0.00"))) {...};
// Constructors snipped
// Setters & Getters snipped
public Amount depositFor(Amount amount, String description) {
return depositForOn(amount, description, new LocalDate());
}
public Amount depositForOn(Amount amount, String description, LocalDate date) {
return globalSource.transferToForOn(amount, this, description, date);
}
public Amount transferToFor(Amount amount, Account destination, String description) {
return transferToForOn(amount, destination, description, new LocalDate());
}
public Amount transferToForOn(Amount amount, Account destination,
String description, LocalDate date) {
Transaction trans = new Transaction(description, amount,
this, destination, date);
destination.amount = destination.amount.add(amount);
amount = amount.subtract(amount);
transactions.add(trans);
destination.transactions.add(trans);
return amount;
}Account is pretty straightforward. It keeps track of the transactions that involve the account and provides methods to move amounts in and out of the acount.
With these classes complete, I can begin working on the actual application.
The source for the classes above can be downloaded here.