Payroll-Exceptions01, continued - Exercise

Contact Us or call 1-877-932-8228
Payroll-Exceptions01, continued - Exercise

Payroll-Exceptions01, continued

Duration: 15 to 20 minutes.
  1. Go ahead and add a second version of each get numeric method in KeyboardReader that accepts an error message string as a second parameter; have it loop on each numeric input request until it succeeds without throwing the exception (and printing the error message each time the exception occurs).
  2. Then modify Payroll to call these methods.

Challenge

This approach still doesn't solve the problem of limited employee types, valid department numbers, etc. Can you think of an approach that would? (Hint: interfaces are a powerful tool ...).

Solution:

Solutions/Payroll-Exceptions01/util/KeyboardReader.java
package util;
import java.io.*;

public class KeyboardReader {


---- C O D E   O M I T T E D ----
  public static int getPromptedInt(String prompt, String errMsg) {
    for ( ; ; ) {
      try {
    		return Integer.parseInt(getPromptedString(prompt));
      } catch (NumberFormatException nfe) {
        System.out.println(errMsg);
      }
    }
  }
  
  public static float getPromptedFloat(String prompt, String errMsg) {
    for( ; ; ) {
      try {
        return Float.parseFloat(getPromptedString(prompt));
      } catch (NumberFormatException nfe) {
        System.out.println(errMsg);
      }
    }
  }

  public static double getPromptedDouble(String prompt, String errMsg) {
    for( ; ; ) {
      try {
        return Double.parseDouble(getPromptedString(prompt));
      } catch (NumberFormatException nfe) {
        System.out.println(errMsg);
      }
    }
  }
}

Solution:

Solutions/Payroll-Exceptions01/Payroll.java
import employees.*;
import vendors.*;
import finance.*;
import util.*;

public class Payroll {  
  public static void main(String[] args) {
    Employee[] e = new Employee[5];
    String fName = null;
    String lName = null;
    int dept = 0;
    double payRate = 0.0;
    double hours = 0.0;

    for (int i = 0; i < e.length; i++) {
      char type = KeyboardReader.getPromptedChar(
          "Enter type: E, N, or C: ");
      if (type != 'e' && type != 'E' && 
          type != 'n' && type != 'N' && 
          type != 'c' && type != 'C') {
        System.out.println("Please enter a valid type");
        i--;
        continue;        
      }
      fName = KeyboardReader.getPromptedString("Enter first name: ");
      lName = KeyboardReader.getPromptedString("Enter last name: ");
      dept = KeyboardReader.getPromptedInt(
          "Enter department: ", "Department must be numeric");
      do {
        payRate = KeyboardReader.getPromptedDouble(
            "Enter pay rate: ", "Pay rate must be numeric");
        if (payRate < 0.0) System.out.println("Pay rate must be >= 0");
      } while (payRate < 0.0);

      switch (type) {
        case 'e':
        case 'E': e[i] = new ExemptEmployee(fName, lName, dept, payRate);
                  break;
        case 'n':
        case 'N': do {
                    hours = KeyboardReader.getPromptedDouble(
                        "Enter hours: ", "Hours must be numeric");
                    if (hours < 0.0) 
                      System.out.println("Hours must be >= 0");
                  } while (hours < 0.0);
                  e[i] = new NonexemptEmployee(
                      fName, lName, dept, payRate, hours);
                  break;
        case 'c':
        case 'C': do {
                    hours = KeyboardReader.getPromptedDouble(
                        "Enter hours: ", "Hours must be numeric");
                    if (hours < 0.0) 
                      System.out.println("Hours must be >= 0");
                  } while (hours < 0.0);
                  e[i] = new ContractEmployee(
                      fName, lName, dept, payRate, hours);
      }

      System.out.println(e[i].getPayInfo());
    }

---- C O D E   O M I T T E D ----
  }

}

The revised code uses the new overloads of the getPromptedXXX methods.

Challenge Solution:

Solutions/Payroll-Exceptions01-challenge/util/IntValidator.java
package util;

public interface IntValidator {
	public boolean accept(int candidate);
}

This interface specifies a method that will be used to validate integers. A validator for a specific field (like department) would implement this with code to test for legal values for that field. The package contains similar interfaces for floats and doubles.

Challenge Solution:

Solutions/Payroll-Exceptions01-challenge/employees/DeptValidator.java
package employees;
import util.IntValidator;

public class DeptValidator implements IntValidator {

	@Override
	public boolean accept(int dept) {
		return dept > 0 && dept <= 5;
	}

}
/* Sample usage in Payroll

dept = KeyboardReader.getPromptedInt(
"Enter department: ", "Dept must be numeric",
new DeptValidator(), "Valid depts are 1 - 5");

*/

This class validates department numbers to be from 1 - 5 inclusive. We also could create separate validators for pay rates, etc.

Challenge Solution:

Solutions/Payroll-Exceptions01-challenge/util/KeyboardReader.java
package util;
import java.io.*;

public class KeyboardReader {


---- C O D E   O M I T T E D ----
	public static int getPromptedInt(String prompt) {
		return Integer.parseInt(getPromptedString(prompt));
	}
	
	public static int getPromptedInt(String prompt, String errMsg) {
		for ( ; ; ) {
			try {
				return Integer.parseInt(getPromptedString(prompt));
			} catch (NumberFormatException e) {
				System.out.println(errMsg);
			}
		}
	}
	public static int getPromptedInt(
			String prompt, String formatErrMsg, 
			IntValidator val, String valErrMsg) {
		for ( ; ; ) {
			try {
				int num = Integer.parseInt(getPromptedString(prompt));
				if (val.accept(num)) return num;
				else System.out.println(valErrMsg);
			} catch (NumberFormatException e) {
				System.out.println(formatErrMsg);
			}
		}
	}
	
	public static float getPromptedFloat(String prompt) {
		return Float.parseFloat(getPromptedString(prompt));
	}
	public static float getPromptedFloat(String prompt, String errMsg) {
		for ( ; ; ) {
			try {
				return Float.parseFloat(getPromptedString(prompt));
			} catch (NumberFormatException e) {
				System.out.println(errMsg);
			}
		}
	}
	public static float getPromptedFloat(
			String prompt, String formatErrMsg, 
			FloatValidator val, String valErrMsg) {
		for ( ; ; ) {
			try {
				float num = Float.parseFloat(getPromptedString(prompt));
				if (val.accept(num)) return num;
				else System.out.println(valErrMsg);
			} catch (NumberFormatException e) {
				System.out.println(formatErrMsg);
			}
		}
	}

	public static double getPromptedDouble(String prompt) {
		return Double.parseDouble(getPromptedString(prompt));
	}
	public static double getPromptedDouble(String prompt, String errMsg) {
		for ( ; ; ) {
			try {
				return Double.parseDouble(getPromptedString(prompt));
			} catch (NumberFormatException e) {
				System.out.println(errMsg);
			}
		}
	}
	public static double getPromptedDouble(
			String prompt, String formatErrMsg, 
			DoubleValidator val, String valErrMsg) {
		for ( ; ; ) {
			try {
				double num = Double.parseDouble(getPromptedString(prompt));
				if (val.accept(num)) return num;
				else System.out.println(valErrMsg);
			} catch (NumberFormatException e) {
				System.out.println(formatErrMsg);
			}
		}
	}
}
Next