czwartek, 6 stycznia 2011

everything I know about Google Calendar Api

source: http://code.google.com/intl/pl-PL/apis/calendar/data/2.0/developers_guide_java.html
// CONNECTING
        CalendarService service = new CalendarService("isod-export");
        service.setUserCredentials("login", "password");

        // RETRIVING ALL CALENDARS USER OWN
        String url = "https://www.google.com/calendar/feeds/default/owncalendars/full";
        URL feedUrl = new URL(url);
        CalendarFeed calendars = service.getFeed(feedUrl, CalendarFeed.class);

        // ITERATING ON CALENDARS
        for (int i = 0; i < calendars.getEntries().size(); i++) {
            CalendarEntry entry = calendars.getEntries().get(i);
            // GETTING CONTENT - CALENDAR DESCRIPTION
            entry.getPlainTextContent();
        }

        // CREATING NEW CALENDAR
        CalendarEntry calendar = new CalendarEntry();
        // FILLING UP CALENDAR
        calendar.setTitle(new PlainTextConstruct("CALENDAR NAME"));
        calendar.setSummary(new PlainTextConstruct("CALENDAR DESCRIPTION"));
        calendar.setTimeZone(new TimeZoneProperty("Europe/Warsaw"));
        calendar.setHidden(HiddenProperty.FALSE);
        calendar.setColor(new ColorProperty("#2952A3"));
        calendar.addLocation(new Where("", "", "NAME OF LOCATION"));
        // SENDING CALENDAR TO GOOGLE
        url = "https://www.google.com/calendar/feeds/default/owncalendars/full";
        URL postUrl = new URL(url);
        CalendarEntry inserted = service.insert(postUrl, calendar);

        // CREATING CALENDAR URL FROM ID
        String id = inserted.getId();
        url = id.replace("%40", "@").replace("http", "https").replace("default/calendars/", "") + "/private/full";

        // RETRIVING ENTRIES FROM CALENDAR
        feedUrl = new URL(url);
        CalendarEventFeed myFeed = service.getFeed(feedUrl, CalendarEventFeed.class);

        // ITERATING ON ENTRIES
        for (int i = 0; i < myFeed.getEntries().size(); i++) {
            CalendarEventEntry eventEntry = myFeed.getEntries().get(i);
        }
        // CREATING NEW ENTRY
        CalendarEventEntry newEntry = new CalendarEventEntry();
        Recurrence recur = new Recurrence();
        // CREATING RECURRENCE
        /*
         * DTSTART - start of event
         * TZID - time zone (must be same as calendar)
         * 20110110T081500 - date: yyyymmddThhmmss
         * DTEND - end of event
         * RRULE - repeating
         * BYDAY - available options: SU,MO,TU,WE,TH,FR,SA
         */
        String recurrence = "DTSTART;TZID=Europe/Warsaw:20110110T081500;\r\n"
                + "DTEND;TZID=Europe/Warsaw:20110110T100000;\r\n"
                + "RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=Mo,Tu;COUNT=15\r\n";
        recur.setValue(recurrence);
        // FILLING ENTRY WITH DATA
        newEntry.setRecurrence(recur);
        newEntry.addLocation(new Where("", "", "CLASSROOM"));
        newEntry.setTitle(new PlainTextConstruct("NAME OF SUBJECT"));
        newEntry.setContent(new PlainTextConstruct("DESCRIPTION OF SUBJECT (contains ID)"));

        // AND BATCHING LIKE ON http://code.google.com/intl/pl-PL/apis/calendar/data/2.0/developers_guide_java.html#batch
        // Get some events to operate on.
        URL defaultEventFeedUrl = new URL("https://www.google.com/calendar/feeds/default/private/full");
        CalendarEventFeed feed = service.getFeed(defaultEventFeedUrl, CalendarEventFeed.class);

// Create an batch entry to insert a new event.
        CalendarEventEntry toInsert = new CalendarEventEntry();
        toInsert.setTitle(new PlainTextConstruct("first batch event"));
        BatchUtils.setBatchId(toInsert, "1");
        BatchUtils.setBatchOperationType(toInsert, BatchOperationType.INSERT);

// Create an batch entry to query an event.
        CalendarEventEntry toQuery = feed.getEntries().get(0);
        BatchUtils.setBatchId(toQuery, "2");
        BatchUtils.setBatchOperationType(toQuery, BatchOperationType.QUERY);

// Create an batch entry to update an existing event.
        CalendarEventEntry toUpdate = feed.getEntries().get(1);
        toUpdate.setTitle(new PlainTextConstruct("updated via batch"));
        BatchUtils.setBatchId(toUpdate, "3");
        BatchUtils.setBatchOperationType(toUpdate, BatchOperationType.UPDATE);

// Create an batch entry to delete an existing event.
        CalendarEventEntry toDelete = feed.getEntries().get(2);
        BatchUtils.setBatchId(toDelete, "4");
        BatchUtils.setBatchOperationType(toDelete, BatchOperationType.DELETE);

// Add the entries to a new feed.
        CalendarEventFeed batchRequest = new CalendarEventFeed();
        batchRequest.getEntries().add(toInsert);
        batchRequest.getEntries().add(toQuery);
        batchRequest.getEntries().add(toUpdate);
        batchRequest.getEntries().add(toDelete);

// Get the batch link URL and send the batch request there.
        Link batchLink = feed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
        CalendarEventFeed batchResponse = service.batch(new URL(batchLink.getHref()), batchRequest);

// Ensure that all the operations were successful.
        boolean isSuccess = true;
        for (CalendarEventEntry entry : batchResponse.getEntries()) {
            String batchId = BatchUtils.getBatchId(entry);
            if (!BatchUtils.isSuccess(entry)) {
                isSuccess = false;
                BatchStatus status = BatchUtils.getBatchStatus(entry);
                System.out.println("\n" + batchId + " failed (" + status.getReason() + ") " + status.getContent());
            }
        }
        if (isSuccess) {
            System.out.println("Successfully deleted all events via batch request.");
        }
    }

Google Calendar

Projekt indywidualny zmusił mnie do zapoznania się z API kalendarza od Google'a.
Moim zadaniem było umożliwić studentom eksportowanie planu zajęć do prywatnego kalendarza.
Poniżej przedstawiam wam czego się nauczyłem.

Co będzie nam potrzebne?
- lista niezbędnych rzeczy znajduje się tutaj,
- biblioteki samego kalendarza pobieramy stąd.

1. Logowanie
Google API zapewnia nam kilka sposobów logowania się do naszego konta - ja korzystam z podawania loginu i hasła - ogranicza się to do dwóch linii kodu.

service = new CalendarService("isod-export");
service.setUserCredentials(login, password);
Powyższy kod tworzy service o nazwie "isod-export" - Jest to nazwa którą sam stworzyłem, nie ma ona żadnego znaczenia. Uwierzytelnienie znajduje się w drugiej linii.Po nawiązaniu połączenia możemy zacząć zabawę. Zaczynamy od pobrania listy kalendarzy - interesują nas tylko te, których właścicielem jest nasz student. Robimy to zgodnie z tym co sugeruje Google w swoim przewodniku.
public void connect(String login, String password) throws // Create a CalenderService and authenticate
CalendarService myService = new CalendarService("exampleCo-exampleApp-1");
myService.setUserCredentials("jo@gmail.com", "mypassword");

// Send the request and print the response
URL feedUrl = new URL("https://www.google.com/calendar/feeds/default/owncalendars/full");
CalendarFeed resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);
System.out.println("Calendars you own:");
System.out.println();
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
Praktycznie wszystko co dotyczy kalendarza da się wyczytać z przewodnika - problem jest z tymi magicznymi odnośnikami:
"https://www.google.com/calendar/feeds/default/owncalendars/full"
"https://www.google.com/calendar/feeds/jo@gmail.com/private/full"
Pierwszy z nich, jak zdążyliście zauważyć, daje nam dostęp do kalendarzy użytkownika. Natomiast drugi - pobiera wszystkie wydarzenia z kalendarza. I tu pada pytanie: Którego kalendarza?
Odpowiedzią jest - kalendarz domyślny. "jo@gmail.com" jest nie tylko loginem i mailem właściciela konta, nazwą kalendarza domyślnego, ale również jego 'adresem'.

Sporo problemów sprawiło mi zrozumienie jak odbierać/dodawać/usuwać zdarzenia z konkretnego kalendarza. Wystarczy posiadać odpowiednie URL. Tylko skąd je wziąć? CalendarEntry nie ma metody getUrl, ale ma getId() różnica między jednym a drugim wygląda następująco:
id = "http://www.google.com/calendar/feeds/default/calendars/joe%40gmail.com";
url = "https://www.google.com/calendar/feeds/joe@gmail.com/private/full";
Czyli wystarczyło
url = id.replace("%40", "@").replace("http", "https").replace("default/calendars/", "") + "/private/full";
I mamy wszystko co potrzeba :)
Dalsza praca była przyjemnością - wszystko zgodnie z przewodnikiem... Kolejne schody zaczęły się dopiero gdy trzeba było nadać zdarzeniom cykliczność... W przewodniku znajdziemy tylko taki przykład:
String recurData = "DTSTART;VALUE=DATE:20070501\r\n"
        + "DTEND;VALUE=DATE:20070502\r\n"
        + "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";

CalendarEventEntry myEntry = new CalendarEventEntry();
Recurrence recur = new Recurrence();
recur.setValue(recurData);
myEntry.setRecurrence(recur);

I odnośnik do dokumentacji specyfikacji. Jak tworzyć wydarzenia co dwa tygodnie? Jak ustawić godzinę? Jak ustawić strefę czasową? Szybki research i wszystko jasne :) a więc:
DTSTART;TZID=Europe/Warsaw:20110110T081500;
DTEND;TZID=Europe/Warsaw:20110110T100000;
RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=Mo;COUNT=15
Tworzy nam zdarzenie które rozpoczyna się (DTSTART) 10.01.2010 o godzinie 8:15 a kończy (DTEND) o godzinie 10:00 w strefie czasowej - warszawskiej (TZID). Wydarzenie odbywa się 15 razy (COUNT) - regularnie co 2 (INTERVAL) tygodnie (FREQ) - w poniedziałki (BYDAY).

I to chyba wszystko z czym mogą występować problemy.
Teraz wystarczy zapoznać się dobrze z przewodnikiem i ewentualnie specyfikacją tworzenia cyklicznych wydarzeń i można się bawić :)