Whenever I find myself doing Graphical User Interface based code, I find I need to validate text fields that should fit specific formats. Ideally, I would develop a template based field that would validate the string against a regular expression (RE) as part of the constructor. Since Java now has REs and templates as part of the language, and C++ has a great RE facility in Boost, both of these languages should support this. nimbus cloud There are several types I’ve come across that would fit this category. Note that my Regex syntax is a little bastardized. I use the [] to indicate selecte one of values inside and () to indicate a grouping.
Digit: [0-9]. I’ll call this D.
Hex digit: [0-9a-fA-F]. I’ll call this one X since I’ll use it below.
Social security number DDD-DD-DDDD
IP address: D?D?D.D?D?D.D?D?D.D?D?D
MAC Address:XX:XX:XX:XX:XX
ZIP code: DDDDD(-DDDD)?
Phone Number. THis one get’s tricky. Should you allow parenthesis for the Area code? If you do, it gets harder to write as a regex. You have to do something like: (\(DDD\))|(DDD)-DDD-DDDD. If you make the Area code optional, it gets even more complicated.
Even more complicated is the regex for email addresses.
The interesting design decision here is how to implement. Basically, you want a type that takes a regex as a template parameter, or something that can be converted into a regex. Here is a simple example in C++:
template < char * re> class MyType {
static char * mystring;
};
char s1[] = "ABC";
char s2[] = "123";
int main(){
MyType<s1> s1type;
MyType<s2> s2type;
return 0;
}
The interesting thing about this is that the template is really only making two types based on the value of the pointer, not the value of the String field. This is not really any different than using an integer value. You would really want to use a typedef for this. That means that your Regex needs to be a single global instance of your regex class. My Java template Kung-Fu is not so strong; I can’t provide a comparable example for Java.
Since you may be validating a large volume of Data, you don’t want to throw exceptions. Ordinarily, I think exceptions would be correct, but there is some argument to be made that invalid data is part of normal processing. This is an ideal use of a policy that should be selected by the user.
This means you probably want to use a factory to create the container. The factory can then determine wheather to return null, return a null object, or throw an exception if the string fails the parsing.
Regardless of your error handling scheme, you are going to end up with a lot of code like this:
template <class T>
…
try{
T t = T.factory(str)
}catch(invalid_format& i){
errorCollection.push_back(fieldName, errorMessage);
}
Usually something like this can be wrapped in a loop which is processed on form validation.