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 ( "|", "" ).replaceAll ( "\\s+", " " ).split("
"); 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 FROM_STRING; static { FROM_STRING = new HashMap(); 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; } } }