| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/DHXCalParser.java')
| -rw-r--r-- | src/DHXCalParser.java | 263 |
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; + } + } +} |


