package be.digitalia.fosdem.parsers; import android.text.TextUtils; import org.xmlpull.v1.XmlPullParser; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Locale; import be.digitalia.fosdem.model.Day; import be.digitalia.fosdem.model.Event; import be.digitalia.fosdem.model.Link; import be.digitalia.fosdem.model.Person; import be.digitalia.fosdem.model.Track; import be.digitalia.fosdem.utils.DateUtils; /** * Main parser for FOSDEM schedule data in pentabarf XML format. * * @author Christophe Beyls */ public class EventsParser extends IterableAbstractPullParser<Event> { private final DateFormat DATE_FORMAT = DateUtils.withBelgiumTimeZone(new SimpleDateFormat("yyyy-MM-dd", Locale.US)); // Calendar used to compute the events time, according to Belgium timezone private final Calendar calendar = Calendar.getInstance(DateUtils.getBelgiumTimeZone(), Locale.US); private Day currentDay; private String currentRoom; private Track currentTrack; /** * Returns the hours portion of a time string in the "hh:mm" format, without allocating objects. * * @param time string in the "hh:mm" format * @return hours */ private static int getHours(String time) { return (Character.getNumericValue(time.charAt(0)) * 10) + Character.getNumericValue(time.charAt(1)); } /** * Returns the minutes portion of a time string in the "hh:mm" format, without allocating objects. * * @param time string in the "hh:mm" format * @return minutes */ private static int getMinutes(String time) { return (Character.getNumericValue(time.charAt(3)) * 10) + Character.getNumericValue(time.charAt(4)); } @Override protected boolean parseHeader(XmlPullParser parser) throws Exception { while (!isEndDocument()) { if (isStartTag("schedule")) { return true; } parser.next(); } return false; } @Override protected Event parseNext(XmlPullParser parser) throws Exception { while (!isNextEndTag("schedule")) { if (isStartTag()) { switch (parser.getName()) { case "day": currentDay = new Day(); currentDay.setIndex(Integer.parseInt(parser.getAttributeValue(null, "index"))); currentDay.setDate(DATE_FORMAT.parse(parser.getAttributeValue(null, "date"))); break; case "room": currentRoom = parser.getAttributeValue(null, "name"); break; case "event": Event event = new Event(); event.setId(Long.parseLong(parser.getAttributeValue(null, "id"))); event.setDay(currentDay); event.setRoomName(currentRoom); // Initialize empty lists List<Person> persons = new ArrayList<>(); event.setPersons(persons); List<Link> links = new ArrayList<>(); event.setLinks(links); String duration = null; String trackName = ""; Track.Type trackType = Track.Type.other; while (!isNextEndTag("event")) { if (isStartTag()) { switch (parser.getName()) { case "start": String time = parser.nextText(); if (!TextUtils.isEmpty(time)) { calendar.setTime(currentDay.getDate()); calendar.set(Calendar.HOUR_OF_DAY, getHours(time)); calendar.set(Calendar.MINUTE, getMinutes(time)); event.setStartTime(calendar.getTime()); } break; case "duration": duration = parser.nextText(); break; case "slug": event.setSlug(parser.nextText()); break; case "title": event.setTitle(parser.nextText()); break; case "subtitle": event.setSubTitle(parser.nextText()); break; case "track": trackName = parser.nextText(); break; case "type": try { trackType = Enum.valueOf(Track.Type.class, parser.nextText()); } catch (Exception e) { // trackType will be "other" } break; case "abstract": event.setAbstractText(parser.nextText()); break; case "description": event.setDescription(parser.nextText()); break; case "persons": while (!isNextEndTag("persons")) { if (isStartTag("person")) { Person person = new Person(); person.setId(Long.parseLong(parser.getAttributeValue(null, "id"))); person.setName(parser.nextText()); persons.add(person); } } break; case "links": while (!isNextEndTag("links")) { if (isStartTag("link")) { Link link = new Link(); link.setUrl(parser.getAttributeValue(null, "href")); link.setDescription(parser.nextText()); links.add(link); } } break; default: skipToEndTag(); break; } } } if ((event.getStartTime() != null) && !TextUtils.isEmpty(duration)) { calendar.add(Calendar.HOUR_OF_DAY, getHours(duration)); calendar.add(Calendar.MINUTE, getMinutes(duration)); event.setEndTime(calendar.getTime()); } if ((currentTrack == null) || !trackName.equals(currentTrack.getName()) || (trackType != currentTrack.getType())) { currentTrack = new Track(trackName, trackType); } event.setTrack(currentTrack); return event; default: skipToEndTag(); break; } } } return null; } }