Payroll System Modification in Java

(Payroll System Modification) Modify the payroll system of Figs. 10.4–10.9 to include private instance variable birth Date in class Employee. Use class Date of Fig. 8.7 to represent an employee’s birthday. Add get methods to class Date. Assume that payroll is processed once per month.Create an array of Employee variables to store references to the various employee objects. In a loop,calculate the payroll for each Employee (polymorphically), and add a $100.00 bonus to the person’s payroll amount if the current month is the one in which the Employee’s birthday occurs.

Payroll System Modification in Java

/*
 *       Filename:  PayrollSystemTest.java
 *
 *    Description:  Exercise 10.10 - Payroll System Modification
 *
*  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
import java.util.Calendar;

public class PayrollSystemTest{
    public static void main(String[] args){
        int currentMonth = 1 + Calendar.getInstance().get(Calendar.MONTH);

        // create four element Employee array
        Employee[] employees = new Employee[5];

        // initialise array with Employees
        employees[0] = new SalariedEmployee(
                "John", "Smith", "111-11-1111", 800.0f, 11, 3, 1883);
        employees[1] = new HourlyEmployee(
                "Karen", "Price", "222-22-2222", 16.75f, 40.0f, 12, 12, 1975);
        employees[2] = new CommissionEmployee(
                "Sue", "Jones", "333-33-3333", 10000.0f, .06f, 12, 13, 1965);
        employees[3] = new BasePlusCommissionEmployee(
                    "Bob", "Lewis", "444-44-4444", 5000.0f, .04f, 300.0f, 12, 12, 1956);
        employees[4] = new PieceWorker(
                "Deez", "Nutz", "555-55-5555", 20.25f, 52.0f, 10, 11, 1983);

        System.out.println("Employees processed polymorphically:\n");

        for(Employee currentEmployee : employees){
            System.out.println(currentEmployee);

            // determine whether element is a BasePlusCommissionEmployee
            if(currentEmployee instanceof BasePlusCommissionEmployee){
                // downcase Employee reference to
                // BasePlusCommissionEmployee reference
                BasePlusCommissionEmployee employee =
                    (BasePlusCommissionEmployee) currentEmployee;

                employee.setBaseSalary(1.10f * employee.getBaseSalary());

                System.out.printf("new base salary with 10%% increase is: $%,.2f\n",
                        employee.getBaseSalary());


            }

            // add $100.0 if birth month is current
            System.out.printf("earned $%,.2f\n\n",
                    (currentEmployee.getBirthday().getMonth() == currentMonth) ?
                    currentEmployee.earnings() + 100.0f : currentEmployee.earnings());
        }

        // get type name of each object in employee array
        for(int j=0; j<employees.length; j++){
            System.out.printf("Employee %d is a %s\n",
                    j, employees[j].getClass().getName());
        }
    }
}

PieceWorker.java

/*
 *       Filename:  PieceWorker.java
 *
 *    Description:  Exercise 10.10 - Payroll System Modification
 *
*  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class PieceWorker extends Employee{
    private double wage;
    private double pieces;

    // constructor
    public PieceWorker(String first, String last, String ssn,
            double wage, double pieces, int month, int day, int year){
        super(first, last, ssn, month, day, year);

        setWage(wage);
        setPieces(pieces);
    }
    // SETTERS
    public void setWage(double w){
        if(w >= 0.0f)
            this.wage = w;
        else
            throw new IllegalArgumentException(
                    "Wage must be >= 0.0f");
    }
    public void setPieces(double p){
        if(p >= 0.0f)
            this.pieces = p;
        else
            throw new IllegalArgumentException(
                    "Pieces must be >= 0.0f");
    }
    // GETTERS
    public double getWage(){
        return this.wage;
    }
    public double getPieces(){
        return this.pieces;
    }
    // calculate earnings; override abstract method in Employee
    @Override
    public double earnings(){
        return getPieces() * getWage();
    }
    // String representation of object
    @Override
    public String toString(){
        return String.format("piece worker: %s\n%s: $%,.2f; %s: %,.2f",
                super.toString(), "wage", getWage(),
                "pieces produced", getPieces());
    }
}

Method 1 : Payroll System Modification in Java

BasePlusCommissionEmployee.java

/*
 *       Filename:  BasePlusCommissionEmployee.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
*  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class BasePlusCommissionEmployee extends CommissionEmployee{
    private double baseSalary;

    // constructor
    public BasePlusCommissionEmployee(String first, String last, String ssn,
            double sales, double rate, double salary, int month, int day, int year){
        // call CommissionEmployee constructor
        super(first, last, ssn, sales, rate, month, day, year);
        setBaseSalary(salary);
    }
    // SETTERS
    public void setBaseSalary(double salary){
        if(salary >= 0.0f)
            baseSalary = salary;
        else
            throw new IllegalArgumentException(
                    "Base salary must be >= 0.0f");
    }
    // GETTERS
    public double getBaseSalary(){
        return this.baseSalary;
    }
    // calculate earnings; override method earnings in CommissionEmployee
    @Override
    public double earnings(){
        return getBaseSalary() + super.earnings();
    }
    // return String representation of object
    @Override
    public String toString(){
        return String.format("%s %s; %s: $%,.2f",
                "base-salaried", super.toString(),
                "base salary", getBaseSalary());
    }
}

CommissionEmployee.java

/*
 *       Filename:  CommissionEmployee.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
 *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class CommissionEmployee extends Employee{
    private double grossSales;
    private double commissionRate;

    // constructor
    public CommissionEmployee(String first, String last, String ssn,
            double sales, double rate, int month, int day, int year){
        super(first, last, ssn, month, day, year);
        setGrossSales(sales);
        setCommissionRate(rate);
    }
    // SETTERS
    public void setCommissionRate(double rate){
        if(rate > 0.0f && rate < 1.0f)
            this.commissionRate = rate;
        else
            throw new IllegalArgumentException(
                    "Commission rate must be > 0.0f and < 1.0f");
    }
    public void setGrossSales(double sales){
        if(sales >= 0.0f)
            this.grossSales = sales;
        else
            throw new IllegalArgumentException
                ("Gross sales muse be >= 0.0f");
    }
    // GETTERS
    public double getCommissionRate(){
        return this.commissionRate;
    }
    public double getGrossSales(){
        return this.grossSales;
    }
    // calculate earnings; override abstract method earnings in Employee
    @Override
    public double earnings(){
        return getCommissionRate() * getGrossSales();
    }
    // String representation of object
    @Override
    public String toString(){
        return String.format("%s: %s\n%s: $%,.2f; %s: %.2f",
                "commission employee", super.toString(),
                "gross sales", getGrossSales(),
                "commission rate", getCommissionRate());
    }
}

Date.java

/*
 *       Filename:  Date.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
 *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class Date{
    private static final int MONTHS_IN_YEAR = 12;
    private static final int FEB_LEAP_YEAR = 29;

    // non static so as not to screw up non leap year february's
    private final int[] daysPerMonth =
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    private static final String[] strMonths =
    {"", "January", "February", "March", "April", "May", "June", "July", "August",
     "September", "October", "November", "December"};

    private static final String[] strDays =
    {"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

    private int[] date = new int[3];

    // constructors
    // overloaded constructors need to set year first
    // to check for/against leap year
    // default
    public Date(){
        date[0] = 1;
        date[1] = 1;
        date[2] = 1900;
    }
    // mm dd yyyy - 3 ints
    public Date(int month, int day, int year){
        setYear(year);
        setMonth(month);
        setDay(day);
    }
    // month dd yyyy - string month 2 ints
    public Date(String month, int day, int year){
        setYear(year);
        setStringMonth(month);
        setDay(day);
    }
    // DDDD YYYY - longform day number and year
    public Date(int dayOfYear, int year){
        setYear(year);
        setLongFormDay(dayOfYear);
    }
    // SETTERS
    public void setMonth(int month){
        date[0] = checkMonth(month);
    }
    public void setStringMonth(String month){
        date[0] = checkStringMonth(month);
    }
    public void setDay(int day){
        date[1] = checkDay(day);
    }
    // get month and day from day of year
    public void setLongFormDay(int dayOfYear){
        if(dayOfYear <= 0 || dayOfYear > 365)
            throw new IllegalArgumentException("day of year must be 1-365");

        int month = 1;

        // if leap year fix daysPerMonth day count
        if(isLeapYear() && daysPerMonth[2] != FEB_LEAP_YEAR)
            daysPerMonth[2] = FEB_LEAP_YEAR;

        // determine the month by sequentially subtracting daysPerMonth
        // and incrementing months counter. Remainder is day of month
        while(dayOfYear > daysPerMonth[month]){
            dayOfYear -= daysPerMonth[month];
            month++;
        }

        setMonth(month);
        setDay(dayOfYear);
    }
    public void setYear(int year){
        date[2] = checkYear(year);
    }
    // GETTERS
    public int getMonth(){
        return date[0];
    }
    public int getDay(){
        return date[1];
    }
    public int getYear(){
        return date[2];
    }
    // return int representation of day number in the year
    // add total daysPerMonth upto one month before current
    // add day onto total
    private int getDayOfYear(){
        int tmp = 0;

        for(int i=1; i<date[0]; i++){
            tmp += daysPerMonth[i];
        }
        return tmp + date[1];
    }
    // ensures string month is valid
    private int checkStringMonth(String month){
        if(month.length() > 1)
            month = month.substring(0, 1).toUpperCase() + month.substring(1);

        // check for matches
        for(int i=1; i<strMonths.length; i++){
            if(strMonths[i].equals(month))
                return i;
        }

        throw new IllegalArgumentException("invalid month string");
    }
    // check month is within correct range
    private int checkMonth(int testMonth){
        if(testMonth > 0 && testMonth <= MONTHS_IN_YEAR)
            return testMonth;
        else
            throw new IllegalArgumentException("month must be 1-12");
    }
    // check day is within range for month
    private int checkDay(int testDay){
        if(isLeapYear() && daysPerMonth[2] != FEB_LEAP_YEAR)
            daysPerMonth[2] = FEB_LEAP_YEAR;

        if(testDay > 0 && testDay <= daysPerMonth[getMonth()])
            return testDay;

        throw new IllegalArgumentException("day out of range for specified month and year");
    }
    // check for leap year
    private boolean isLeapYear(){
        return (getYear() % 400 == 0 || (getYear() % 4 == 0 && getYear() % 100 != 0));
    }
    // check year is within 4 digit range and not negative
    private int checkYear(int testYear){
        if(testYear >= 0 && testYear <= 9999)
            return testYear;
        else
            throw new IllegalArgumentException("year must be 0-9999");
    }
    // string representations
    public String toString(){
        return String.format("%02d/%02d/%04d", date[0], date[1], date[2]);
    }
    public String toLongDateString(){
        return String.format("%s %02d %04d", strMonths[date[0]], date[1], date[2]);
    }
    public String toDayOfYearString(){
        return String.format("%03d %04d", getDayOfYear(), date[2]);
    }
}

Employee.java

/*
 *       Filename:  Employee.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
 *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public abstract class Employee{
    private String firstName;
    private String lastName;
    private String socialSecurityNumber;
    private Date birthDay;

    // constructor
    public Employee(String first, String last, String ssn,
            int month, int day, int year){

        setFirstName(first);
        setLastName(last);
        setSocialSecurityNumber(ssn);

        birthDay = new Date(month, day, year);
    }
    // SETTERS
    public void setFirstName(String first){
        this.firstName = first;
    }
    public void setLastName(String last){
        this.lastName = last;
    }
    public void setSocialSecurityNumber(String ssn){
        this.socialSecurityNumber = ssn;
    }
    // GETTERS
    public String getFirstName(){
        return this.firstName;
    }
    public String getLastName(){
        return this.lastName;
    }
    public String getSocialSecurityNumber(){
        return this.socialSecurityNumber;
    }
    public Date getBirthday(){
        return this.birthDay;
    }
    // return String representation of Employee object
    @Override
    public String toString(){
        return String.format("%s %s\nsocial security number: %s",
                getFirstName(), getLastName(), getSocialSecurityNumber());
    }
    // ABSTRACT METHODS
    // not implemented here
    public abstract double earnings();
}

HourlyEmployee.java

/*
 *       Filename:  HourlyEmployee.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
 *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class HourlyEmployee extends Employee{
    private double wage;
    private double hours;

    // constructor
    public HourlyEmployee(String first, String last, String ssn,
            double hourlyWage, double hoursWorked, int month, int day, int year){
        // explicit Employee constructor call
        super(first, last, ssn, month, day, year);
        setWage(hourlyWage);
        setHours(hoursWorked);
    }
    // SETTERS
    public void setWage(double hourlyWage){
        if(hourlyWage >= 0.0f)
            this.wage = hourlyWage;
        else
            throw new IllegalArgumentException(
                    "Hourly wage must be >= 0.0f");
    }
    public void setHours(double hoursWorked){
        if((hoursWorked >= 0.0f) && (hoursWorked <= 168.0f))
            this.hours = hoursWorked;
        else
            throw new IllegalArgumentException(
                    "Hours worked must be >= 0.0f and <= 16.0f");
    }
    // GETTERS
    public double getWage(){
        return this.wage;
    }
    public double getHours(){
        return this.hours;
    }
    // calculate earnings; override abstract method earnings in Employee
    @Override
    public double earnings(){
        if(getHours() <= 40)
            return getWage() * getHours();
        else
            return 40 * getWage() + (getHours() - 40) * getWage() * 1.5f;
    }
    // String representation of object
    @Override
    public String toString(){
        return String.format("hourly employee: %s\n%s: $%,.2f; %s: %,.2f",
                super.toString(), "hourly wage", getWage(),
                "hours worked", getHours());
    }
}

PayrollSystemTest.java

/*
 *       Filename:  PayrollSystemTest.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
 *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
import java.util.Calendar;

public class PayrollSystemTest{
    public static void main(String[] args){
        int currentMonth = 1 + Calendar.getInstance().get(Calendar.MONTH);

        // create four element Employee array
        Employee[] employees = new Employee[4];

        // initialise array with Employees
        employees[0] = new SalariedEmployee(
                "John", "Smith", "111-11-1111", 800.0f, 11, 3, 1883);
        employees[1] = new HourlyEmployee(
                "Karen", "Price", "222-22-2222", 16.75f, 40.0f, 12, 12, 1975);
        employees[2] = new CommissionEmployee(
                "Sue", "Jones", "333-33-3333", 10000.0f, .06f, 12, 13, 1965);
        employees[3] = new BasePlusCommissionEmployee(
                    "Bob", "Lewis", "444-44-4444", 5000.0f, .04f, 300.0f, 12, 12, 1956);

        System.out.println("Employees processed polymorphically:\n");

        for(Employee currentEmployee : employees){
            System.out.println(currentEmployee);

            // determine whether element is a BasePlusCommissionEmployee
            if(currentEmployee instanceof BasePlusCommissionEmployee){
                // downcase Employee reference to
                // BasePlusCommissionEmployee reference
                BasePlusCommissionEmployee employee =
                    (BasePlusCommissionEmployee) currentEmployee;

                employee.setBaseSalary(1.10f * employee.getBaseSalary());

                System.out.printf("new base salary with 10%% increase is: $%,.2f\n",
                        employee.getBaseSalary());


            }

            // add $100.0 if birth month is current
            System.out.printf("earned $%,.2f\n\n",
                    (currentEmployee.getBirthday().getMonth() == currentMonth) ?
                    currentEmployee.earnings() + 100.0f : currentEmployee.earnings());
        }

        // get type name of each object in employee array
        for(int j=0; j<employees.length; j++){
            System.out.printf("Employee %d is a %s\n",
                    j, employees[j].getClass().getName());
        }
    }
}

SalariedEmployee.java

/*
 *       Filename:  SalariedEmployee.java
 *
 *    Description:  Exercise 10.8 - Payroll System Modification
 *
  *  @Author:  Bilal Tahir Khan Meo
 *  Website: https://codeblah.com
 *
 * =====================================================================================
 */
public class SalariedEmployee extends Employee{
    private double weeklySalary;

    // constructor
    public SalariedEmployee(String first, String last, String ssn, double salary,
            int month, int day, int year){
        // pass to Employee constructor
        super(first, last, ssn, month, day, year);

        setWeeklySalary(salary);
    }
    // SETTERS
    public void setWeeklySalary(double salary){
        if(salary >= 0.0f)
            this.weeklySalary = salary;
        else
            throw new IllegalArgumentException(
                    "Weekly salary must be >= 0.0f");
    }
    // GETTERS
    public double getWeeklySalary(){
        return this.weeklySalary;
    }
    // calculate earnings; override abstract method earnings in Employee
    @Override
    public double earnings(){
        return getWeeklySalary();
    }
    // return String representation of SalriedEmployee object
    @Override
    public String toString(){
        return String.format("salaried employee: %s\n%s: $%,.2f",
                super.toString(), "weekly salary", getWeeklySalary());
    }
}