The one class that you may want to use here that will give you grief is DateDate(String)DateDateCalendarDateStringDateFormatCalendarDateDate
Listing Two
package com.holub.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* A {@link Date} with a non-deprecated {@link String} constructor. Use
* {@code new DateTime(DateTime.NOW)} to create a `DateTime` that represents the
* time that the object is created. This class is intended be used by configuration
* enum that's wrapping a {@link Configurations} object, so the
* constructor throws a {@link ConfigurationError} if it fails.
*
* @author Allen Holub
*
* <div style='font-size:8pt; margin-top:.25in;'>
* ©2012 <!--copyright 2012--> Allen I Holub. All rights reserved.
* This code is licensed under a variant on the BSD license. View
* the complete text at <a href="http://holub.com/license.html">
* http://www.holub.com/license.html</a>.
* </div>
*/
public class CalendarDate extends java.util.Date
{
private static final long serialVersionUID = 1L; // Required because Date is serializable
private static final ExtendedLogger log = ExtendedLogger.getLogger(CalendarDate.class);
/** Pass to the constructor to create a date representing the moment
* the object was created.
*/
public static final String NOW = "now";
/** Create a date using {@link SimpleDateFormat#parse(String)}. The only
* recognized date format is yyyy-MM-dd
*
* @param initialValue
* @throws ConfigurationError
*/
public CalendarDate( String initialValue ) throws ConfigurationError
{
try
{
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); // DateFormat.getDateInstance();
formatter.setLenient(true);
Date value = initialValue.equals( NOW )
? new Date()
: formatter.parse( initialValue );
setTime( value.getTime() );
}
catch (ParseException e)
{ throw new ConfigurationError
( log.error("Illegal initializer string for Date (%s):\n\t%s", initialValue, e.getMessage() )
);
}
}
}
More Insights
White Papers
More >>Reports
- Informed CIO: SDN and Server Virtualization on a Collision Course
- InformationWeek 2013 IT Spending Priorities Survey
Webcasts
More >>
Here's how I define a couple date keys in the enum
key_dateNow ( CalendarDate.class, CalendarDate.NOW, null),
key_dateThen( CalendarDate.class, "2001-07-04", null),
So far, the only load-time error checking we've performed is that the value in the
properties is acceptable to the field's Stringnullverifier, a class that implements
the Configurations.Verifier
public interface Verifier
{ public void verify(Object input) throws ConfigurationError;
}
VerifierConfigurationError
I provide two, out-of-the-box verifiers for handling the most-common scenarios. Here's how the first one is used:
intBound ( Integer.class, 2, new RangeVerifier(1, 3) ), // Defaults to 2. 1<=value<=3;
The RangeVerifierintBoundRangeVerifierjava.util.ComparableNumberComparableNumberStringDate
dateBound ( CalendarDate.class, "2001-07-04",
new RangeVerifier( new CalendarDate("2001-01-01"), new CalendarDate("2001-12-31")) ),
The phoneNumberRegExVerifier
phoneNumber ( String.class, "(510)555-1212", // must take the form: (ddd)ddd-dddd
new RegExVerifier("(\\(\\d\\d\\d\\))?\\s*\\d\\d\\d[-.]\\d\\d\\d\\d") ),
This verifier checks that the presented value matches the regular express specified in the constructor. Here, I'm checking for a standard US phone-number format, with parenthesis around the area code.
The verifiers are run on both the default version of the object (as specified in the enum
Moving on to more mundane details...
First, I have to get a pointer to the actual properties file. Because of the location-based configuration class that I showed you a couple months back, that's trivial to do. The code
public static final File INPUT_FILE = Places.CONFIG.file("test.properties");
(on line 53)
creates a Filetest.properties. That file must be in the directory specified by the
either by the CONFIG environment or the -DCONFIG=location command-line switch, or in the default
location ~/config as a last resort. The program terminates with a ConfigurationError
All the enumConfigurations.SupportenumSupportenum elements to be initialized (from either the file or a default value, as required) and verified (using the VerifierSupportstaticSupportload()
public static void load( boolean paramsWithDefaultNotRequiredInPropertiesFile, boolean allowUnusedKeys )
{ if( support == null )
support = new Configurations.Support<TestConfiguration>( values(), INPUT_FILE,
paramsWithDefaultNotRequiredInPropertiesFile, allowUnusedKeys );
}
The reset()SupportsupportnullConfigurations.Support
The enumenumSupportpublicSupport
I can't pass the element-specific information to the SupportenumSupport object is shared by all the elements.
The object happens to be created by whichever enumenumSupport object doesn't really work either.
(A push is usually preferable better than a pull because the dependencies are more tractable.)
The SupportenumSupportSupport object keep local copies of information that's
also stored in every enum element, and I'm reluctant to duplicate information unnecessarily. Duplicates are just
bugs waiting to happen if they get out of phase.
So, the only viable alternative seems to be accessors, and these accessors have to be declared in an
interface (ConfigurationsTestConfigurationenumenumfriendConfigurations.Support
The remainder of the methods are just one-liner wrappers that delegate to similarly
named Configuration.Support


