Question

It might seem like a stupid question to you guys, but I'm a java noob and still trying to grasp the whole concept. So, I basically have a simple theatre management system that allows me to add groups to the database. To each group, you can add students that each have a unique student ID and a name. You can also add rehearsal dates to a group. Both of these are stored in separate linked lists. This is my rehearsal object:

public Rehearsal(int d, int m, int y) {
    day = d;
    month = m;
    year = y;
}

This is the addRehearsal method in the group class:

public void addRehearsal(int d, int m, int y) {
    Rehearsal newrehearsal = new Rehearsal(d, m, y);
    if (!RehearsalDates.contains(newrehearsal)) {
        RehearsalDates.add(newrehearsal);
    }
    else
        JOptionPane.showMessageDialog(null, "Rehearsal already exists for this group!", "Error", JOptionPane.WARNING_MESSAGE);
}

My question is, how and where can I restrict what values can be entered. That means, that the program gives an error in the form of a message dialog if the value entered for int d > 31 or int m > 12. This is not really necessary for the year, as the user is allowed to create rehearsal dates for the past as well as the future.

Thanks for your help guys :)

Was it helpful?

Solution

Validating dates is more complex than checking each parameter. For example, calling it with (29, 2, 2000) would be invalid (recall that 2000 was not a leap year), even though all parameters are "within range".

The only sane way to check is to attempt to parse a Date from the parameters and catch the exception. There are a couple of ways to do this, but the simplest is this:

public Rehearsal(int d, int m, int y) {
    try {
        sdf = new SimpleDateFormat("d-M-yyyy");
        sdf.setLenient(false);
        sdf.parse(d + "-" + m + "-" + y);
    } catch (ParseException e) {
        // the parameters are not valid
    }
    // rest of code
}

Note the call to setLenient(), which is required, otherwise invalid input "rolls over" to the next available valid date - for example 36-12-2012 would be parsed as 05-01-2013.

The best place to put this code would be in the constructor, throwing an exception:

public Rehearsal(int d, int m, int y) {
    try {
        sdf = new SimpleDateFormat("d-M-yyyy");
        sdf.setLenient(false);
        sdf.parse(d + "-" + m + "-" + y);
    } catch (ParseException e) {
        // the parameters are not valid
        throw new IllegalArgumentException();
    }
    day = d;
    month = m;
    year = y;
}

And you would catch this wherever it is called.

Rehearsal newrehearsal;
try {
    newrehearsal = new Rehearsal(1, 2, 3);            
} catch (IllegalArgumentException ex) {
    JOptionPane.showMessageDialog(null, "Invalid date input!", "Error", JOptionPane.WARNING_MESSAGE);
    return;
}
// rest of method

An even better design would be to pass a Date object, putting the onus on the caller to validate input, and there would be less throw and catch code.

OTHER TIPS

Why not throw an IllegalArgumentException from the constructor of Rehearsal and then catch it in the addRehearsal method:

public Rehearsal(int d, int m, int y) {
    if (d < 1 || d > 31) {
        throw new IllegalArgumentException("Invalid day");
    }
    if (m < 1 || m > 12) {
        throw new IllegalArgumentException("Invalid month");
    }
    day = d;
    month = m;
    year = y;
}

And in the addRehearsal method catch the exception on construction:

Rehearsal newrehearsal;
try {
    newrehearsal = new Rehearsal(1, 2, 3);            
} catch (IllegalArgumentException ex) {
    JOptionPane.showMessageDialog(null, "Invalid date input!", "Error", JOptionPane.WARNING_MESSAGE);
    return;
}

That should be an intermediate solution - it will certainly prevent the creation of invalid dates.

You may then want to later add listeners on your inputs to prevent the invalid data in the first place.

Finally, you may want to consider using a Calendar rather than a custom date object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top