0

Having successfully created a policy holder and writing the information to csv I try to run the program again using a do while loop but receive an inputmismatchexception after typing surname.

Can someone point me in the right direction or advise what I am doing wrong with this piece of code?

Here is example of what happens... console

/**
 * 
 */
package InsurancePolicySystem;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * @author
 *
 */
public class InsurancePolicy {

    // create variables
    private String surname;
    private int age;
    private String motorType;
    private String motorPolicyId;
    private String addAnother;
    private String pattern = "^[a-zA-Z](\\s?[a-zA-Z]){2,29}$";

    // import scanner for user input
    Scanner scanner = new Scanner(System.in);

    // time stamp number. -1 used on month as time stamp displays next year instead
    // of current year
    int year = Calendar.getInstance().get(Calendar.YEAR);
    int month = Calendar.getInstance().get(Calendar.MONTH) - 1;

    // sum of the year and month
    int timeStamp = year + month;

    /**
     * default constructor
     */
    public InsurancePolicy() {

    }

    /**
     * non default constructor
     * 
     * @param surname
     * @param age
     * @param motorType
     * @param motorPolicyId
     */
    public InsurancePolicy(String surname, int age, String motorType, String motorPolicyId) {
        this.surname = surname;
        this.age = age;
        this.motorType = motorType;
        this.motorPolicyId = motorPolicyId;

    }

    /**
     * 
     * @return
     */
    public String getSurname() {
        return surname;
    }

    /**
     * Surname should be more than 3 letters and not greater than 20. Anything more
     * will cause a not valid error!
     * 
     * @param surname
     * @throws IllegalArgumentException
     */
    public void setSurname(String surname) throws IllegalArgumentException {
        this.surname = surname;
    }

    /**
     * 
     * @return
     */
    public int getAge() {
        return age;
    }

    /**
     * Age must be between 18 & 50 Any other age will produce not eligible error!
     * 
     * @param age
     * @throws IllegalArgumentException
     */
    public void setAge(int age) throws IllegalArgumentException {
        if ((age >= 18) && (age <= 50)) {
            this.age = age;
        } else {
            throw new IllegalArgumentException("Not eligible for an insurance policy!");
        }
    }

    /**
     * 
     * @return
     */
    public String getMotorType() {
        return motorType;
    }

    /**
     * motor type should only be either CAR, TAXI or BUS. if statement to prevent
     * other vehicle types and throw error if user inputs a different vehicle.
     * 
     * @param motorType
     * @throws IllegalArgumentException
     */
    public void setMotorType(String motorType) throws IllegalArgumentException {
        if (motorType.equals("CAR") || motorType.equals("TAXI") || motorType.equals("BUS")) {
            this.motorType = motorType;
        } else {
            throw new IllegalArgumentException("Not eligible for an insurance policy!");
        }
        this.motorType = motorType;

    }

    /**
     * 
     * @return
     */
    public String getMotorPolicyId() {
        return motorPolicyId;
    }

    /**
     * 
     * @param motorPolicyId
     */
    public void setMotorPolicyId(String motorPolicyId) {
        this.motorPolicyId = motorPolicyId;
    }

    /**
     * Method to write policy holder particulars to a csv file. Creates ArrayList
     * and uses collect joining to add comma for file.
     * 
     * @throws IOException
     */
    public void writeToFile() throws IOException {
        BufferedWriter writer = new BufferedWriter(
                new FileWriter("/Users/johnj/eclipse-workspace/InsuranceProject/insurance.csv", true));

        // creates policy holder (insurance) array
        ArrayList<String> insurance = new ArrayList<String>();
        insurance.add(surname);
        insurance.add(Integer.toString(age));
        insurance.add(motorType);
        insurance.add(motorPolicyId);

        // write array to csv file
        String collect = insurance.stream().collect(Collectors.joining(", "));
        System.out.println(collect);
        writer.write(collect);
        writer.newLine();
        writer.flush();
        writer.close();
    }

    /**
     * Builds and generates user input. Will then add it into an array list and
     * append to writeToFile(). Included do while loop for user to continue creating
     * policy profiles without having to re run program.
     * 
     * @param motorType
     */
    public void addPolicyHolder() throws IOException {

        try {

            do {

                // enter policy holder surname. Checks pattern to ensure compliance
                System.out.println("Please type your surname...");
                surname = scanner.next(pattern).toUpperCase().trim();
                setSurname(this.surname);

                // user input age
                System.out.println("Please type your age...");
                age = scanner.nextInt();
                setAge(this.age);

                // user input motor type which is converted to upper case
                System.out.println("Please type your motor type i.e. CAR, TAXI or BUS...");
                motorType = scanner.next().toUpperCase().trim();
                setMotorType(this.motorType);

                System.out.println(); // used to create next line space

                // Motor Policy Id should be 3 characters from surname as well as time stamp. If
                // time stamp odd number add 1 or else add 0 if even.
                motorPolicyId = surname.substring(0, 3) + timeStamp;
                if (timeStamp % 2 == 0) {
                    motorPolicyId = this.motorPolicyId + 0;
                } else {
                    motorPolicyId = this.motorPolicyId + 1;
                }

                // creates csv file
                writeToFile();

                // prints completed user input of policy holder
                System.out.println();
                System.out.println("Surname      :" + this.surname);
                System.out.println("Age          :" + this.age);
                System.out.println("Policy Ref   :" + this.motorPolicyId);
                System.out.println("Motor Type:  :" + this.motorType);

                System.out.println(); // used to create next line space

                // asks user if they would like to create a different policy holder
                System.out.println("Add another Policy Holder (Y or N)..");
                addAnother = scanner.next();
            } while (addAnother.equalsIgnoreCase("Y")); // If N program ends.
        } catch (Exception exception) { // if exception program ends
            System.out.println(
                    "There is a problem ... Policy Holder does meet necessary criteria, run the program again.");
        } finally {
            scanner.close();
            System.out.println("Program ended!"); // end of program
        }

    }

public static void main(String[] args) throws IOException {

        InsurancePolicy insurancePolicy = new InsurancePolicy();
        insurancePolicy.addPolicyHolder();

    }

}

I am able to complete a first run but do while loop fails when trying to add another policy holder.

  • 1
    What was the value you provided? Since you are using `next(pattern)` are you sure it matches `String pattern = "^[a-zA-Z](\\s?[a-zA-Z]){2,29}$";`? – Pshemo Feb 09 '23 at 18:11
  • 1
    Also note that `next` can only read values until *delimiter* of Scanner, which by default is set to *one or more whitespace*. This is why `next` can (by default) only return single words which don't contain whitespaces, so pattern which matches those words will never match `\\s`. – Pshemo Feb 09 '23 at 18:15
  • Yes, following same criteria. Here is example of what happens... Please type your surname... Smith Please type your age... 22 Please type your motor type i.e. CAR, TAXI or BUS... car SMITH, 22, CAR, SMI20231 Surname :SMITH Age :22 Policy Ref :SMI20231 Motor Type: :CAR Add another Policy Holder (Y or N).. y Please type your surname... jones There is a problem ... Policy Holder does meet necessary criteria, run the program again. Program ended! – donkey_junior Feb 09 '23 at 18:16
  • Please use [edit] option and add that to your question instead of comment (lets not force other people who may want to help you to look for necessary information all over the comments section). – Pshemo Feb 09 '23 at 18:18
  • 1
    "*..I try to run the program again using a do while loop but receive an inputmismatchexception after typing surname.*" your console example doesn't let us see that problem. To get better help please consider reducing your example to [SSCCE](http://sscce.org) (a.k.a. [MCVE]) - in other words get rid of things which are not related to problem you are showing (this will also help you to narrow its cause which may lead you to solving it yourself). Also make it runnable/debuggable for us - maybe add to it `main` method which we could run and get exact error you are facing. – Pshemo Feb 09 '23 at 18:35
  • I half-suspect I know where the problem lies. Does it work after changing the line `addAnother = scanner.next();` to `addAnother = scanner.nextLine();`? – gparyani Feb 09 '23 at 19:02
  • no, it ignores the do while loop and instead goes to finally "Program ended!" – donkey_junior Feb 09 '23 at 19:08
  • 1
    Off-Topic: One poor practice in your code is printing a generic message when an exception is thrown: `(Exception exception) { System.out.println( "There is a problem ... Policy Holder does meet necessary criteria, run the program again.");`. In debugging, it helps to display the actual `exception.toString`. – Old Dog Programmer Feb 09 '23 at 19:11
  • 1
    Also, another good practice is to not depend on the exception throwing behavior of Scanner, and instead use the `hasNext...` methods (e.g., `hasNext`, `hasNextInt`, etc.) which you can use in if statements to determine if the next input meets the criteria. – gparyani Feb 09 '23 at 19:21
  • Remove `^` from your regex, as it indicates *start of data* which for first surname is valid (as it is provided at beginning of input stream) but after that `^` will *prevent* pattern from matching other surnames since they are no longer at "*start of stream*". You can also remove `$` and `\s` since it doesn't add anything here. In other words you can reduce your `pattern` to `private String pattern = "[a-zA-Z][a-zA-Z]{2,29}";` – Pshemo Feb 09 '23 at 19:21
  • Thanks everyone for your help. Thank you Pshemo for identifying the problem. Much appreciated. – donkey_junior Feb 09 '23 at 19:27
  • You are welcome. BTW `private String pattern = "[a-zA-Z][a-zA-Z]{2,29}";` can be farther simplified to `private String pattern = "[a-zA-Z]{3,30}";` – Pshemo Feb 09 '23 at 19:33

0 Answers0