In this assignment, you will build a very simple insurance company system. You will gain practice with inheritance, overriding methods, an abstract class, abstract methods and Exceptions. You will also make use of proper coding style by making public/private/protected attributes and methods and creating get/set methods. The insurance system will keep track of the insurance company's clients. Each client will have at least one policy with the company. The assignment constructs the system in three parts: defining insurance policies, defining clients and defining an Exception.
Define a public class called Policy which has a private static/class variable called NEXT_POLICY_NUMBER which is an int (initially set to 1) representing the number to be given to the next policy created. Create the following attributes in the class as well:
Create a public constructor which takes a single float parameter and uses it to set the amount variable. The constructor sets the policyNumber such that each created policy has a unique number and also updates the class variable appropriately.
Create public get methods for your attributes as well as a public toString() method that returns a String with the following format (use String.format() for both the policy number and amount) :
Policy: 0001 amount: $320.00
Create a public instance method called isExpired() which always returns false. Now test your code with this program:
public class PolicyTestProgram {
public static void main(String args[]) {
System.out.println(new Policy(320)); // displays Policy: 0001 amount: $320.00
System.out.println(new Policy(500.1f)); // displays Policy: 0002 amount: $500.10
System.out.println(new Policy(0)); // displays Policy: 0003 amount: $0.00
System.out.println(new Policy(320).isExpired()); // displays false
}
}
Now we will make some subclasses to represent different types of policies. Define a public class called DepreciablePolicy as a subclass of Policy which has a private attribute called rate of type float which represents the rate at which the policy depreciates each time a claim is made. For example, a rate of 0.10 means that the value of the policy (i.e., the amount) depreciates 10% each time a claim is made (we will discuss the making of claims in the next section). Implement these:
DepreciablePolicy: 0001 amount: $320.00 rate: 10.0%
You MUST make use of inheritance by calling the toString() from the superclass (You will have to make a change to the Policy class' toString() method as well. In addition, you will need to make the amount attribute from Policy to be protected now). Also, use String.format() again to display the rate.
Define a ExpirablePolicy class as a subclass of Policy which has a private attribute called expiryDate of type Date that contains the date after which the policy is invalid. The Date class is in the java.util package, so import java.util.* at the top of your code. Implement these:
GregorianCalendar aCalendar = new GregorianCalendar(); // makes today's date aCalendar.add(Calendar.YEAR,1); expiryDate = aCalendar.getTime();
ExpirablePolicy: 0001 amount: $320.00 expires: April 30, 2001You MUST make use of inheritance by calling the toString() from the superclass. Note that to display a date in the format above (i.e., April 30, 2001), you can use String.format() again with a format string of "%1$tb %1$te,%1$tY" for the date part.
Now test your new classes with this test program:
import java.util.*;
public class PolicyTestProgram2 {
public static void main(String args[]) {
DepreciablePolicy p1;
ExpirablePolicy p2, p3;
// Make sure that the Policy toString() method still works
System.out.println(new Policy(320));
// Make a DepreciablePolicy
p1 = new DepreciablePolicy(500.1f, 0.1f);
System.out.println(p1);
// Now depreciate it a little
p1.depreciate();
System.out.println(p1);
// Make an Expirable Policy
System.out.println(new ExpirablePolicy(1000));
// Make another Expirable Policy
p2 = new ExpirablePolicy(2000, new GregorianCalendar(2025, 0, 2).getTime());
System.out.println(p2);
System.out.println(p2.isExpired());
// Make yet another Expirable Policy
p3 = new ExpirablePolicy(2500, new GregorianCalendar(1997, 3, 1).getTime());
System.out.println(p3);
System.out.println(p3.isExpired());
}
}
Here is the output (assuming that today's date is before the year 2025)
Policy: 0001 amount: $320.00 DepreciablePolicy: 0002 amount: $500.10 rate: 10.0% DepreciablePolicy: 0002 amount: $450.09 rate: 10.0% ExpirablePolicy: 0003 amount: $1000.00 expires: May 28,2010 ExpirablePolicy: 0004 amount: $2000.00 expires: Jan 2,2025 false ExpirablePolicy: 0005 amount: $2500.00 expires: Apr 1,1997 true
Define a public class called Client which has a private static/class variable called NEXT_ID which is an int (initially set to 1) representing the number to be given to the next client created. Add the following attributes to the class as well:
Implement the following in the Client class:
Client 0001: John Smith
Now test what you have done so far with this program:
import java.util.*;
public class ClientTestProgram {
public static void main(String args[]) {
Client c = new Client("Bob B. Pins");
System.out.println(c);
c.openPolicyFor(100);
c.openPolicyFor(200, 0.10f);
c.openPolicyFor(300, new GregorianCalendar(2005, 0, 2).getTime());
System.out.println(c.getPolicies());
System.out.println(c.totalCoverage());
System.out.println(c.cancelPolicy(6));
System.out.println(c.cancelPolicy(1));
System.out.println(c.totalCoverage());
}
}
Here is the output:
Client 0001: Bob B. Pins [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: January 2, 2005] 600.0 null Policy: 0001 amount: $100.00 500.0
Now make the Client class abstract. Try running the test code above again but WITHOUT recompiling. Do you know what InstantiationError means ? Think about it ... and then try recompiling your test code. Now do you understand what happened ?
Now create two subclasses of Client, one called IndividualClient and the other called CompanyClient. Do not implement any attributes or methods yet for these classes. Try compiling them. Notice that your test code will not compile. That's because subclasses DO NOT inherit constructors and java requires a constructor to be available. You will have to create a constructor (taking a single String argument) for each of these subclasses that calls the one in Client explicitly. Alter your ClientTestProgram by changing the first line to be:
CompanyClient c = new CompanyClient("Bob B. Pins");
Re-run the test. Go back and change your toString() method in Client so that the proper client type is displayed. For example:
CompanyClient 0001: Bob B. Pins
Now define a public abstract method in the Client class called makeClaim(int polNum) that returns a float. After re-compiling the Client class, try recompiling the IndividualClient and CompanyClient classes. Do you understand the error message ?
Implement the makeClaim(int polNum) method in the IndividualClient class as follows. First check to make sure that the policy with the given number has not expired. If it has, then return 0. IndividualClients are allowed to make only 1 claim per for regular policies but Depreciable Policies and Expirable Policies can have multiple claims. So, if the Policy with the given number is of type Policy, you should remove the policy from the policies list after making this claim (make use of the cancelPolicy() method to do this). (Be careful if you use the instanceof keyword ... are subclasses of Policy instances of Policy ?) If the claim is being made for a DepreciablePolicy, then you must make sure to depreciate the policy. For IndividualClients, you should depreciate the policy BEFORE returning the claim amount. This method should return the amount of the policy if the policy was indeed valid, otherwise 0 is returned.
We will now write a similar method in the CompanyClient class. However, we will make use of the double dispatching technique. Before we do this, we will have to go write a method called handleClaim() in each of the policy classes so that we can make use of them here.
Now go back to the CompanyClient class and implement the makeClaim(int polNum) method so that it first checks to make sure the policy number is valid and then uses the double-dispatching technique by calling the handleClaim() method. Note that you MUST NOT use any IF statements to determine the policy type ... as that would undo the advantages of double-dispatching.
Test your code with the following program:
import java.util.*;
public class ClientTestProgram2 {
public static void main(String args[]) {
// Create an individual client, open some policies
// and then make some claims
IndividualClient ic = new IndividualClient("Bob B. Pins");
ic.openPolicyFor(100);
ic.openPolicyFor(200, 0.10f);
ic.openPolicyFor(300, new GregorianCalendar(2025, 0, 2).getTime());
ic.openPolicyFor(400, new GregorianCalendar(1999, 5, 4).getTime());
Policy p = new Policy(500);
System.out.println("Here are the Individual Client's policies:");
System.out.println(ic.getPolicies());
System.out.println("Making claims:");
System.out.println("Claim for policy 0001: " + ic.makeClaim(1));
System.out.println("Claim for policy 0002: " + ic.makeClaim(2));
System.out.println("Claim for policy 0003: " + ic.makeClaim(3));
System.out.println("Claim for policy 0004: " + ic.makeClaim(4));
System.out.println("Claim for policy 0005: " + ic.makeClaim(5));
System.out.println("Here are the Individual Client's policies after claims:");
System.out.println(ic.getPolicies());
// Create a company client, open some policies
// and then make some claims
CompanyClient cc = new CompanyClient("The Pillow Factory");
cc.openPolicyFor(1000);
cc.openPolicyFor(2000, 0.10f);
cc.openPolicyFor(3000, new GregorianCalendar(2025, 0, 2).getTime());
cc.openPolicyFor(4000, new GregorianCalendar(1999, 5, 4).getTime());
System.out.println("\nHere are the Company Client's policies:");
System.out.println(cc.getPolicies());
System.out.println("Making claims:");
System.out.println("Claim for policy 0006: " + cc.makeClaim(6));
System.out.println("Claim for policy 0007: " + cc.makeClaim(7));
System.out.println("Claim for policy 0008: " + cc.makeClaim(8));
System.out.println("Claim for policy 0009: " + cc.makeClaim(9));
System.out.println("Claim for policy 0005: " + cc.makeClaim(5));
System.out.println("Here are the Company Client's policies after claims:");
System.out.println(cc.getPolicies());
}
}
Here is the expected output:
Here are the Individual Client's policies: [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Making claims: Claim for policy 0001: 100.0 Claim for policy 0002: 180.0 Claim for policy 0003: 300.0 Claim for policy 0004: 0.0 Claim for policy 0005: 0.0 Here are the Individual Client's policies after claims: [DepreciablePolicy: 0002 amount: $180.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Here are the Company Client's policies: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $2000.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999] Making claims: Claim for policy 0006: 1000.0 Claim for policy 0007: 2000.0 Claim for policy 0008: 3000.0 Claim for policy 0009: 0.0 Claim for policy 0005: 0.0 Here are the Company Client's policies after claims: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $1800.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999]
Create a subclass of Exception called PolicyNotFoundException. Create a constructor that takes a String as a parameter and calls the superclass constructor that also takes a String (as we did in the notes). You do not need to create any other methods for this class.
Go back to your method in the Client class called getPolicy() and modify it so that instead of returning null when the policy is not found, a PolicyNotFoundException is thrown. When calling the exception's constructor, pass in a String of this format: "Bad Policy Number 0001" (where 0001 is the number of the policy being searched for). Note that you will be forced to declare that the method throws this new exception.
Try recompiling the Client class. Notice that any method which calls the getPolicy() method must now handle the exception (e.g., cancelPolicy()). Make changes to the cancelPolicy() method so that it also declares that it throws the exception. Now your Client code should compile.
You will have to go back into your makeClaim() method (i.e., in the CompanyClient and IndividualClient classes) to also handle the exception. DO NOT have your makeClaim() method throw any exceptions. Instead, handle the exception in the makeClaim() method directly by displaying the exception's message and returning 0. Simplify your method code, since you no longer have to check for null from the getPolicy() or cancelPolicy() methods.
Make changes to your ClientTestProgram so that it handles the PolicyNotFoundException each time the cancelPolicy() method is called. You should catch the exception and simply display its message (which you can obtain by sending getMessage() to the exception parameter). Here is the output that you should get .... notice the exception's message being shown:
CompanyClient: 0001 Bob B. Pins [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2005] 600.0 Bad Policy Number: 6 Policy: 0001 amount: $100.00 500.0
Here is the output from the ClientTestProgram2 after these exception changes:
Here are the Individual Client's policies: [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Making claims: Claim for policy 0001: 100.0 Claim for policy 0002: 180.0 Claim for policy 0003: 300.0 Claim for policy 0004: 0.0 Bad Policy Number: 5 Claim for policy 0005: 0.0 Here are the Individual Client's policies after claims: [DepreciablePolicy: 0002 amount: $180.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Here are the Company Client's policies: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $2000.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999] Making claims: Claim for policy 0006: 1000.0 Claim for policy 0007: 2000.0 Claim for policy 0008: 3000.0 Claim for policy 0009: 0.0 Bad Policy Number: 5 Claim for policy 0005: 0.0 Here are the Company Client's policies after claims: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $1800.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999]