ContactQuery query = null;
//if this is the first page, there is no next link. Construct initial page url
if (nextLink == null) {
String domain = getDomain(loggedInEmailAddress);
String initialLink = PROFILES_FEED + domain + PROJECTION_FULL;
query = new ContactQuery(new URL(initialLink));
query.setMaxResults(GAE_OPTIMAL_PAGE_SIZE);
} else {
query = new ContactQuery(new URL(nextLink));
}
query.setStringCustomParameter(TWO_LEGGED_OAUTH_PARAM, loggedInEmailAddress);
//fetch next profile feed containing entries
ProfileFeed feed = contactsService.query(query, ProfileFeed.class);
List> currentMaps = (List>)memcacheService.get(memcacheKey);
for(ProfileEntry entry:feed.getEntries()){
//secret sauce: convert entry into csv column header/value map
currentMaps.add(converter.flatten(entry));
}
//store updated list of converted entry maps back into memcache
memcacheService.put(memcacheKey, currentMaps);
if(feed.getNextLink()!=null){
//start task to get next page of entries
tasksService.fetchUserProfilesPageTask(spreadsheetTitle, loggedInEmailAddress, feed.getNextLink().getHref(), memcacheKey);
}else{
//no more pages to retrieve, start task to publish csv
tasksService.exportMapsToSpreadsheet(spreadsheetTitle,loggedInEmailAddress,memcacheKey);
}
}
Exporting Profiles as a Google Docs Spreadsheet
One of the trickiest obstacles to work around in this effort is generating the Spreadsheet file since GAE restricts the ability to write to the File System. The Spreadsheets Data API was one possibility we considered, but we ended up feeling it was a bit of overkill, having to first create the Spreadsheet using the Docs List API and then populate the Spreadsheet one record per request. This could have generated thousands of requests to populate the entire Spreadsheet. Instead, we leveraged an open source library to write csv file data directly to a byte array, and then sent the file data as the content of the newly created Docs List entry in a single request: public void saveRowsAsSpreadsheet(String spreadsheetTitle, String loggedInEmailAddress, String memcacheKey) {
//get list of csv column header/value maps from cache:
List> rows = (List>)memcacheService.get(memcacheKey);
//secret sauce: convert csv maps into a byte arrray
byte[] csvBytes = converter.getCsvBytes(rows);
SpreadsheetEntry newDocument = new SpreadsheetEntry();
MediaByteArraySource fileSource = new MediaByteArraySource(csvBytes,"text/csv");
MediaContent content = new MediaContent();
content.setMediaSource(fileSource);
content.setMimeType(new ContentType( "text/csv"));
//add MIME-Typed byte array as content to SpreadsheetEntry
newDocument.setContent(content);
//set title of SpreadsheetEntry
newDocument.setTitle(new PlainTextConstruct(docTitle));
URL feedUri = new URL(new StringBuilder(DOCS_URL).append('?').append(TWO_LEGGED_OAUTH_PARAM).append('=').append(userEmail).toString());
docsService.insert(feedUri,newDocument);
//we are done, time to delete the data stored in cache
memcacheService.delete(memcacheKey);
}
Once completed, this method results in a newly created, populated Google Docs Spreadsheet viewable in the logged-in user's Google Docs.