CODE
public class Loan implements Serializable {
private static final long serialVersionUID = 121536765900L;
// ---------------------------------------------------------------
// variables
private List<Amortization> amortizations = new ArrayList<Amortization>();
private double loanAmount = 0.00;
private double interestRate = 0.00;
private double paymentAmount = 0.00;
private int years = 0;
private boolean calculated = false;
// ---------------------------------------------------------------
// Constructors
/**
* Zero argument Constructor required by Java Beans standards and Serializable implementation
*/
public Loan () {
clear();
}
/**
* Primary Constructor
* Sets calculation values from supplied parameters. Does NOT call calculate method.
*
* @param double Loan Amount
* @param double Yearly Interest Rate
* @param double Term of Loan in Years
*
* @throws LoanParameterException Exception throw on invalid or out of bounds parameters
*/
public Loan (double loanAmount, double interestRate, int years)
throws LoanParameterException {
clear();
this.setLoanAmount(loanAmount);
this.setInterestRate(interestRate);
this.setYears(years);
}
// ---------------------------------------------------------------
// Business Methods
/**
* This method calculates the monthly payment amount and generates the amortization schedule
*
* @throws ArithmeticException On calculation or invalid parameters in calculations
*/
public void calculate () throws ArithmeticException {
int numberOfPayments = 12 * this.getYears();
double payment;
double interestAmount = 0.00;
double principleAmount = 0.00;
double totalInterest = 0.00;
double loanBalance = this.getLoanAmount();
try {
if (this.getInterestRate() == 0.0) {
payment = round(loanAmount / numberOfPayments);
this.setPaymentAmount(payment);
for (int i=0; i < numberOfPayments; i++){
if (payment > loanBalance) {
payment = loanBalance;
}
principleAmount = payment;
totalInterest = 0.0;
loanBalance = round(loanBalance - principleAmount);
if ((i == numberOfPayments -1) && (loanBalance > 0.0)) {
payment = payment + loanBalance;
loanBalance = 0.0;
}
addAmortization( new Amortization(payment,
interestAmount,
principleAmount,
totalInterest,
loanBalance));
}
}
else {
double monthlyInterest = (this.getInterestRate() * .01) / 12;
// EAR = 1 - ((1 + Interest/month) ** -number of months)
double ear = 1 - Math.pow((monthlyInterest + 1), -numberOfPayments);
// Payment = (Interest * Loan Amount) / (EAR)
payment = round((monthlyInterest * this.getLoanAmount()) / ear);
this.setPaymentAmount(payment);
for (int i=0; i < numberOfPayments; i++){
interestAmount = round(loanBalance * monthlyInterest);
if ((payment + interestAmount) > loanBalance) {
payment = loanBalance + interestAmount;
}
principleAmount = round(payment - interestAmount);
totalInterest = round(totalInterest + interestAmount);
loanBalance = round(loanBalance - principleAmount);
if ((i == numberOfPayments -1) && (loanBalance > 0.0)) {
payment = payment + loanBalance;
loanBalance = 0.0;
}
addAmortization( new Amortization(payment,
interestAmount,
principleAmount,
totalInterest,
loanBalance));
}
}
calculated = true;
}
catch (Exception e) {
calculated = false;
throw new ArithmeticException(e.toString());
}
}
/**
* This method is used internally to round calculated values to dollar and cent amounts
* Uses ROUND_HALF_UP method to round values. <p>
* Example: 1.005 rounds up to 1.01 and 1.004 rounds down to 1.00
*
* @param double Amount to Round
* @return double Rounded Value
*/
private double round (double amount) {
BigDecimal bd = new BigDecimal(Double.toString(amount));
bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
/**
* This method clears all parameters and calculated values. <p>
* Resets Loan object to initial state.
*/
public void clear() {
this.amortizations = new ArrayList<Amortization>();
this.loanAmount = 0.00;
this.interestRate = 0.00;
this.paymentAmount = 0.00;
this.years = 0;
this.calculated = false;
}
// ---------------------------------------------------------------
// Attribute Modifiers
/**
* Add a new Amortization object to the list
*/
private void addAmortization(Amortization amortization) {
amortizations.add(amortization);
}
/**
* @return List<Amortization> of Amortization Objects in order
*/
public List<Amortization> getAmortization() {
return amortizations;
}
/**
* @return double The Loan Amount
*/
public double getLoanAmount() {
return loanAmount;
}
/**
* @param double The Loan Amount to set
*
* @throws LoanParameterException Exception thrown Loan amounts Greater than 1 billion or less than 1
*/
public void setLoanAmount(double loanAmount)
throws LoanParameterException {
if (loanAmount < 1) {
throw new LoanParameterException("Invalid Loan Amount: Amount less than $1");
}
if (loanAmount >= 1000000000L) {
throw new LoanParameterException("Invalid Loan Amount: Amount Over $1 Billion");
}
this.calculated = false;
this.loanAmount = loanAmount;
}
/**
* @return double The Yearly Interest Rate
*/
public double getInterestRate() {
return interestRate;
}
/**
* @param double The Yearly Interest Rate to set
*/
public void setInterestRate(double interestRate)
throws LoanParameterException {
if (interestRate < 0) {
throw new LoanParameterException("Invalid Interest Rate: Less than 0%");
}
if (interestRate >= 100L) {
throw new LoanParameterException("Invalid Interest Rate: Rate Over 100%");
}
this.calculated = false;
this.interestRate = interestRate;
}
/**
* @return int The term of the loan in years
*/
public int getYears() {
return years;
}
/**
* @param int The term of the loan in years to set
*/
public void setYears(int years)
throws LoanParameterException {
if (years < 1) {
throw new LoanParameterException("Invalid Term: Less than 1 year");
}
if (years >= 100L) {
throw new LoanParameterException("Invalid Term: Over 100 years");
}
this.calculated = false;
this.years = years;
}
/**
* @return double The monthly payment amount
*/
public double getPaymentAmount() {
return paymentAmount;
}
/**
* @param double The monthly payment amount to set
*/
private void setPaymentAmount(double paymentAmount) {
this.paymentAmount = paymentAmount;
}
/**
* @return boolean true if calculate method has been called since last clear
* false if calculate method not called since parameters have changed
*/
public boolean isCalculated() {
return calculated;
}
// ---------------------------------------------------------------
// Overloaded Methods
/**
* @return String Loan default string or
* loan decorator's format method return if decorator is installed
*/
public String toString() {
DecimalFormat rateDF = new DecimalFormat("###.##");
DecimalFormat dollarsDF = new DecimalFormat("$###,###,##0.00");
StringBuffer output = new StringBuffer();
output.append( "Loan Amortization\n" );
output.append ( "Loan Amount : " + dollarsDF.format(this.getLoanAmount())+ "\n" );
output.append ( "Interest Rate: " + rateDF.format(this.getInterestRate()) + "\n" );
output.append ( "Term in Years: " + this.getYears() + "\n" );
output.append ( "Payment Amount : " + dollarsDF.format(this.getPaymentAmount())+ "\n" );
return output.toString();
}
// ---------------------------------------------------------------
// Static test code removed
/**
public static void main(String[] args) {
double amount = 200000.00;
double interest = 5.75;
int years = 30;
Loan loan = new Loan(amount, interest, years);
loan.calculate();
loan.setDecorator(new LoanReportDecorator());
System.out.println (loan.toString());
try {
PrintWriter loanFile = new PrintWriter(new FileWriter("c:/loan.txt"));
loanFile.println(loan.toString());
loanFile.close();
loanFile.flush();
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println ("----------------------------------------------------------");
loan.setDecorator(new LoanXMLDecorator());
System.out.println (loan.toString());
try {
PrintWriter xmlFile = new PrintWriter(new FileWriter("c:/loan.xml"));
xmlFile.println(loan.toString());
xmlFile.close();
xmlFile.flush();
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println ("----------------------------------------------------------");
loan.setDecorator(new LoanHTMLDecorator());
System.out.println (loan.toString());
try {
PrintWriter htmlFile = new PrintWriter(new FileWriter("c:/loan.html"));
htmlFile.println(loan.toString());
htmlFile.close();
htmlFile.flush();
}
catch (Exception e) {
e.printStackTrace();
}
}
*/
}
Edited to add the [ code] tags
Please
This post has been edited by pbl: 25 Aug, 2008 - 05:22 PM