fulldatechart.FullDateChart.java Source code

Java tutorial

Introduction

Here is the source code for fulldatechart.FullDateChart.java

Source

/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package fulldatechart;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.fortuna.ical4j.data.CalendarOutputter;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Date;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.util.UidGenerator;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class FullDateChart {

    static class Slot implements Comparable<Slot> {
        final int month;
        final int day;

        public Slot(DateTime dt) {
            month = dt.getMonthOfYear();
            day = dt.getDayOfMonth();
        }

        @Override
        public int hashCode() {
            return toString().hashCode();
        }

        /**
         * Returns the next occurrence of this slot.
         * 
         * @return
         */
        public DateTime getNextOccurrence() {
            DateTime slot = DateTime.now().withMonthOfYear(month).withDayOfMonth(day).withTimeAtStartOfDay();
            if (slot.isBeforeNow())
                return slot.plusYears(1).withTimeAtStartOfDay();
            else
                return slot;
        }

        @Override
        public boolean equals(Object other) {
            return month == ((Slot) other).month && day == ((Slot) other).day;
        }

        @Override
        public String toString() {
            return String.format("%02d-%02d", month, day);
        }

        public int compareTo(Slot o) {
            if (o.month != month)
                return Integer.compare(month, o.month);
            else
                return Integer.compare(day, o.day);
        }
    }

    public static void main(String[] args) throws IOException, ParseException, ValidationException {
        if (args.length != 2) {
            System.out.println("Usage: .../fulldatechart.jar /path/to/myfinds.gpx <myuserid>");
            System.exit(1);
        }

        File f = new File(args[0]);
        String ownerId = args[1];

        DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZoneUTC();

        System.out.println("Parsing: " + f);
        Document document = Jsoup.parse(f, "UTF-8");

        Set<Slot> dates = new HashSet<Slot>();

        for (int i = 1; i <= 366; i++) {
            dates.add(new Slot(new DateTime().withYear(2012).withTimeAtStartOfDay().withDayOfYear(i)));
        }

        for (Element elem : document.select("groundspeak|date")) {
            Elements siblings = elem.siblingElements();
            String type = siblings.select("groundspeak|type").text();

            if ((type.equals("Found it") || type.equals("Attended"))
                    && siblings.select("groundspeak|finder").attr("id").equals(ownerId)) {
                DateTime dt = fmt.parseDateTime(elem.text());

                /*
                 * This seems to be necessary to get all log dates to conform to
                 * what's displayed on geocaching.com. Certain logs which have a
                 * date between 0000 and 0600 should really belong to the
                 * previous day.
                 */
                dt = dt.minusHours(6);
                dates.remove(new Slot(dt));
            }
        }

        Calendar cal = new Calendar();
        cal.getProperties().add(new ProdId("-//JesperEs/fulldatechart 1.0//EN"));
        cal.getProperties().add(Version.VERSION_2_0);
        cal.getProperties().add(CalScale.GREGORIAN);

        UidGenerator ug = new UidGenerator("1");

        List<Slot> list = new ArrayList<Slot>();
        list.addAll(dates);
        Collections.sort(list);

        for (Slot slot : list) {
            DateTime dt = slot.getNextOccurrence();
            System.out.format("Next occurrence of empty slot: %s -> %s\n", slot, dt);
            VEvent event = new VEvent(new Date(dt.withHourOfDay(19).toDate()), "Cache-day");
            event.getProperties().add(ug.generateUid());
            cal.getComponents().add(event);
        }

        File output = new File("fulldatechart.ics");
        FileOutputStream fout = new FileOutputStream(output);
        try {
            CalendarOutputter out = new CalendarOutputter();
            out.output(cal, fout);
            System.out.println("Calendar written to " + output.getAbsolutePath());
        } finally {
            fout.close();
        }
    }
}