package com.casamind.adware.server.proxy;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
import com.casamind.adware.server.utils.ServletHelper;
import com.casamind.adware.shared.ChartTypes;
import com.casamind.adware.shared.Strings;
import com.google.gdata.client.DocumentQuery;
import com.google.gdata.client.batch.BatchInterruptedException;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.client.photos.PicasawebService;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.Link;
import com.google.gdata.data.MediaContent;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.acl.AclEntry;
import com.google.gdata.data.acl.AclFeed;
import com.google.gdata.data.acl.AclRole;
import com.google.gdata.data.acl.AclScope;
import com.google.gdata.data.batch.BatchOperationType;
import com.google.gdata.data.batch.BatchStatus;
import com.google.gdata.data.batch.BatchUtils;
import com.google.gdata.data.docs.DocumentEntry;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.data.docs.PresentationEntry;
import com.google.gdata.data.media.MediaByteArraySource;
import com.google.gdata.data.photos.AlbumEntry;
import com.google.gdata.data.photos.AlbumFeed;
import com.google.gdata.data.photos.CommentEntry;
import com.google.gdata.data.photos.GphotoEntry;
import com.google.gdata.data.photos.GphotoFeed;
import com.google.gdata.data.photos.PhotoEntry;
import com.google.gdata.data.photos.TagEntry;
import com.google.gdata.data.photos.UserFeed;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
public class GDataDocumentsProxy {
private static final Logger log = Logger.getLogger(GDataDocumentsProxy.class.getName());
private long gdataThreadSleep = 20000;
private long gdataConnectTimeout = 20000;
private String documentsFeedUrl = "https://docs.google.com/feeds/default/private/full";
private String spreadsheetFeedUrl = "https://spreadsheets.google.com/feeds/spreadsheets/private/full";
private URL documentsFeedUri;
private URL spreadsheetFeedUri;
private String PWA_API_PREFIX;
private DocsService documentsService;
private SpreadsheetService spreadsheetService;
private PicasawebService photoService;
public GDataDocumentsProxy() {
this.documentsService = new DocsService("Avicena-v1");
this.photoService = new PicasawebService("Avicena-v1");
this.spreadsheetService = new SpreadsheetService("Avicena-v1");
}
public GDataDocumentsProxy(String login, String password) {
this();
connect(login, password);
}
public GDataDocumentsProxy(String documentsFeedUrl, String spreadsheetFeedUrl, String login, String password, long gdataThreadSleep, long gdataConnectTimeout) {
this();
this.gdataThreadSleep = gdataThreadSleep;
this.gdataConnectTimeout = gdataConnectTimeout;
this.documentsFeedUrl = documentsFeedUrl;
this.spreadsheetFeedUrl = spreadsheetFeedUrl;
connect(login, password);
}
private void connect(String login, String password) {
try {
if (ServletHelper.isDevMode()) {
// Ignore the servlet parameter
login("avicena.dev@gmail.com", "mofiapke1;");
} else {
log.info("GData API Login : \n\t" + login + "\n\t" + password);
login(login, password);
}
this.documentsFeedUri = new URL(documentsFeedUrl);
this.spreadsheetFeedUri = new URL(spreadsheetFeedUrl);
} catch (AuthenticationException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private void login(String user, String pass) throws AuthenticationException {
this.documentsService.setUserCredentials(user, pass);
this.spreadsheetService.setUserCredentials(user, pass);
this.photoService.setUserCredentials(user, pass);
this.documentsService.setConnectTimeout((int) gdataConnectTimeout);
this.documentsService.setReadTimeout((int) gdataConnectTimeout);
this.spreadsheetService.setConnectTimeout((int) gdataConnectTimeout);
this.spreadsheetService.setReadTimeout((int) gdataConnectTimeout);
this.PWA_API_PREFIX = "https://picasaweb.google.com/data/feed/api/user/";
}
public void deleteDocumentFile(DocumentListEntry entry) throws IOException, ServiceException {
entry.delete();
}
public DocumentListEntry createDocumentFile(String type, String title, String folder) throws IOException, ServiceException {
DocumentListEntry newEntry = null;
if (type.equals("document")) {
newEntry = new DocumentEntry();
} else if (type.equals("presentation")) {
newEntry = new PresentationEntry();
} else if (type.equals("spreadsheet")) {
newEntry = new com.google.gdata.data.docs.SpreadsheetEntry();
}
newEntry.setTitle(new PlainTextConstruct(title));
DocumentListEntry folderEntry = findDocumentFolderEntry(folder);
if (folderEntry != null) {
return documentsService.insert(new URL(((MediaContent) folderEntry.getContent()).getUri()), newEntry);
}
return documentsService.insert(documentsFeedUri, newEntry);
}
public String getExportLink(DocumentListEntry entry, String format){
return ((MediaContent) entry.getContent()).getUri() + "&exportFormat=" + format;
}
public void createReprtWorksheets(String title) {
try {
SpreadsheetEntry spEntry = findSpreadsheetEntry(title);
for (WorksheetEntry wsEntry : spEntry.getWorksheets()) {
if (wsEntry.getTitle().getPlainText().equals("Sheet 1") || wsEntry.getTitle().getPlainText().equals("Sheet1")) {
wsEntry.setTitle(new PlainTextConstruct(ChartTypes.TOTAL));
wsEntry.setRowCount(20);
wsEntry.setColCount(2);
wsEntry.update();
break;
}
}
URL wsFeedUrl = spEntry.getWorksheetFeedUrl();
WorksheetEntry wsEntry = null;
if (spEntry != null) {
if (findWorksheetEntry(ChartTypes.DAY, spEntry) == null) {
wsEntry = new WorksheetEntry();
wsEntry.setRowCount(365);
wsEntry.setColCount(20);
wsEntry.setTitle(new PlainTextConstruct(ChartTypes.DAY));
spreadsheetService.insert(wsFeedUrl, wsEntry);
Thread.sleep(gdataThreadSleep);
}
if (findWorksheetEntry(ChartTypes.MONTH, spEntry) == null) {
wsEntry = new WorksheetEntry();
wsEntry.setRowCount(12);
wsEntry.setColCount(20);
wsEntry.setTitle(new PlainTextConstruct(ChartTypes.MONTH));
spreadsheetService.insert(wsFeedUrl, wsEntry);
Thread.sleep(gdataThreadSleep);
}
if (findWorksheetEntry(ChartTypes.YEAR, spEntry) == null) {
wsEntry = new WorksheetEntry();
wsEntry.setRowCount(10);
wsEntry.setColCount(20);
wsEntry.setTitle(new PlainTextConstruct(ChartTypes.YEAR));
spreadsheetService.insert(wsFeedUrl, wsEntry);
Thread.sleep(2500);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private WorksheetEntry findWorksheetEntry(String title, SpreadsheetEntry spEntry) {
try {
for (WorksheetEntry wsEntry : spEntry.getWorksheets()) {
if (wsEntry.getTitle().getPlainText().equals(title)) {
return wsEntry;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void initStatSpreadSheet(String title) {
try {
SpreadsheetEntry spEntry = findSpreadsheetEntry(title);
if (spEntry != null) {
WorksheetEntry wsEntry = findWorksheetEntry(ChartTypes.DAY, spEntry);
if (wsEntry != null) {
initStatWorksheet(wsEntry, ChartTypes.DAY);
}
wsEntry = findWorksheetEntry(ChartTypes.MONTH, spEntry);
if (wsEntry != null) {
initStatWorksheet(wsEntry, ChartTypes.MONTH);
}
wsEntry = findWorksheetEntry(ChartTypes.YEAR, spEntry);
if (wsEntry != null) {
initStatWorksheet(wsEntry, ChartTypes.YEAR);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void initStatWorksheet(WorksheetEntry wsEntry, String type) {
try {
// this is a workaround for this
// http://code.google.com/p/gdata-java-client/issues/detail?id=103
spreadsheetService.setProtocolVersion(SpreadsheetService.Versions.V1);
URL cellFeedUrl = wsEntry.getCellFeedUrl();
CellFeed cellFeed = spreadsheetService.getFeed(cellFeedUrl, CellFeed.class);
// Build list of cell addresses to be filled in
List<BatchCell> batchCells = new ArrayList<BatchCell>();
Locale fr = new Locale("fr");
if (type.equals(ChartTypes.DAY)) {
Calendar calendar = Calendar.getInstance();
Calendar nextYear = Calendar.getInstance();
calendar.set(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_YEAR, 1);
nextYear.set(Calendar.MONTH, 1);
nextYear.set(Calendar.DAY_OF_YEAR, 1);
nextYear.add(Calendar.YEAR, 1);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM");
int i = 1;
while (calendar.before(nextYear)) {
batchCells.add(new BatchCell(i, 1, dateFormat.format(calendar.getTime())));
calendar.add(Calendar.DAY_OF_YEAR, 1);
i++;
}
} else if (type.equals(ChartTypes.MONTH)) {
DateFormatSymbols dfs = new DateFormatSymbols(fr);
String[] months = dfs.getShortMonths();
for (int i = 1; i < months.length; i++) {
batchCells.add(new BatchCell(i, 1, months[i - 1]));
}
} else if (type.equals(ChartTypes.YEAR)) {
for (int i = 1; i < 11; i++) {
batchCells.add(new BatchCell(i, 1, String.valueOf(i + 2010)));
}
}
// Prepare the update
// getCellEntryMap is what makes the update fast.
Map<String, CellEntry> cellEntries = getCellEntryMap(cellFeedUrl, batchCells);
CellFeed batchRequest = new CellFeed();
for (BatchCell batchCell : batchCells) {
CellEntry batchEntry = new CellEntry(cellEntries.get(batchCell.idString));
batchEntry.changeInputValueLocal(batchCell.value);
BatchUtils.setBatchId(batchEntry, batchCell.idString);
BatchUtils.setBatchOperationType(batchEntry, BatchOperationType.UPDATE);
batchRequest.getEntries().add(batchEntry);
}
// Submit the update
Link batchLink = cellFeed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
URL batchURL = new URL(batchLink.getHref());
CellFeed batchResponse = spreadsheetService.batch(batchURL, batchRequest);
// Ensure that all the operations were successful.
boolean isSuccess = true;
for (CellEntry entry : batchResponse.getEntries()) {
String batchId = BatchUtils.getBatchId(entry);
if (!BatchUtils.isSuccess(entry)) {
isSuccess = false;
BatchStatus status = BatchUtils.getBatchStatus(entry);
log.warning("\n" + batchId + " failed (" + status.getReason() + ") " + status.getContent());
}
}
if (isSuccess) {
log.info("Successfully executed all events via batch request.");
}
} catch (BatchInterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public DocumentListEntry updateDocumentFile(DocumentListEntry entry, String content, String mediaType) throws IOException, ServiceException {
entry.setMediaSource(new MediaByteArraySource(content.getBytes(), mediaType));
return entry.updateMedia(true);
}
public DocumentListEntry findDocumentEntry(String title) throws IOException, ServiceException {
DocumentListEntry entry = null;
DocumentQuery query = new DocumentQuery(documentsFeedUri);
query.setTitleQuery(title);
query.setTitleExact(true);
query.setMaxResults(1);
DocumentListFeed feed = documentsService.getFeed(query, DocumentListFeed.class);
if (feed != null && feed.getEntries().size() > 0) {
entry = feed.getEntries().get(0);
}
return entry;
}
private DocumentListEntry findDocumentFolderEntry(String title) throws IOException, ServiceException {
URL folderFeedUri = new URL("https://docs.google.com/feeds/default/private/full/-/folder");
DocumentListFeed feed = documentsService.getFeed(folderFeedUri, DocumentListFeed.class);
for (DocumentListEntry folder : feed.getEntries()) {
if (folder.getTitle().getPlainText().compareTo(title) == 0) {
return folder;
}
}
return null;
}
public DocumentListEntry uploadFile(byte[] mediaBytes, String mediaType, String title, String folder) throws IOException, ServiceException, URISyntaxException {
DocumentListEntry newEntry = new DocumentListEntry();
newEntry.setTitle(new PlainTextConstruct(title));
newEntry.setMediaSource(new MediaByteArraySource(mediaBytes, mediaType));
DocumentListEntry folderEntry = findDocumentFolderEntry(folder);
if (folderEntry != null) {
return documentsService.insert(new URL(((MediaContent) folderEntry.getContent()).getUri()), newEntry);
}
return documentsService.insert(documentsFeedUri, newEntry);
}
public PhotoEntry uploadImage(byte[] mediaBytes, String mediaType, String imageName, String albumName) throws IOException, ServiceException {
PhotoEntry myPhoto = new PhotoEntry();
myPhoto.setTitle(new PlainTextConstruct(imageName));
MediaByteArraySource myMedia = new MediaByteArraySource(mediaBytes, mediaType);
myPhoto.setMediaSource(myMedia);
AlbumEntry albumEntry = getAlbum(albumName);
if (albumEntry != null) {
return photoService.insert(new URL(((MediaContent) albumEntry.getContent()).getUri()), myPhoto);
}
return photoService.insert(new URL(PWA_API_PREFIX + "default"), myPhoto);
}
public SpreadsheetEntry findSpreadsheetEntry(String title) throws IOException, ServiceException {
SpreadsheetFeed feed = spreadsheetService.getFeed(spreadsheetFeedUri, SpreadsheetFeed.class);
for (SpreadsheetEntry entry : feed.getEntries()) {
if (entry.getTitle().getPlainText().equals(title))
return entry;
}
return null;
}
public String getSpreadsheetURL(String title) {
try {
DocumentListEntry entry = findDocumentEntry(title);
return entry == null ? null : entry.getDocumentLink().getHref();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void updateAclRole(DocumentListEntry entry, String newUser, String oldUser) {
AclFeed aclFeed;
boolean foundEntries = false;
AclScope scope = new AclScope(AclScope.Type.USER, newUser);
try {
if (oldUser != null) {
aclFeed = documentsService.getFeed(new URL(entry.getAclFeedLink().getHref()), AclFeed.class);
for (AclEntry aclEntry : aclFeed.getEntries()) {
if (aclEntry.getScope().getValue().equals(oldUser)) {
aclEntry.setScope(scope);
aclEntry.update();
foundEntries = true;
}
}
}
if (foundEntries == false) {
AclEntry aclEntry = new AclEntry();
aclEntry.setRole(new AclRole("reader"));
aclEntry.setScope(scope);
documentsService.insert(new URL(entry.getAclFeedLink().getHref()), aclEntry);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void addAclRole(DocumentListEntry entry, String user, String role) {
if (Strings.isValidDomainAccount(user, "gmail.com") || Strings.isValidDomainAccount(user, "casamind.com")) {
try {
AclEntry aclEntry = new AclEntry();
aclEntry.setRole(new AclRole(role));
aclEntry.setScope(new AclScope(AclScope.Type.USER, user));
documentsService.insert(new URL(entry.getAclFeedLink().getHref()), aclEntry);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
log.warning("Invalid user: " + user);
}
}
/**
* Retrieves the albums for the given user.
*/
public List<AlbumEntry> getAlbums(String username) throws IOException, ServiceException {
String albumUrl = PWA_API_PREFIX + username;
UserFeed userFeed = getFeed(albumUrl, UserFeed.class);
List<GphotoEntry> entries = userFeed.getEntries();
List<AlbumEntry> albums = new ArrayList<AlbumEntry>();
for (GphotoEntry entry : entries) {
GphotoEntry adapted = entry.getAdaptedEntry();
if (adapted instanceof AlbumEntry) {
albums.add((AlbumEntry) adapted);
}
}
return albums;
}
/**
* Retrieves the albums for the currently logged-in user. This is equivalent
* to calling {@link #getAlbums(String)} with "default" as the username.
*/
public List<AlbumEntry> getAlbums() throws IOException, ServiceException {
return getAlbums("default");
}
public AlbumEntry getAlbum(String albumName) {
try {
for (AlbumEntry entry : getAlbums()) {
if (entry.getName().equals(albumName))
return entry;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* Retrieves the tags for the given user. These are tags aggregated across
* the entire account.
*/
public List<TagEntry> getTags(String uname) throws IOException, ServiceException {
String tagUrl = PWA_API_PREFIX + uname + "?kind=tag";
UserFeed userFeed = getFeed(tagUrl, UserFeed.class);
List<GphotoEntry> entries = userFeed.getEntries();
List<TagEntry> tags = new ArrayList<TagEntry>();
for (GphotoEntry entry : entries) {
GphotoEntry adapted = entry.getAdaptedEntry();
if (adapted instanceof TagEntry) {
tags.add((TagEntry) adapted);
}
}
return tags;
}
/**
* Retrieves the tags for the currently logged-in user. This is equivalent
* to calling {@link #getTags(String)} with "default" as the username.
*/
public List<TagEntry> getTags() throws IOException, ServiceException {
return getTags("default");
}
/**
* Retrieves the photos for the given album.
*/
public List<PhotoEntry> getPhotos(AlbumEntry album) throws IOException, ServiceException {
String feedHref = getLinkByRel(album.getLinks(), Link.Rel.FEED);
AlbumFeed albumFeed = getFeed(feedHref, AlbumFeed.class);
List<GphotoEntry> entries = albumFeed.getEntries();
List<PhotoEntry> photos = new ArrayList<PhotoEntry>();
for (GphotoEntry entry : entries) {
GphotoEntry adapted = entry.getAdaptedEntry();
if (adapted instanceof PhotoEntry) {
photos.add((PhotoEntry) adapted);
}
}
return photos;
}
/**
* Retrieves the comments for the given photo.
*/
public List<CommentEntry> getComments(PhotoEntry photo) throws IOException, ServiceException {
String feedHref = getLinkByRel(photo.getLinks(), Link.Rel.FEED);
AlbumFeed albumFeed = getFeed(feedHref, AlbumFeed.class);
List<GphotoEntry> entries = albumFeed.getEntries();
List<CommentEntry> comments = new ArrayList<CommentEntry>();
for (GphotoEntry entry : entries) {
GphotoEntry adapted = entry.getAdaptedEntry();
if (adapted instanceof CommentEntry) {
comments.add((CommentEntry) adapted);
}
}
return comments;
}
/**
* Retrieves the tags for the given taggable entry. This is valid on user,
* album, and photo entries only.
*/
public List<TagEntry> getTags(GphotoEntry<?> parent) throws IOException, ServiceException {
String feedHref = getLinkByRel(parent.getLinks(), Link.Rel.FEED);
feedHref = addKindParameter(feedHref, "tag");
AlbumFeed albumFeed = getFeed(feedHref, AlbumFeed.class);
List<GphotoEntry> entries = albumFeed.getEntries();
List<TagEntry> tags = new ArrayList<TagEntry>();
for (GphotoEntry entry : entries) {
GphotoEntry adapted = entry.getAdaptedEntry();
if (adapted instanceof TagEntry) {
tags.add((TagEntry) adapted);
}
}
return tags;
}
/**
* Album-specific insert method to insert into the gallery of the current
* user, this bypasses the need to have a top-level entry object for parent.
*/
public AlbumEntry insertAlbum(AlbumEntry album) throws IOException, ServiceException {
String feedUrl = PWA_API_PREFIX + "default";
return photoService.insert(new URL(feedUrl), album);
}
/**
* Insert an entry into another entry. Because our entries are a hierarchy,
* this lets you insert a photo into an album even if you only have the
* album entry and not the album feed, making it quicker to traverse the
* hierarchy.
*/
public <T extends GphotoEntry> T insert(GphotoEntry<?> parent, T entry) throws IOException, ServiceException {
String feedUrl = getLinkByRel(parent.getLinks(), Link.Rel.FEED);
return photoService.insert(new URL(feedUrl), entry);
}
/**
* Helper function to allow retrieval of a feed by string url, which will
* create the URL object for you. Most of the Link objects have a string
* href which must be converted into a URL by hand, this does the
* conversion.
*/
public <T extends GphotoFeed> T getFeed(String feedHref, Class<T> feedClass) throws IOException, ServiceException {
return photoService.getFeed(new URL(feedHref), feedClass);
}
/**
* Helper function to add a kind parameter to a url.
*/
public String addKindParameter(String url, String kind) {
if (url.contains("?")) {
return url + "&kind=" + kind;
} else {
return url + "?kind=" + kind;
}
}
/**
* Helper function to get a link by a rel value.
*/
public String getLinkByRel(List<Link> links, String relValue) {
for (Link link : links) {
if (relValue.equals(link.getRel())) {
return link.getHref();
}
}
throw new IllegalArgumentException("Missing " + relValue + " link.");
}
/**
* Connects to the specified {@link SpreadsheetService} and uses a batch
* request to retrieve a {@link CellEntry} for each cell enumerated in
* {@code cellAddrs}. Each cell entry is placed into a map keyed by its RnCn
* identifier.
*
* @param ssSvc
* the spreadsheet service to use.
* @param cellFeedUrl
* url of the cell feed.
* @param cellAddrs
* list of cell addresses to be retrieved.
* @return a map consisting of one {@link CellEntry} for each address in
* {@code cellAddrs}
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Map getCellEntryMap(URL cellFeedUrl, List<BatchCell> cellAddrs) throws IOException, ServiceException {
CellFeed batchRequest = new CellFeed();
for (BatchCell cellId : cellAddrs) {
CellEntry batchEntry = new CellEntry(cellId.row, cellId.col, cellId.idString);
batchEntry.setId(String.format("%s/%s", cellFeedUrl.toString(), cellId.idString));
BatchUtils.setBatchId(batchEntry, cellId.idString);
BatchUtils.setBatchOperationType(batchEntry, BatchOperationType.QUERY);
batchRequest.getEntries().add(batchEntry);
}
CellFeed cellFeed = spreadsheetService.getFeed(cellFeedUrl, CellFeed.class);
Link batchLink = cellFeed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
URL batchURL = new URL(batchLink.getHref());
CellFeed queryBatchResponse = spreadsheetService.batch(batchURL, batchRequest);
Map cellEntryMap = new HashMap(cellAddrs.size());
for (CellEntry entry : queryBatchResponse.getEntries()) {
cellEntryMap.put(BatchUtils.getBatchId(entry), entry);
}
return cellEntryMap;
}
/**
* A basic struct to store cell row/column information and the associated
* RnCn identifier.
*/
private static class BatchCell {
public final int row;
public final int col;
public final String value;
public final String idString;
/**
* Constructs a CellAddress representing the specified {@code row} and
* {@code col}. The idString will be set in 'RnCn' notation.
*/
public BatchCell(int row, int col, String value) {
this.row = row;
this.col = col;
this.value = value;
this.idString = String.format("R%sC%s", row, col);
}
public BatchCell(int row, int col) {
this.row = row;
this.col = col;
this.value = "";
this.idString = String.format("R%sC%s", row, col);
}
}
}