All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.vertretungsplan.additionalinfo.BaseIcalParser Maven / Gradle / Ivy

Go to download

Java library for parsing schools' substitution schedules. Supports multiple different systems mainly used in the German-speaking countries.

There is a newer version: 1.0.0-beta356
Show newest version
/*
 * substitution-schedule-parser - Java library for parsing schools' substitution schedules
 * Copyright (c) 2017 Johan v. Forstner
 *
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package me.vertretungsplan.additionalinfo;

import biweekly.Biweekly;
import biweekly.ICalendar;
import biweekly.component.VEvent;
import biweekly.io.TimezoneAssignment;
import biweekly.io.TimezoneInfo;
import biweekly.util.com.google.ical.compat.javautil.DateIterator;
import me.vertretungsplan.objects.AdditionalInfo;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;

public abstract class BaseIcalParser extends BaseAdditionalInfoParser {
    protected abstract String getIcalUrl();

    protected String getTitle() {
        return "Termine";
    }

    protected int getMaxItemsCount() {
        return 4;
    }

    @Override
    public AdditionalInfo getAdditionalInfo() throws IOException {
        AdditionalInfo info = new AdditionalInfo();
        info.setTitle(getTitle());

        String rawdata = httpGet(getIcalUrl(), "UTF-8");

        if (shouldStripTimezoneInfo()) {
            Pattern pattern = Pattern.compile("BEGIN:VTIMEZONE.*END:VTIMEZONE", Pattern.DOTALL);
            rawdata = pattern.matcher(rawdata).replaceAll("");
        }

        DateTime now = DateTime.now().withTimeAtStartOfDay();
        List icals = Biweekly.parse(rawdata).all();

        List events = new ArrayList<>();
        for (ICalendar ical : icals) {
            for (VEvent event : ical.getEvents()) {
                Event item = new Event();

                TimeZone timezoneStart = getTimeZoneStart(ical, event);

                if (event.getDescription() != null) {
                    item.description = event.getDescription().getValue();
                }
                if (event.getSummary() != null) {
                    item.summary = event.getSummary().getValue();
                }
                if (event.getDateStart() != null) {
                    item.startDate = new DateTime(event.getDateStart().getValue());
                    item.startHasTime = event.getDateStart().getValue().hasTime();
                } else {
                    continue;
                }
                if (event.getDateEnd() != null) {
                    item.endDate = new DateTime(event.getDateEnd().getValue());
                    item.endHasTime = event.getDateEnd().getValue().hasTime();
                }
                if (event.getLocation() != null) {
                    item.location = event.getLocation().getValue();
                }
                if (event.getUrl() != null) {
                    item.url = event.getUrl().getValue();
                }

                if (event.getRecurrenceRule() == null
                        && item.endDate != null
                        && (item.endDate.compareTo(now) < 0)) {
                    continue;
                } else if (event.getRecurrenceRule() == null
                        && (item.startDate.compareTo(now) < 0)) {
                    continue;
                }
                if (event.getRecurrenceRule() != null
                        && event.getRecurrenceRule().getValue().getUntil() != null
                        && event.getRecurrenceRule().getValue().getUntil()
                        .compareTo(now.toDate()) < 0) {
                    continue;
                }

                if (event.getRecurrenceRule() != null) {
                    Duration duration = null;
                    if (event.getDateEnd() != null) {
                        duration = new Duration(new DateTime(event.getDateStart().getValue()), new DateTime(event
                                .getDateEnd().getValue()));
                    }

                    DateIterator iterator = event.getDateIterator(timezoneStart);
                    while (iterator.hasNext()) {
                        Date date = iterator.next();
                        Event reccitem = item.clone();
                        reccitem.startDate = new DateTime(date);
                        reccitem.endDate = reccitem.startDate.plus(duration);

                        if (item.startDate.equals(reccitem.startDate)) continue;

                        if (item.endDate != null
                                && (item.endDate.compareTo(now) < 0)) {
                            continue;
                        } else if (item.endDate == null
                                && (item.startDate.compareTo(now) < 0)) {
                            continue;
                        }

                        events.add(reccitem);
                    }
                }

                if (item.endDate != null
                        && (item.endDate.compareTo(now) < 0)) {
                    continue;
                } else if (item.endDate == null
                        && (item.startDate.compareTo(now) < 0)) {
                    continue;
                }

                events.add(item);
            }
        }
        Collections.sort(events, new Comparator() {
            @Override public int compare(Event o1, Event o2) {
                return o1.startDate.compareTo(o2.startDate);
            }
        });

        StringBuilder content = new StringBuilder();

        int count = 0;

        DateTimeFormatter fmtDt = DateTimeFormat.shortDateTime().withLocale(Locale.GERMANY);
        DateTimeFormatter fmtD = DateTimeFormat.shortDate().withLocale(Locale.GERMANY);
        DateTimeFormatter fmtT = DateTimeFormat.shortTime().withLocale(Locale.GERMANY);

        for (Event item : events) {
            if (count >= getMaxItemsCount()) {
                break;
            } else if (count != 0) {
                content.append("

\n\n"); } DateTime start = item.startDate; if (item.endDate != null) { DateTime end = item.endDate; if (!item.endHasTime) { end = end.minusDays(1); } content.append((item.startHasTime ? fmtDt : fmtD).print(start)); if (!end.equals(start)) { content.append(" - "); if (item.startHasTime && item.endHasTime && end.toLocalDate().equals(start.toLocalDate())) { content.append(fmtT.print(end)); } else { content.append((item.endHasTime ? fmtDt : fmtD).print(end)); } } } else { content.append(fmtDt.print(start)); } content.append("
\n"); content.append(""); content.append(item.summary); content.append(""); count++; } info.setText(content.toString()); return info; } protected boolean shouldStripTimezoneInfo() { return false; } private TimeZone getTimeZoneStart(ICalendar ical, VEvent event) { if (event.getDateStart() == null) { return null; } TimezoneInfo tzinfo = ical.getTimezoneInfo(); TimeZone timezone; if (tzinfo.isFloating(event.getDateStart())) { timezone = TimeZone.getDefault(); } else { TimezoneAssignment dtstartTimezone = tzinfo.getTimezone(event.getDateStart()); timezone = (dtstartTimezone == null) ? TimeZone.getTimeZone("UTC") : dtstartTimezone.getTimeZone(); } return timezone; } private class Event implements Cloneable { public String summary; public String description; public String location; public DateTime startDate; public DateTime endDate; public String url; public boolean startHasTime; public boolean endHasTime; @Override protected Event clone() { Event clone = new Event(); clone.summary = this.summary; clone.description = this.description; clone.location = this.location; clone.startDate = this.startDate; clone.endDate = this.endDate; clone.url = this.url; return clone; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy