summaryrefslogtreecommitdiff
path: root/server/CalendarFormatParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'server/CalendarFormatParser.java')
-rw-r--r--server/CalendarFormatParser.java269
1 files changed, 269 insertions, 0 deletions
diff --git a/server/CalendarFormatParser.java b/server/CalendarFormatParser.java
new file mode 100644
index 0000000..4ef6fe5
--- /dev/null
+++ b/server/CalendarFormatParser.java
@@ -0,0 +1,269 @@
+/**
+ *
+ */
+package server;
+
+import java.util.*;
+import java.util.regex.*;
+import java.text.*;
+import java.io.*;
+
+import shared.*;
+
+/**
+ * This class is needed for parsing the original UNIX calendar database format.
+ * Its parsing the calendar database from the file-system and its caching it into the
+ * memory. Then, the CalendarDatabase class can be used to access the database.
+ * Each calendar category has its own file. In each file all the calendar events of the
+ * specific categories are stored.
+ * @author buetow
+ *
+ */
+public final class CalendarFormatParser {
+ private int iCurrentYear;
+ private Date dateCurrent;
+ private String sWorkdir;
+ private Vector vecCategories;
+ private static final Pattern datePattern;
+ private static final Pattern dateYearlyPattern;
+ private static final Pattern dateEndPattern;
+ // private static final Pattern emptyLine;
+ private static final String DATE_FORMAT = "M/d-y";
+ private static final String EXTENDED_DATE_FORMAT = "M/d-y-H:m";
+
+ // Those pattern will be used later, precompile here once to use often
+ static {
+ // Matches calendar date format like: "01/25 2006-14:23"
+ datePattern = Pattern.compile("\\d{2}/\\d{2}\t\\d{4}-\\d{2}:\\d{2}");
+
+ // Matches calendar date format like: "01/25 yearly-14:23"
+ dateYearlyPattern = Pattern.compile("\\d{2}/\\d{2}\tyearly-\\d{2}:\\d{2}");
+
+ // Matches the end of the date string like: "arly-14:23 " or "2006-14:23"
+ dateEndPattern = Pattern.compile(".{4}-\\d{2}:\\d{2}");
+ }
+
+ /**
+ * Simple constructor. Creates a calendar format parser object and initializes some private members.
+ */
+ public CalendarFormatParser() {
+ // Use current dir as workdir by default
+ this.sWorkdir = ".";
+ this.vecCategories = new Vector();
+
+ // Events without a year specified will use the current year!
+ GregorianCalendar cal = new GregorianCalendar();
+ iCurrentYear = cal.get(Calendar.YEAR);
+
+ dateCurrent = new Date();
+ }
+
+ /**
+ * This method returns a vector of all found calendar categories after parsing.
+ * @return Returns a Vector of all available CalendarCategory objects.
+ */
+ public Vector getCategories() {
+ return vecCategories;
+ }
+
+ /**
+ * This method sets the working directory. Its the "server_database_dir" variable defined in the current configuration by default.
+ * @param sWorkdir Specifies the working directory.
+ */
+ public void setWorkdir(String sWorkdir) {
+ this.sWorkdir = sWorkdir;
+ }
+
+ /**
+ * Starts the parsing work of the calendar database files.
+ */
+ public void start() {
+ lookForCategories();
+ parseAllCategories();
+ Main.execExternalCommand(Config.getStringValue("server_startup_command"));
+ }
+
+ /**
+ * Parses for the available calendar categories.
+ */
+ private void lookForCategories() {
+ File dir = new File(sWorkdir);
+ File[] dirContent = dir.listFiles();
+
+ for (int i = 0; i < dirContent.length; ++i)
+ if (dirContent[i].isFile())
+ // Ignore the 'calendar' file, only read the 'calendar.*' files
+ if (!dirContent[i].getName().equals("calendar"))
+ vecCategories.add(new CalendarCategory(dirContent[i]));
+ }
+
+ /**
+ * Parses all events of all available categories.
+ */
+ private void parseAllCategories() {
+ Enumeration enumCategories = vecCategories.elements();
+ while (enumCategories.hasMoreElements())
+ parseCategory((CalendarCategory) enumCategories.nextElement());
+ }
+
+ /**
+ * Parses all events of a category file.
+ * @param category Specifies the calendar category to be parsed.
+ */
+ private void parseCategory(CalendarCategory category) {
+ Vector vecEvents = new Vector();
+ File file = category.getFile();
+
+ try {
+ BufferedReader in = new BufferedReader(new FileReader(file));
+ String sLine;
+
+ while ((sLine = in.readLine()) != null) {
+ CalendarEvent event = new CalendarEvent(category);
+
+ // Ignore empty lines!
+ if (sLine.equals(""))
+ continue;
+
+ setEventsDate(event, sLine);
+ setEventsPlace(event, sLine);
+ setEventsDescription(event, sLine);
+
+ vecEvents.add(event);
+ }
+
+ } catch (Exception e) {
+ Main.infoMessage("Error: " + e.toString());
+ }
+
+ category.setEvents(vecEvents);
+ category.unsetFile();
+ }
+
+ /**
+ * This method parses all known informations from a given calendar format line and saves them
+ * into the given calendar event object.
+ * @param event Specifies the calendar event to be modified.
+ * @param sLine Specifies the single line of the category file to be parsed.
+ */
+ private void setEventsDate(CalendarEvent event, String sLine) {
+ // Create a local copy because the string may be modified
+ String sMyLine = new String(sLine).replaceAll(" ", "");
+ String sDateFormat;
+ boolean bValidDateFormat = false;
+
+ // Check if its a yearly event
+ Matcher matcher = dateYearlyPattern.matcher(sMyLine);
+ if (matcher.find()) {
+ sMyLine = sMyLine.replaceFirst("\tyearly", "-" + iCurrentYear);
+ sDateFormat = EXTENDED_DATE_FORMAT;
+ event.setYearly(true);
+ bValidDateFormat = true;
+
+ } else {
+ // Event is not yearly, but check if its still using NetCalendars
+ // extended format which contains the event's time (hours:minutes)
+ matcher = datePattern.matcher(sMyLine);
+ if (matcher.find()) {
+ sMyLine = sMyLine.replaceFirst("\t", "-");
+ sDateFormat = EXTENDED_DATE_FORMAT;
+ event.setYearly(false);
+ bValidDateFormat = true;
+
+ } else {
+ // Just use original Calendar format without any year and time
+ // informations
+ // Assume yearly
+ sMyLine = sMyLine.replaceFirst("\t", "-" + iCurrentYear);
+ sDateFormat = DATE_FORMAT;
+ event.setYearly(true);
+ bValidDateFormat = true;
+ }
+ }
+
+ // Create a new date object containing the events time informations
+ SimpleDateFormat formatter = new SimpleDateFormat(sDateFormat);
+ Date date = null;
+
+ if (bValidDateFormat) {
+ try {
+ date = formatter.parse(sMyLine);
+
+ } catch (ParseException e) {
+ Main.infoMessage("Error: Calendar format parser error at category "
+ + event.getCategoryName() + ": " + e.getMessage());
+ }
+ }
+
+ // The event is yearly, but occured already this year, so increment the events
+ // year by one!
+ if (event.isYearly() && date.getTime() < dateCurrent.getTime()) {
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTime(date);
+ calendar.set(Calendar.YEAR, iCurrentYear + 1);
+ date = calendar.getTime();
+ }
+
+ event.setDate(date);
+ }
+
+ /**
+ * Parses a single calendar line for the place information.
+ * @param event Specifies the calendar event to be modified.
+ * @param sLine Specifies the single line of the category file to be parsed.
+ */
+ private void setEventsPlace(CalendarEvent event, String sLine) {
+ int iPos = sLine.indexOf(";;");
+
+ // No event! Return empty string!
+ if (iPos < 0) {
+ event.setPlace("");
+
+ } else {
+ event.setPlace(trim(sLine.substring(iPos + 2)));
+ }
+ }
+
+ /**
+ * Parses a single calendar line for the description information.
+ * @param event Specifies the calendar event to be modified.
+ * @param sLine Specifies the single line of the category file to be parsed.
+ */
+ private void setEventsDescription(CalendarEvent event, String sLine) {
+ // We need a local copy because we may modify the string
+ String sTmp = new String(sLine);
+
+ // Check if there is a place string...
+ int iPos = sLine.indexOf(";;");
+
+ // ... if yes, dont include it!
+ if (iPos >= 0)
+ sTmp = sTmp.substring(0, iPos);
+
+ // Remove the events date from the string
+ Matcher matcher = dateEndPattern.matcher(sTmp);
+
+ if (matcher.find()) {
+ sTmp = sTmp.substring(matcher.start()+11);
+
+ } else {
+ sTmp = sTmp.substring(sTmp.indexOf("\t")+1);
+ }
+
+ event.setDescription(trim(sTmp));
+ }
+
+ /**
+ * Its like String.trim() but also removes a ending newline.
+ * @param sTrimString Specifies the String to be trimmed.
+ * @return Returns a copy of the string, with leading and trailing whitespace omitted, also a trailing newline will be omitted.
+ */
+ private String trim(String sTrimString) {
+ int iPos = sTrimString.indexOf("\n");
+
+ if (iPos >= 0)
+ return sTrimString.substring(0, iPos).trim();
+
+ return sTrimString.trim();
+ }
+}