com.netflix.search.query.report.google.GoogleSheetsService Maven / Gradle / Ivy
/**
* Copyright 2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.search.query.report.google;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import com.netflix.search.query.report.detail.DetailReport;
import com.netflix.search.query.report.detail.DetailReportHeader;
import com.netflix.search.query.report.summary.SummaryReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.*;
import com.google.api.services.sheets.v4.model.AddSheetRequest;
import com.google.api.services.sheets.v4.model.AppendDimensionRequest;
import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest;
import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetResponse;
import com.google.api.services.sheets.v4.model.CellData;
import com.google.api.services.sheets.v4.model.ExtendedValue;
import com.google.api.services.sheets.v4.model.GridCoordinate;
import com.google.api.services.sheets.v4.model.Request;
import com.google.api.services.sheets.v4.model.RowData;
import com.google.api.services.sheets.v4.model.Sheet;
import com.google.api.services.sheets.v4.model.SheetProperties;
import com.google.api.services.sheets.v4.model.Spreadsheet;
import com.google.api.services.sheets.v4.model.UpdateCellsRequest;
import com.google.api.services.sheets.v4.model.ValueRange;
import com.netflix.search.query.Properties;
import com.netflix.search.query.input.TitleWithQueries;
import com.netflix.search.query.report.Report;
import com.netflix.search.query.report.ReportItem;
import com.netflix.search.query.report.ReportType;
import com.netflix.search.query.report.detail.DetailReportItem;
import com.netflix.search.query.report.summary.SummaryReportItem;
import com.netflix.search.query.utils.DateUtil;
import com.netflix.search.query.utils.HeaderUtils;
public class GoogleSheetsService {
public static final Logger logger = LoggerFactory.getLogger(GoogleSheetsService.class);
private String summaryReportName = "";
private String detailReportName = "";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static Sheets spreadsheetService = null;
private static final List SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS);
private DateUtil dateUtil = new DateUtil();
public GoogleSheetsService() {
super();
try {
initSpreadsheetService();
} catch (Throwable e) {
logger.error("Error trying to init the GoogleSheetsService", e);
}
}
public void setUpReportNames() {
this.summaryReportName = Properties.sumReportSheet.get();
this.detailReportName = Properties.detailReportSheet.get();
if (Properties.isDevOnlyTest.get()) {
this.summaryReportName = Properties.sumReportSheetDev.get();
this.detailReportName = Properties.detailReportSheetDev.get();
}
}
private void initSpreadsheetService() throws Throwable {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
spreadsheetService = new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)).setApplicationName(Properties.googleAppName.get()).build();
}
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws Exception {
File privateKeyFile = new File(Properties.googleSheetsKeyDir.get() + Properties.p12KeyFileName.get());
GoogleCredential cr = GoogleCredential
.fromStream(new FileInputStream(privateKeyFile))
.createScoped(SCOPES);
GoogleCredential.Builder builder = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountScopes(SCOPES)
.setServiceAccountId(cr.getServiceAccountId())
.setServiceAccountPrivateKey(cr.getServiceAccountPrivateKey())
.setServiceAccountPrivateKeyId(cr.getServiceAccountPrivateKeyId())
.setTokenServerEncodedUrl(cr.getTokenServerEncodedUrl())
.setServiceAccountUser(Properties.serviceAccountEmail.get());
return builder.build();
}
public List> getSpreadsheetDataForQueries(String worksheetId) throws Throwable {
List> values = null;
Spreadsheet spreadsheet = getSpreadsheet(Properties.inputQueriesSheet.get());
Sheet worksheet = getWorksheet(spreadsheet, worksheetId);
if (worksheet != null) {
ValueRange response = spreadsheetService.spreadsheets().values().get(Properties.inputQueriesSheet.get(), worksheetId).execute();
values = response.getValues();
}
return values;
}
public List> getSpreadsheetData(Spreadsheet spreadsheet, String spreadsheetName, String worksheetId) throws Throwable {
List> values = null;
Sheet worksheet = getWorksheet(spreadsheet, worksheetId);
if (worksheet != null) {
ValueRange response = spreadsheetService.spreadsheets().values().get(spreadsheetName, worksheetId).execute();
values = response.getValues();
}
return values;
}
public List getLatestSummaryReportAsTsv(Report report) {
return extractWorksheetData(report, HeaderUtils.getHeader(ReportType.summary));
}
public List getLatestDetailReportAsTsv(Report report) {
return extractWorksheetData(report, HeaderUtils.getHeader(ReportType.details));
}
public Report extractReport(boolean isDetailReport) throws Throwable {
Report report = null;
if (isDetailReport) report = new DetailReport();
else report = new SummaryReport();
List reportItems = null;
String spreadsheetName = getReportName(isDetailReport);
Spreadsheet spreadsheet = getSpreadsheet(spreadsheetName);
String worksheetId = getLatestWorksheetId(spreadsheet);
List> spreadsheetData = getSpreadsheetData(spreadsheet, spreadsheetName, worksheetId);
if (spreadsheetData != null && spreadsheetData.size() > 0) {
reportItems = getReport(spreadsheetData, isDetailReport);
}
report.setItems(reportItems);
report.setDate(worksheetId);
return report;
}
private String getLatestWorksheetId(Spreadsheet spreadsheet) {
String worksheetId = null;
Date reportCurrentDate = new Date(Long.MIN_VALUE);
for (Sheet sheet : spreadsheet.getSheets()) {
String title = sheet.getProperties().getTitle();
if (title.equals("instructions") || title.equals("Sheet1") || title.startsWith("diff_") || title.startsWith("ignore_"))
continue;
Date date = dateUtil.getDateFromString(title);
if (date.after(reportCurrentDate)) {
reportCurrentDate = date;
worksheetId = title;
}
}
return worksheetId;
}
protected List extractWorksheetData(List> values, String[] headerDefault) {
List returnValue = Lists.newArrayList();
int startingIndex = headerDefault == null ? 0 : 1;
int headerSize = 0;
if (values != null && values.size() > 0) {
if (headerDefault != null) {
returnValue.add(Arrays.asList(headerDefault).stream().collect(Collectors.joining(Properties.inputDelimiter.get())));
headerSize = headerDefault.length;
} else {
headerSize = values.get(0).size();
}
for (List