Tuesday, June 16, 2009

Custom String Values for an Enum in Java

The default String value that Java returns for an enum is the actual name of the enum constant in use. For example given the following enum:

public enum DayOfWeek {

MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

}
This simple program:
public class DayOfWeekTest {

public static void main(String[] args) {
DayOfWeek dow = DayOfWeek.MONDAY;
System.out.println(dow.toString());
}
}
Will return:
$ java DayOfWeekTest
MONDAY
But in the program above what I really want is an abbreviated version of the week day in Title Case; For example Mon. Now I could override the toString method of the enum class as follows:
public enum DayOfWeek {

MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

public String toString() {
String dayOfWeek = name().toString();
dayOfWeek = dayOfWeek.charAt(0) + dayOfWeek.substring(1,3).toLowerCase();
return dayOfWeek;
}
}
Which does meet my needs, but it’s not the most obvious or readable piece of code. What Java allows you to do is provide a constructor for the enumeration as follows:
public enum DayOfWeek {

MONDAY("Mon"), TUESDAY("Tue"), WEDNESDAY("Wed"), THURSDAY("Thu"), FRIDAY("Fri"), SATURDAY("Sat"), SUNDAY("Sun");

private String dayOfWeek;

private DayOfWeek(String dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}

public String toString() {
return this.dayOfWeek;
}
}
Which I think we can all agree is a far simpler piece of code.

Now to make this enum really useful we should provide a method to convert a String back to an enum. If we simply used the supplied valueOf method in the DayOfWeekTest as follows:
public class DayOfWeekTest {

public static void main(String[] args) {
DayOfWeek mon = DayOfWeek.MONDAY;
System.out.println(mon.toString());
DayOfWeek tue = DayOfWeek.valueOf("Tue");
System.out.println(tue.toString());
}
}
A java.lang.IllegalArgumentException: No enum const class DayOfWeek.Tue is thrown as the valueOf method expects the full name of the enum constant; For example TUESDAY. A new method is needed, therefore out final enum becomes:
public enum DayOfWeek {

MONDAY("Mon"), TUESDAY("Tue"), WEDNESDAY("Wed"), THURSDAY("Thu"), FRIDAY("Fri"), SATURDAY("Sat"), SUNDAY("Sun");

private String dayOfWeek;

private DayOfWeek(String dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}

public String toString() {
return this.dayOfWeek;
}

public static DayOfWeek getValue(String dayOfWeek) {
for (DayOfWeek dow : DayOfWeek.values()) {
// Use equalsIgnoreCase to make the getValue method a little more robust
if (dow.toString().equalsIgnoreCase(dayOfWeek)) {
return dow;
}
}
return null;
}
}

We then change the valueOf method in the DayOfWeekTest to the getValue method as follows:
public class DayOfWeekTest {

public static void main(String[] args) {
DayOfWeek mon = DayOfWeek.MONDAY;
System.out.println(mon.toString());
DayOfWeek tue = DayOfWeek.getValue("Tue");
System.out.println(tue.toString());
}
}
Run the program and Voila!
$ java DayOfWeekTest
Mon
Tue

Wednesday, June 10, 2009

Mimicing "break" in a PL/SQL FOR Loop

It seems a major omission in the Oracle PL/SQL Programming language that the BREAK keyword cannot be used in FOR loops (or WHILE loops) to skip to the next iteration.

Here is a (trivial) example of how you can implement "break" functionality using exceptions:
DECLARE
e_skip_row EXCEPTION;
l_total PLS_INTEGER := 0;
BEGIN
--
dbms_output.enable(10000);
--
FOR l_index IN 1..100 LOOP
BEGIN
--
-- If the row is even then skip
IF MOD(l_index,2) = 0 THEN
RAISE e_skip_row;
END IF;
--
l_total := l_total + l_index;
--
EXCEPTION
WHEN e_skip_row THEN NULL;
END;
END LOOP;
--
dbms_output.put_line('Total is: '||l_total);
--
END;