/*=======================================
Loan.java
This applet calculates the time it would take
to repay a loan of money, when
interest is being charged. For example, if I
borrow ? million, and I pay
back ?00,000 every year, how long will it
take to pay off the whole loan?
If we can answer this question, it is very
easy to answer another important
question: how much do I pay in total,
including interest?
This applet calculate both these figures, from
the users figures for
amount borrowed, interest rate and repayment
amount. It doesnt matter
what units of currency are used, as long as
you are consistent (i.e.,
the repayment amount and the amount borrowed
are in the same currency).
The interest rate should be entered as a
percentage.
The programss display looks like this:
<img src=loan.gif>
<p>
(If you arent looking at the HTML
version of this file, you wont see
the picture)
The user should enter the appropriate figures,
then click on `Calculate
to get the results.
This is a good program for demonstrating
Javas exception handling
mechanisms, as theres any number of
things that can go wrong in this
program. For example:
1. The user may not fill all the data entry
fields in
2. The user may enter values which are not
numbers at all (e.g., text)
3. The user may enter values which are valid
numbers, but are nonetheless
invalid in the context of this application
(e.g., repayments of zero)
4. The values may all be sensible, but it is
still impossible to get
a sensible result. This will happen if the
amount of the repayment
is less than the interest on the loan (then
the loan will never be
repayed)
A good program will deal correctly with all
these problems, and produce
sensible guidance to the user in each case. It
is never acceptable in
modern practice for a program to say `INVALID
DATA and shut down!
You will notice that in this application
approximately half the code
is concerned with checking and handling
errors. But the good thing about the
exception throwing scheme is that the
`normal program code and the
`error program code is largely separate.
In this program, the exception
classes are all defined after the main part of
the program
Please note that I am not an accountant, so I
cant be sure that my
repayment calculations are correct!
Kevin Boone, July 1999
==============================================================================*/
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/*==============================================================================
Loan class
Defines a sub-type of applet that implements a
loan calculator
==============================================================================*/
public class Loan extends Applet implements
ActionListener
{
/*==============================================================================
Attributes of Loan class
==============================================================================*/
// We store the objects that correspond to
data entry fields as attributes,
// as when the user starts a calculation we
will need to refer to them
// to get the data out
TextField amountBorrowedField;
TextField interestRateField;
TextField repaymentField;
// The result label is that part of the
display where the result will be
// displayed
Label resultLabel;
/*==============================================================================
Loan constructor
This method (as with all constructors) is
executed when the new object
is created.
The applets display area has three main
parts; from top to bottom these
are: the result display, the data entry area,
and the `calculate
button. The data entry area has three text
areas and the corresponding
labels. This part is organized as a grid of 3
rows and 2 columns.
The main display is organized as a
BorderLayout. The data entry area
will go in the centre of this area, the result
area at the top
(`North) and the calculate button at the
bottom (`South).
==============================================================================*/
public Loan()
{
super();
Panel entryPanel = new Panel();
entryPanel.setLayout (new GridLayout(3, 2));
Label l = new Label ("Amount
borrowed:");
l.setAlignment (Label.RIGHT);
entryPanel.add(l);
amountBorrowedField = new TextField();
entryPanel.add(amountBorrowedField);
l = new Label ("Interest rate
(%):");
l.setAlignment (Label.RIGHT);
entryPanel.add(l);
interestRateField = new TextField();
entryPanel.add(interestRateField);
l = new Label ("Repayment:");
l.setAlignment (Label.RIGHT);
entryPanel.add(l);
repaymentField = new TextField();
entryPanel.add(repaymentField);
setLayout(new BorderLayout());
add(entryPanel, "Center");
resultLabel = new Label("?");
resultLabel.setAlignment(Label.CENTER);
add(resultLabel, "North");
Button calculateButton = new
Button("Calculate");
calculateButton.addActionListener(this);
add(calculateButton , "South");
}
/*==============================================================================
getFieldValue
This method attempts to get a numerical value
from a specified data entry
field. If this cannot be accomplished, for any
reason, it throws an exception
to indicate the reason. The caller of this
method is responsible for
dealing with the exception if one arrives.
This method has three arguments. The first,
`field is the data entry
field itself. This will have been created in
the constructor with a
call to `new TextField(). The second is
the name of the field. This name will
be saved in the exception if anything goes
wrong, so that the exception can
display an error message indicating where the
error occured. Finally
`zeroAllowed is `true if it is
meaningful for the data entry field to have
`zero as its value. In this application,
the interest rate can meaningfully
be zero, but none of the other fields can
==============================================================================*/
double getFieldValue (TextField field, String
fieldName, boolean zeroAllowed)
throws EmptyNumberFieldException,
NotANumberException,
NegativeNotAllowedException,
ZeroNotAllowedException
{
// First get the text value out of the data
entry fieinto a
// String.
String stringValue = field.getText();
// Is the data entry field empty? If so, throw
an
// EmptyNumberFieldExceptino. Note that the
name of the field is
// passed to the exceptions constructor,
so that it can be stored
// and used in error messages
if (stringValue.equals(""))
throw (new
EmptyNumberFieldException(fieldName));
try
{
// Now try to convert the string to a double
value.
// If this fails (e.g., if the data is not a
number), then
// a NumberFormatException will be thown. We
will catch
// that exception, and convert it to a
NotANumberException.
// The main reason for doing this is that the
built-in
// NumberFormatException displays a very ugly
and unhelpful
// error messages, which we can improve upon
easily.
double value =
Double.parseDouble(stringValue);
// If the value is negative, throw and
NegativeNotAllowedException