Conclusion
I've solved the problem with my own APIs that properly abstract the transport layer. The REST requests and JSON-result parsing is hidden from you, and you can access the Calendar via objects that implement reasonable abstractions. I'll be presenting those classes to you starting next month.
Related Articles
Implementing Secure Login: Part 2
Secure Login in AJAX Applications
Getting Started With the Cloud: Logging On With Google OAuth
Getting Started with Google Apps and OAuth
Getting Started with The Cloud: The Ecosystem
Allen Holub provides technical training, OO design and agile-process consulting, and web application/SaaS development services. He is the author of Holub on Patterns: Learning Design Patterns by Looking at Code, C+ C++: Programming With Objects in C and C++, and numerous articles for SD Times, JavaWorld, and IBM Developer Works. Contact him via http://www.holub.com/contact.
The XML that Google Returns
<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http:<i>//www.w3.org/2005/Atom'</i>
xmlns:openSearch='http:<i>//a9.com/-/spec/opensearch/1.1/'</i>
xmlns:gCal='http:<i>//schemas.google.com/gCal/2005'</i>
xmlns:gd='http:<i>//schemas.google.com/g/2005'</i>
gd:etag='W/"CkYFSHg-fyp7ImA9WxRVGUo."'>
<id>http:<i>//www.google.com/calendar/feeds/default/allcalendars/full</id></i>
<updated>2008-11-18T01:01:59.657Z</updated>
<title>Coach's Calendar List</title>
<link rel='alternate' type='text/html'
href='https:<i>//www.google.com/calendar/render' /></i>
<link rel='http:<i>//schemas.google.com/g/2005#feed'</i>
type='application/atom+xml'
href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full' /></i>
<link rel='http:<i>//schemas.google.com/g/2005#post'</i>
type='application/atom+xml'
href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full' /></i>
<link rel='self' type='application/atom+xml'
href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full' /></i>
<author>
<name>Coach</name>
<email>user@gmail.com</email>
</author>
<generator version='1.0' uri='http:<i>//www.google.com/calendar'>Google Calendar</generator></i>
<openSearch:startIndex>1</openSearch:startIndex>
<entry gd:etag='W/"DU4ERH47eCp7ImA9WxRVEkQ."'>
<id>http:<i>//www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com</id></i>
<published>2007-07-11T22:10:30.257Z</published>
<updated>2007-07-11T21:46:35.000Z</updated>
<title>My Primary Calendar</title>
<summary type='text'>A primary calendar is created by default for each Google Calendar user.</summary>
<link rel='alternate' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/user%40gmail.com/private/full' /></i>
<link rel='http:<i>//schemas.google.com/gCal/2005#eventFeed' type='application/atom+xml' href='https://www.google.com/calendar/feeds/user%40gmail.com/private/full' /></i>
<link rel='http:<i>//schemas.google.com/acl/2007#accessControlList' type='application/atom+xml' href='https://www.google.com/calendar/feeds/user%40gmail.com/acl/full' /></i>
<link rel='self' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com' /></i>
<link rel='edit' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com' /></i>
<author>
<name>Coach</name>
<email>user@gmail.com</email>
</author>
<gCal:timezone value='America/Los_Angeles' />
<gCal:hidden value='false' />
<gCal:color value='#2952A3' />
<gCal:selected value='true' />
<gCal:accesslevel value='owner' />
<gd:where valueString='Mountain View' />
</entry>
<entry gd:etag='W/"Ck4GRH4-eSp7ImA9WxRVGUo."'>
<id>http:<i>//www.google.com/calendar/feeds/default/allcalendars/full/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com</id></i>
<published>2007-07-11T22:10:30.258Z</published>
<updated>2007-07-11T21:50:15.000Z</updated>
<title>Little Giants</title>
<summary type='text'>This calendar contains practice times and this season's Little League game schedule. Go Little Giants!</summary>
<link rel='alternate' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com/private/full'/></i>
<link rel='http:<i>//schemas.google.com/gCal/2005#eventFeed' type='application/atom+xml' href='https://www.google.com/calendar/feeds/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com/private/full'/></i>
<link rel='http:<i>//schemas.google.com/acl/2007#accessControlList' type='application/atom+xml' href='https://www.google.com/calendar/feeds/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com/acl/full'/></i>
<link rel='self' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com'/></i>
<link rel='edit' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/rf1c66uld6dgk2t5lh43svev6g%40group.calendar.google.com'/></i>
<author>
<name>Little Giants</name>
</author>
<gCal:timezone value='America/Los_Angeles' />
<gCal:hidden value='false' />
<gCal:color value='#5A6986' />
<gCal:selected value='false' />
<gCal:accesslevel value='owner' />
<gd:where valueString='San Francisco' />
</entry>
<entry gd:etag='W/"C0cEQnkyeip7ImA9WxRVGUo."'>
<id>http:<i>//www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com</id></i>
<published>2007-07-11T22:10:30.297Z</published>
<updated>2007-06-05T09:38:50.000Z</updated>
<title>Google Doodles</title>
<summary type='text'/>
<link rel='alternate' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com/private/full'/></i>
<link rel='http:<i>//schemas.google.com/gCal/2005#eventFeed' type='application/atom+xml' href='https://www.google.com/calendar/feeds/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com/private/full'/></i>
<link rel='self' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/></i>
<link rel='edit' type='application/atom+xml' href='https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'/></i>
<author>
<name>Google Doodles</name>
</author>
<gCal:timezone value='Etc/GMT' />
<gCal:hidden value='false' />
<gCal:color value='#5229A3' />
<gCal:selected value='false' />
<gCal:accesslevel value='read' />
<gd:where valueString='' />
</entry>
</feed>
The JSON-C that Google Returns
{
"apiVersion": "2.3",
"data": {
"kind": "calendar#calendarFeed",
"etag": "W/\"AkQBSH8-fSp7IWA9WxBaGEs.\"",
"id": "http:<i>//www.google.com/calendar/feeds/default/allcalendars/full",</i>
"updated": "2010-03-29T13:12:39.155Z",
"author": {
"displayName": "Coach",
"email": "user@gmail.com"
},
"feedLink": "https:<i>//www.google.com/calendar/feeds/default/allcalendars/full",</i>
"selfLink": "https:<i>//www.google.com/calendar/feeds/default/allcalendars/full?alt\u003djsonc",</i>
"canPost": true,
"items": [
{
"kind": "calendar#calendar",
"etag": "W/\"Ck4FQX47eCp7IWA9WxBaFEk.\"",
"id": "http:<i>//www.google.com/calendar/feeds/default/calendars/full/user%40google.com",</i>
"created": "2010-03-29T13:12:38.877Z",
"updated": "2010-03-24T14:28:30.000Z",
"title": "My Primary Calendar",
"eventFeedLink": "https:<i>//www.google.com/calendar/feeds/user%40gmail.com/private/full",</i>
"accessControlListLink": "https:<i>//www.google.com/calendar/feeds/user%40gmail.com/acl/full",</i>
"selfLink": "https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/user%40gmail.com",</i>
"canEdit": true,
"author": {
"displayName": "Coach",
"email": "user@gmail.com"
},
"accessLevel": "owner",
"color": "#A32929",
"hidden": false,
"selected": true,
"timeZone": "America/Los_Angeles",
"location": "Mountain View",
"timesCleaned": 0
},
{
"kind": "calendar#calendar",
"etag": "W/\"CUMCQX47eCp7IWA9WxBaGEk.\"",
"id": "http:<i>//www.google.com/calendar/feeds/default/calendars/p%23moonphase%40group.v.calendar.google.com",</i>
"created": "2010-03-29T13:12:38.861Z",
"updated": "2010-03-29T06:17:40.000Z",
"title": "Phases of the Moon",
"details": "Shows the primary phases of the Moon",
"eventFeedLink": "https:<i>//www.google.com/calendar/feeds/p%23moonphase%40group.v.calendar.google.com/private/full",</i>
"selfLink": "https:<i>//www.google.com/calendar/feeds/default/allcalendars/full/p%23moonphase%40group.v.calendar.google.com",</i>
"canEdit": true,
"author": {
"displayName": "Phases of the Moon"
},
"accessLevel": "read",
"color": "#AB8B00",
"hidden": false,
"selected": false,
"timeZone": "Europe/Zurich",
"timesCleaned": 0
}
]
}
}


