package com.pugh.sockso.web; import com.pugh.sockso.resources.Locale; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.List; /** * Encapsulates validating some data that has been submitted * */ public class Submission { public static final int FIELD_TEXT = 1; public static final int FIELD_EMAIL = 2; public static final int FIELD_DATE = 3; public static final int FIELD_INTEGER = 4; private final List<String> errors; private final Request req; private final Locale locale; public Submission( final Request req, final Locale locale ) { this.req = req; this.locale = locale; this.errors = new ArrayList<String>(); } /** * adds a field to be validated (field assumed to be required) * * @param name * @param type * */ public void addField( final String name, final int type ) { addField( name, type, true, "" ); } /** * adds a field to be validated (using locale key for error) * * @param name * @param type * @param localeKey * */ public void addField( final String name, final int type, final String localeKey ) { addField( name, type, true, localeKey ); } /** * adds a field to be validated * * @param name * @param type * @param isRequired * */ public void addField( final String name, final int type, final boolean isRequired ) { addField( name, type, isRequired, "" ); } /** * adds a field to be validated (error message will use locale text) * * @param name * @param type * @param isRequired * @param localeKey * */ public void addField( final String name, final int type, final boolean isRequired, final String localeKey ) { final String value = req.getArgument( name ); // check for missing required fields if ( value.equals("") && isRequired ) { addError( "required field missing", localeKey ); } // before we check the format of the field, if it's blank // and not required then it's fine, so make sure we have something. else if ( isRequired && !value.equals("") ) { switch ( type ) { case FIELD_EMAIL: if ( !isValidEmail(value) ) { addError( "invalid email", localeKey ); } break; case FIELD_INTEGER: if ( !isValidInteger(value) ) { addError( "invalid integer", localeKey ); } break; case FIELD_DATE: if ( !isValidDate(value) ) { addError( "invalid date", localeKey ); } break; case FIELD_TEXT: // any kind of text is valid break; default: addError( "unknown field type (dev error?)", localeKey ); } } } /** * Adds a check that two fields match * * @param field1 * @param field2 * @param localeKey * */ public void addMatchingFields( final String field1, final String field2, final String localeKey ) { final String value1 = req.getArgument( field1 ); final String value2 = req.getArgument( field2 ); if ( !value1.equals(value2) ) { addError( "fields dont match", localeKey ); } } /** * checks if this submission is valid, and if not throws an exception * * @throws BadRequestException * */ public void validate() throws BadRequestException { if ( !isValid() ) throw new BadRequestException( getErrors() ); } /** * adds an error message using the locale text if it's specified, or just * using the normal message otherwise * * @param message * @param localeKey * */ public void addError( final String message, final String localeKey ) { errors.add( localeKey.equals("") ? message : locale.getString(localeKey) ); } /** * returns the errors * * @return * */ public String[] getErrors() { return errors.toArray( new String[] {} ); } /** * checks if a string seems to be a valid date * * @param value * * @return * */ private boolean isValidDate( final String value ) { try { DateFormat df = DateFormat.getDateInstance( DateFormat.SHORT ); df.setLenient( true ); df.parse(value); } catch ( final ParseException e ) { return false; } catch ( final IllegalArgumentException e ) { return false; } return true; } /** * checks if a value is a valid integer * * @param integer * * @return * */ private boolean isValidInteger( final String integer ) { try { Integer.parseInt( integer ); return true; } catch ( final NumberFormatException e ) { return false; } } /** * checks if the value is a valid email * * @param email * * @return * */ private boolean isValidEmail( final String email ) { final String pattern = "^[a-zA-Z][\\w\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$"; return email.matches( pattern ); } /** * determines if the submission is valid. returns a boolean. * * @return boolean * */ public boolean isValid() { return errors.isEmpty(); } }