summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/DHXCalParser.java')
-rw-r--r--src/DHXCalParser.java263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/DHXCalParser.java b/src/DHXCalParser.java
new file mode 100644
index 0000000..bad0581
--- /dev/null
+++ b/src/DHXCalParser.java
@@ -0,0 +1,263 @@
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.Iterator;
+import java.util.TimeZone;
+
+import java.io.PrintWriter;
+
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * This class stores the incoming data from XML.
+ * It is needed because of the stream nature of the XML parser.
+ **/
+public class DHXCalParser
+{
+ private final Group group;
+ private String uid_prefix;
+ private Event event;
+ private DataType data_type;
+ private int event_count;
+
+ public static void parse
+ (
+ final XMLStreamReader stream_reader,
+ final Group group,
+ final String uid_prefix
+ )
+ throws XMLStreamException
+ {
+ final DHXCalParser parser;
+
+ parser = new DHXCalParser(group, uid_prefix);
+
+ while (stream_reader.hasNext())
+ {
+ switch (stream_reader.next())
+ {
+ case XMLStreamReader.START_ELEMENT:
+ parser.handle_new_element(stream_reader);
+ break;
+
+ case XMLStreamReader.CDATA:
+ case XMLStreamReader.CHARACTERS:
+ parser.handle_data(stream_reader.getText().trim());
+ break;
+
+ case XMLStreamReader.END_DOCUMENT:
+ parser.flush();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ private DHXCalParser
+ (
+ final Group group,
+ final String uid_prefix
+ )
+ {
+ this.group = group;
+ this.uid_prefix = uid_prefix;
+
+ event = null;
+ event_count = 0;
+ }
+
+ /**
+ * Called when entering an new element.
+ **/
+ private void handle_new_element (final XMLStreamReader stream_reader)
+ {
+ final DataType new_data_type;
+
+ new_data_type = DataType.get(stream_reader.getLocalName());
+
+ switch (new_data_type)
+ {
+ case EVENT:
+ /** We're done handling the previous event. **/
+ flush();
+ break;
+
+ default:
+ break;
+ }
+
+ data_type = new_data_type;
+ }
+
+ private void flush ()
+ {
+ if (event == null)
+ {
+ /**
+ * This is the first event, we don't have anything to write.
+ **/
+
+ event = new Event();
+ event.set_uid(uid_prefix + (event_count++));
+
+ return;
+ }
+
+ group.add_event(event);
+
+ event = new Event();
+ event.set_uid(uid_prefix + (event_count++));
+ }
+
+ /**
+ * Called when finding actual data.
+ **/
+ private void handle_data (final String data)
+ {
+ final String[] info;
+ final StringBuilder sb;
+ int i;
+
+ if (data.equals(""))
+ {
+ /**
+ * Data was garbage.
+ * It happens sometimes, I don't know why.
+ **/
+
+ /* [XXX][Improvement] Prevent this from happening. */
+ return;
+ }
+
+ /**
+ * Uses the previously set "data_type" to know where the data belongs.
+ **/
+ switch (data_type)
+ {
+ case START_DATE:
+ event.set_start_time(date_to_calendar(data));
+ break;
+
+ case END_DATE:
+ event.set_end_time(date_to_calendar(data));
+ break;
+
+ case TEXT:
+ info =
+ data.replaceAll
+ (
+ "<b>|</b>",
+ ""
+ ).replaceAll
+ (
+ "\\s+",
+ " "
+ ).split("<br />");
+
+ event.set_name(info[0]);
+
+ sb = new StringBuilder();
+
+ for (i = 1; i < info.length; ++i)
+ {
+ sb.append(info[i].trim());
+ sb.append(", ");
+ }
+
+ if (info.length > 1)
+ {
+ sb.delete((sb.length() - 2), sb.length());
+ }
+
+ event.set_description(sb.toString());
+ break;
+
+ case DETAILS:
+ // TODO
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private static Calendar date_to_calendar (final String data)
+ {
+ final String[] day_hour;
+ final String[] hour;
+ final String[] day;
+ final java.util.Calendar result;
+
+ day_hour = data.split(" ");
+ hour = day_hour[1].split(":");
+ day = day_hour[0].split("-");
+
+ result =
+ java.util.Calendar.getInstance
+ (
+ TimeZone.getTimeZone("Europe/Paris"),
+ Locale.FRENCH
+ );
+
+ result.set(java.util.Calendar.DAY_OF_MONTH, Integer.parseInt(day[2]));
+
+ /* Java... don't ask... */
+ result.set(java.util.Calendar.MONTH, Integer.parseInt(day[1]) - 1);
+ result.set(java.util.Calendar.YEAR, Integer.parseInt(day[0]));
+
+ result.set(java.util.Calendar.HOUR_OF_DAY, Integer.parseInt(hour[0]));
+ result.set(java.util.Calendar.MINUTE, Integer.parseInt(hour[1]));
+
+ return result;
+ }
+
+ /**
+ * This enum is used to sort what is relevant in the XML file.
+ * Sadly, for justified reasons, Java does not permit access to the static
+ * members of an enum from its constructor, hence the "static"'s redundancy.
+ **/
+ private static enum DataType
+ {
+ IRRELEVANT,
+ EVENT,
+ START_DATE,
+ END_DATE,
+ TEXT,
+ DETAILS,
+ DATA;
+
+ private static final HashMap<String, DataType> FROM_STRING;
+
+ static
+ {
+ FROM_STRING = new HashMap<String, DataType>();
+
+ FROM_STRING.put("irrelevant", IRRELEVANT);
+ FROM_STRING.put("event", EVENT);
+ FROM_STRING.put("start_date", START_DATE);
+ FROM_STRING.put("end_date", END_DATE);
+ FROM_STRING.put("text", TEXT);
+ FROM_STRING.put("details", DETAILS);
+ FROM_STRING.put("data", DATA);
+ }
+
+ public static DataType get (final String e)
+ {
+ final DataType result;
+
+ result = FROM_STRING.get(e);
+
+ if (result == null)
+ {
+ return IRRELEVANT;
+ }
+
+ return result;
+ }
+ }
+}