Aqua Phoenix
     >>  Lectures >>  Java 3  
 

Navigator
   
 
       
   

3.5 Homework Assignment 3 - Employee Database

Due date and time: October 6, 2005 at 11:59:59am (noon)

Points: 16

This homework assignment is intended as an exercise for working with Arrays, Polymorphism, and Exception Handling in Java. It also serves as a follow-up exercise for the last homework.

You should not resort to Inheritance, even though it would be an acceptable way to complete the assignment. Use Polymorphism instead.

You will be creating a database of employees in a University. The database contains different types of people who share common properties related to employees: they work hours, they get paid certain hourly rates, and they accumulate salaries over time.

The types of people you will consider are:

  • Professor
  • SupportStaff
  • Student

Each of these three types of people have different constructors and different instance variables and methods that are unique to them. You should figure out from the following description what instance variables you need. Your classes should ONLY be instantiated using these constructors. No other constructors should be used.

  • Professor: ( Professor.java)
    • Constructors (follow the order in which values are passed to constructors):
      • accepts full name (String), name of department (String), and a boolean value denoting tenure (true) or not tenure (false).
      • accepts full name (String), name of department (String). In this case, you can assume that the professor does not have tenure.
    • Methods:
      • boolean hasTenure() : returns whether the professor has tenure or not
      • String getDepartment() : returns the name of the department
      • String toString() : returns a String that summarizes this person, i.e.: "Professor NAME in Department DEPARTMENT (TENURED OR NOT)"
  • SupportStaff: ( SupportStaff.java)
    • Constructors:
      • accepts full name (String), area of support (String), and a boolean value denoting unionized (true) or not unionized (false).
      • accepts full name (String), area of support (String). In this case, assume that the position is non-unionized.
    • Methods:
      • boolean isUnionized()
      • String getSupportArea()
      • String toString() : returns a String that summarized this person, i.e.: "Support Staff NAME in area AREA (UNIONIZED OR NOT)"
  • Student: ( Student.java)
    • Constructors:
      • accepts full name (String), year (int), school (String), major (String)
      • accepts full name (String), year (int), school (String). In this case, assume that the major is "Undecided".
    • Methods:
      • int getYear()
      • String getSchoolName()
      • String getMajorName()
      • String toString() : returns a String that summarized this person, i.e.: "Student NAME in school SCHOOL, year YEAR, with major MAJOR"

Write an interface called Payable. This interface should define the following methods:

  • String getName()
  • double addHoursWorked(int h)
  • void setPayRate(float dollars)
  • double getSalaryTotal()
  • void printAccount()

All three of the people classes must implement this interface. Be sure to add the appropriate methods to all of the classes that implement Payable. You will also need to update the instance variables in those classes to reflect the functionality expected by interface Payable. For example, you will need to hold values for the pay rate, total salary, and total hours worked.

By default, when a class has been instantiated, the instance variables needed for the interface methods should be set to defaults. For example, once a Student object has been created, the student's total salary should be initialized to zero, and so should her pay rate. Only when the methods from the interface are called on the objects, should the instance variables for pay rate and total salary change.

The interaction with any of the people classes is dictated as follows:

  1. Create an object of some type (Professor, SupportStaff, or Student). This will merely create the objects, and set default values for salary information.
  2. If the person should get paid at some point for work performed, then:
    • the method setPayRate(float) will be called to set an hourly wage
    • the method addHoursWorked(int) will be called to declare the amount of time that has been worked
    • inside addHoursWorked(int) , the current wage rate is used to compute the total salary for the newly worked hours (passed as an argument)
    • the newly worked hours are added to the instance variable that aggregates all hours worked
    • the computed wage is added to the total salary, and also returned to note how much money the person has earned for this pay period
  3. For any future payment cycle, if setPayRate(float) is not called before addHoursWorked(int) , then the current pay rate is used for that payment cycle

The following exception handling should be added to your code:

  • For method addHoursWorked(int) , add an exception handler that throws a new exception when the pay rate has never been set, i.e. it is still zero. Obviously, any number of hours worked multiplied by a zero pay rate returns zero dollars. This is bad practice for accounting, and thus we require that any work is compensated, even if it is just one cent per hour. Example code for adding exception handling is demonstrated in the lecture notes. Just to reiterate, here is a simple example for divison of numbers. When the denominator is zero, a generic exception is thrown:

      public double divideNumbers(int a, int b) throws Exception {
        if (b == 0) {
          throw new Exception("Infinity");
        }
        return a / b;
      }
    The exception is then caught by whatever calls divideNumbers():

      ...
      try {
        divideNumbers(9, 0);
      } catch (Exception e) {
        System.out.println(e.getMessage());
      }
      ...
    This will print the message "Infinity".

    You should extrapolate from this code and implement an exception that is thrown when the hourly rate is set to 0. The message you pass to Exception should reflect this.

  • Also throw an exception when the hourly rate is set to a negative number. This should be prevented, and thus you should throw an exception with an appropriate message.
  • Implement a further thrown exception when the number of hours worked that are passed are negative.

To manage all employees, you will need to create the EmployeeManager class. This class will keep track of all employees in an array of type Payable. Do not use a hashtable or any other such data structure.

Define a constant ( static final int MAX_SIZE = 20 ) which will denote the maximum number of people that can exist in the array. In your constructor for EmployeeManager, you will instantiate the array with the size defined by MAX_SIZE.

Remember that by default, all objects in an Object array are set to null. You will need to keep track of the current number of valid (non-null) objects in the array. When there are no objects in the array, this variable will be zero. When the first object is placed into the array, then this variable increments by one and it will point to the next available slot. Once this variable equals the constant MAX_SIZE, then all slots are filled, and no more persons can be added.

You will need to implement several methods that can be called from the outside. These methods are used to manage the employees:

  • void addEmployee(Payable p) throws Exception : This method takes an object of type Payable (which can be a Professor, SupportStaff, or Student), and adds that person to the database (array). Before adding the person to the database, you should check whether a person by that name already exists. You can do this by iterating over the valid objects of type Payable and compare their names to the one passed to this method. If a matching name exists, then the new person cannot be added, and instead an exception with an appropriate message is thrown.

    When there are no more slots in the array into which the passed Payable object can be placed, then an exception should be thrown with a message like "The University is full".

    String comparison in the case of Payable objects is performed as follows. Assume that you are comparing the names of 2 Payable objects p1 and p2:

      if (p1.getName().equals(p2.getName())) {
        // the two Payable objects have the same name
      }
    The class String contains a method by the name of equals(String s), which compares a String object to another String object: "Joe" is not equal "John", but "Jane" does equal "Jane".
  • void payEmployee(String name, double hoursWorked, float payRate) throws Exception : This method will pay an employee by the name passed as an argument. Before paying the employee, you will need to iterate over the array of valid objects Payable, and find the employee. Again, use string comparison between name and each Payable's name. When a match is found, call the appropriate methods in Payable. You will need to call setPayRate() and addHoursWorked() in order to achieve the purpose of this method. If no match is found, then throw an exception with an appropriate message. If a match is found, then, after calling the method to add hours worked, you should print out a message to that effect, e.g. "Employee NAME has been paid: YYY dollars".
  • void payEmployee(String name, double hoursWorked) throws Exception : This is the same as the previous method, with the exception that it does not take the payRate argument. Once the matching Payable object has been located, you can call the appropriate method in Payable that fits this method's purpose.
  • void printAll() : This method should iterate over all employees and print out their information as well as their account status. You will have implemented two methods for this purpose. One of them (toString()) prints out personal information. The other (printAccount()) should print out a message that summarizes this person's salary history, including total hours worked, current pay rate, and total (accumulated) salary earned so far.

3.5.1 Driver class

To test your implementation, create a HW3 class, in which you:
  • instantiate one EmployeeManager object
  • and create a few Professors, SupportStaffs, and Students, in order to try out your code. You can turn in this class, but I will test your EmployeeManager with a different test class, which will try out several combinations.
  • Suggestions:
    • Test your Employee database with more than 20 objects, just so that you don't get any unforeseen array errors
    • Do not spend effort in writing a complicated HW3 class. You can simply copy-and-paste the instantiations of several Payable objects to test your code. You will not be graded on HW3.java, but instead on the other files.
    • Be sure to test all methods, i.e. paying people, paying people that don't exist, paying people with wrong rates, etc.
    • Bottom-line: You want to turn in something that will not break, regardless of what I try to call. The success of your assignment is entirely in your hands.

3.5.2 Recommended work-flow

  1. Create the three person classes: Professor, SupportStaff, Student.
  2. Try instantiating these classes by themselves and calling methods on them.
  3. Create the Payable interface.
  4. Implement the interface for ONE of the three person classes, and try out the new methods.
  5. When successful, repeat for the other two person classes.
  6. Do not implement any exception handling yet.
  7. Implement the EmployeeManager class.
  8. Implement the array that will hold Payable objects.
  9. One at a time, implement the mentioned methods in EmployeeManager. Do so without exception handling.
  10. Once you succeed, revisit one method at a time, and implement exception handling.

3.5.3 Submission instructions

Use the submit script to submit your assignment (instructions on class web site).