The MVC Controller (dcops Package)

The dcops package contains two classes that perform the date difference calculations, and the EventCalendar class to manage Event objects.  It also contains EventListManager that acts as the intermediary between the UI and the data store that maintains Event List information.

EventCalendar Class

I created the EventCalendar class as an extension of the GregorianCalendar class, which in turn extends the abstract Calendar class (both of the latter two classes are in the Java SE run-time library, rt.jar).  An Event is a named date/time.  For example, the Event “Assassination of John F. Kennedy” has the associated date “1963-11-23 16:00:00 GMT”.  (Also see Figure 7 for a sample of Events). EventCalendar provides data and methods to manage an Event name and calendar date/time.

I use EventCalendar objects to manage the data in the Start Calendar and Finish Calendar.

package dcops;
 
import java.util.GregorianCalendar;
 
/**
 * The EventCalendar class extends the Gregorian Calendar
 * java.util.GregorianCalendar to include event information
 * associated with a specific event name and associated date.
 *
 * @author Philip Nau
 */
public class EventCalendar extends GregorianCalendar {
    private int eventID;  
    private String eventName;
    private String eventDate;
 
    /**
     * Returns the ID of the event associated with an EventCalendar object.
     * @return the event ID.
     */
    public int getEventID() {
        return eventID;
    }
   
    /**
     * Sets the eventID field of an EventCalendar object.
     * @param id the ID of the Event.
     */
    public void setEventID(int id) {
        eventID = id;
    }
   
    /**
     * Returns the name of the event associated with an EventCalendar object.
     * @return the event name.
     */
    public String getEventName() {
        return eventName;
    }
   
    /**
     * Sets the eventName field of an EventCalendar object.
     * @param name the name of the Event.
     */
    public void setEventName(String name) {
        eventName = name;
    }
 
    /**
     * Returns the date of the event associated with an EventCalendar object.
     * @return the event date.
     */
    public String getEventDate() {
        return eventDate;
    }
 
    /**
     * Sets the eventDate field of an EventCalendar object.
     * @param date the Event date.
     */
    public void setEventDate(String date) {
        eventDate = date;
    }
}

Listing 14 – EventCalendar Class


EventListManager Class

EventListManager is a façade class for access to the data store that maintains one or more lists of Events.  It works via methods identified in the EventDataStoreServices interface (defined in the dcstore package).  The constructor reads an Event List into an ArrayList; the number of records in an Event data store is small, so I chose to load the entire file in memory. Methods are provided to read records from the Event List and append a record to the Event List.

package dcops;
 
import java.util.ArrayList;
import dcstore.EventDataStoreServices;
import dcstore.EventFileIO;
 
/**
 * The EventListManager class acts as the gateway between the UI
 * classes and the Event List data store (which could be a text file, spreadsheet,
 * database, etc), by maintaining the set of EventCalendar 
 * records as an ArrayList, and providing methods to read and
 * write individual EventCalendar records.
 * 
 * @author Philip Nau
 */
public class EventListManager {
    /**
     * Instance of ArrayList that maintains the set of EventCalendar
     * records in the data store.
     */
    private ArrayList eventList = new ArrayList();
    /**
     * Instance of EventDataStoreServices that provides access to
     * the data store.
     */
    private EventDataStoreServices eventListAccess = new EventFileIO();
   
    /**
     * Constructor.  Calls the superclass.  Reads the set of Event records 
     * if necessary.
     */
    public EventListManager() {
        super();
        if (eventList.isEmpty()) {
            readEventRecords();
        }
    }
   
    /**
     * Reads records from the data store to the eventList ArrayList.
     * Each record is converted to an EventCalendar object, which includes the 
     * Gregorian Calendar associated with the event date, as well as String
     * representations of the event name and event date.
     * @return the list of events from the event source.
     */
    public ArrayList readEventRecords() {
        if (eventList.isEmpty()) {
            eventList = eventListAccess.readEventRecords();
        }
        return eventList;
    }
   
    /**
     * Returns the populated event list based on the contents of the data store.
     * @return the event list.
     */
    public ArrayList getEventList() {
        return eventList;
    }
 
    /**
     * Retrieves the selected event record from the eventList.
     * @param selectedRecord the record number of the record in the Event list.
     * @return the selected event record in the form of EventCalendar
     */   
    public EventCalendar retrieveEventRecord(int selectedRecord) {
        if (selectedRecord >=0 && selectedRecord < eventListAccess.getEventListLength())
            return eventList.get(selectedRecord);
        else
            return null;
    }
   
    /**
     * Appends a specified EventCalendar record to the eventList.
     * @param ec the EventCalendar instance to add to the Event list.
     * @return the result of the write operation. 
     */   
    public String appendEventRecord(EventCalendar ec) {
        return eventListAccess.writeEventRecord(ec);
    }
} 

Listing 15 – EventListManager Class

CalendarOps Class

CalendarOps contains a number of methods to perform calculations on the Start Calendar and Finish Calendar, and to provide access (through getter methods) to data in these objects.

This class defines an enum to handle separate START and FINISH cases, and declares the StartCalendar and FinishCalendar objects.  The class methods (all static) are straightforward Java code to process data in these two objects.

package dcops;
 
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
 
/**
 * The CalendarOps class performs calculations on
 * startCalendar and finishCalendar, the two instances of
 * EventCalendar that maintain the user-selected dates for
 * the Event Date Difference Calculator.
 *

 

 * This class also provides a number of public getter methods for access to
 * specific date information by the user interface classes. This class has been
 * implemented with all public methods declared static.
 *
 * @author Philip Nau
 *      TODO: Add leap-seconds to calculations.
 *      TODO: Need more accurate Months calculation algorithm.
 */
public class CalendarOps {
    /**
     * Defines the Calendar Event types (note public declaration for use by
     * the UI classes).
     */
    public enum CalendarType {START, FINISH};
    /**
     * Defines the Start Calendar instance (extends GregorianCalendar).
     */
    private static EventCalendar startCalendar = new EventCalendar();
    /**
     * Defines the Finish Calendar instance (extends GregorianCalendar).
     */   
    private static EventCalendar finishCalendar = new EventCalendar();

Listing 16 – CalendarOps Class Header

CutoverOps Class

CutoverOps is a small class with ‘hardcoded’ declarations for the Julian-Gregorian cut-over date.  This class can be expanded to more rigorously handle cut-over dates based upon the location when the Gregorian calendar was adopted, but that requires establishing geo-location data beyond the current scope of this project.

package dcops;
/**
 * The CutoverOps class handles the cutover or transition between the 
 * Julian Calendar and the Gregorian Calendar.  Due to the
 * accumulating difference between the Julian Calendar date and the actual
 * date as determined by observation, eleven days were skipped at the start
 * of the Gregorian Calendar implementation. The default date
 * for the cutover is October 15, 1582 (Oct 4, 1582 was followed immediately
 * by Oct 15, 1582).
 *
 * @author Philip Nau
 *      TODO: Add user-entered Cutover Date capability.
 */
public class CutoverOps {
   
    private static int cutoverYear = 1582;
    private static int cutoverMonth = 9; // Jan=0; Oct=9
    private static int cutoverStartDay = 5;
    private static int cutoverEndDay = 14;
    private static int lastJulianDay = cutoverStartDay - 1;
    private static int firstGregorianDay = cutoverEndDay + 1;
 
    /**
     * @return the value of the cutover year.
     */   
    public static int getCutoverYear() {
        return cutoverYear;
    }
   
    /**
     * @return the value of the cutover month.
     */   
    public static int getCutoverMonth() {
        return cutoverMonth;
    }
   
    /**
     * @return the value of the cutover start day.
     */   
    public static int getCutoverStartDay() {
        return cutoverStartDay;
    }
   
    /**
     * @return the value of the cutover end day.
     */   
    public static int getCutoverEndDay() {
        return cutoverEndDay;
    }
   
    /**
     * @return the value of the last Julian Calendar Day.
     */   
    public static int getLastJulianDay() {
        return lastJulianDay;
    }
   
    /**
     * @return the value of the first Gregorian Calendar day.
     */   
    public static int getFirstGregorianDay() {
        return firstGregorianDay;
    }
   
    /**
     * Checks if the input date (year, month, day) falls between the
     * Julian/Gregorian cutover, and is therefore not a "real" date.
     * @param year four-digit year
     * @param month month number (0-11)
     * @param day day of month (1-31)
     * @return true if so, false if not.
     */
    public static boolean isDuringCutover(int year, int month, int day) {
        if (year != cutoverYear) return false;
        if (month != cutoverMonth) return false;
        if (day >= cutoverStartDay && day 
        return false;
    }
   
    /**
     * Checks if the StartCalendar date is before the Gregorian
     * cutover date and the FinishCalendar date is after the
     * Gregorian cutover date.
     * @param startCalendar startCalendar instance
     * @param finishCalendar finishCalendar instance
     * @return true if so, false if not.
     */
    public static boolean datesCrossCutover(EventCalendar startCalendar, EventCalendar finishCalendar) {
        EventCalendar tc = new EventCalendar();
        tc.clear();
        // Force cutover date to Oct 15, 1582. (Note - month integers are
        // indexed to zero, so 1 is subtracted from cutoverMonth).
        tc.set(cutoverYear, cutoverMonth, firstGregorianDay); 
        boolean startsBeforeCutoverDate = startCalendar.before(tc);
        boolean finishesAfterCutoverDate = finishCalendar.after(tc);
 
        if(startsBeforeCutoverDate && finishesAfterCutoverDate)
            return true;
        else
            return false;
    }
}

Listing 17 – CutoverOps Class