com.gooddata.sdk.service.export.ExportService Maven / Gradle / Ivy
/*
* Copyright (C) 2004-2019, GoodData(R) Corporation. All rights reserved.
* This source code is licensed under the BSD-style license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
package com.gooddata.sdk.service.export;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gooddata.sdk.common.GoodDataException;
import com.gooddata.sdk.common.GoodDataRestException;
import com.gooddata.sdk.model.export.*;
import com.gooddata.sdk.model.gdc.AsyncTask;
import com.gooddata.sdk.model.gdc.UriResponse;
import com.gooddata.sdk.model.md.AbstractObj;
import com.gooddata.sdk.model.md.Obj;
import com.gooddata.sdk.model.md.ProjectDashboard;
import com.gooddata.sdk.model.md.ProjectDashboard.Tab;
import com.gooddata.sdk.model.md.report.Report;
import com.gooddata.sdk.model.md.report.ReportDefinition;
import com.gooddata.sdk.model.project.Project;
import com.gooddata.sdk.service.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplate;
import java.io.IOException;
import java.io.OutputStream;
import static com.gooddata.sdk.common.util.Validate.notNull;
import static com.gooddata.sdk.common.util.Validate.notNullState;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
/**
* Export project data
*
*/
public class ExportService extends AbstractService {
public static final String EXPORTING_URI = "/gdc/exporter/executor";
private static final String CLIENT_EXPORT_URI = "/gdc/projects/{projectId}/clientexport";
private static final String RAW_EXPORT_URI = "/gdc/projects/{projectId}/execute/raw";
public static final UriTemplate OBJ_TEMPLATE = new UriTemplate(Obj.OBJ_URI);
public static final UriTemplate PROJECT_TEMPLATE = new UriTemplate(Project.URI);
/**
* Service for data export
* @param restTemplate REST template
* @param settings settings
*/
public ExportService(final RestTemplate restTemplate, final GoodDataSettings settings) {
super(restTemplate, settings);
}
/**
* Export the given report definition in the given format to the given output stream
*
* @param reportDefinition report definition
* @param format export format
* @param output target
* @return polling result
* @throws NoDataExportException in case report contains no data
* @throws ExportException on error
*/
public FutureResult export(final ReportDefinition reportDefinition, final ExportFormat format,
final OutputStream output) {
notNull(reportDefinition, "reportDefinition");
final ReportRequest request = new ExecuteReportDefinition(reportDefinition);
return exportReport(request, format, output);
}
/**
* Export the given report in the given format to the given output stream
*
* @param report report
* @param format export format
* @param output target
* @return polling result
* @throws NoDataExportException in case report contains no data
* @throws ExportException on error
*/
public FutureResult export(final Report report, final ExportFormat format,
final OutputStream output) {
notNull(report, "report");
final ReportRequest request = new ExecuteReport(report);
return exportReport(request, format, output);
}
private FutureResult exportReport(final ReportRequest request, final ExportFormat format, final OutputStream output) {
notNull(output, "output");
notNull(format, "format");
final JsonNode execResult = executeReport(ReportRequest.URI, request);
final String uri = exportReport(execResult, format);
return new PollResult<>(this, new SimplePollHandler(uri, Void.class) {
@Override
public boolean isFinished(ClientHttpResponse response) throws IOException {
switch (response.getStatusCode()) {
case OK:
return true;
case ACCEPTED:
return false;
case NO_CONTENT:
throw new NoDataExportException();
default:
throw new ExportException("Unable to export report, unknown HTTP response code: " + response.getStatusCode());
}
}
@Override
public void handlePollException(final GoodDataRestException e) {
throw new ExportException("Unable to export report", e);
}
@Override
protected void onFinish() {
try {
restTemplate.execute(uri, GET, null, new OutputStreamResponseExtractor(output));
} catch (GoodDataException | RestClientException e) {
throw new ExportException("Unable to export report", e);
}
}
});
}
protected JsonNode executeReport(final String executionUri, final ReportRequest request) {
try {
final ResponseEntity entity = restTemplate
.exchange(executionUri, POST, new HttpEntity<>(request), String.class);
return mapper.readTree(entity.getBody());
} catch (GoodDataException | RestClientException e) {
throw new ExportException("Unable to execute report", e);
} catch (IOException e) {
throw new ExportException("Unable to read execution result", e);
}
}
private String exportReport(final JsonNode execResult, final ExportFormat format) {
notNull(execResult, "execResult");
notNull(format, "format");
final ObjectNode root = mapper.createObjectNode();
final ObjectNode child = mapper.createObjectNode();
child.set("result", execResult);
child.put("format", format.getValue());
root.set("result_req", child);
try {
return notNullState(restTemplate.postForObject(EXPORTING_URI, root, UriResponse.class), "exported report").getUri();
} catch (GoodDataException | RestClientException e) {
throw new ExportException("Unable to export report", e);
}
}
/**
* Export the given dashboard tab in PDF format to the given output stream
*
* @param endpoint endpoint for which the export is generated
* @param dashboard dashboard
* @param tab tab
* @param output output
* @return polling result
* @throws ExportException if export fails
*/
public FutureResult exportPdf(final GoodDataEndpoint endpoint, final ProjectDashboard dashboard, final Tab tab, final OutputStream output) {
notNull(endpoint, "endpoint");
notNull(dashboard, "dashboard");
notNull(tab, "tab");
notNull(output, "output");
final String projectId = extractProjectId(dashboard);
final String projectUri = PROJECT_TEMPLATE.expand(projectId).toString();
final String dashboardUri = dashboard.getUri();
final ClientExport export = new ClientExport(endpoint.toUri(), projectUri, dashboardUri, tab.getIdentifier());
final AsyncTask task;
try {
task = restTemplate.postForObject(CLIENT_EXPORT_URI, export, AsyncTask.class, projectId);
} catch (RestClientException | GoodDataRestException e) {
throw new ExportException("Unable to export dashboard: " + dashboardUri, e);
}
return new PollResult<>(this, new SimplePollHandler(notNullState(task, "export pdf task").getUri(), Void.class) {
@Override
public boolean isFinished(ClientHttpResponse response) throws IOException {
switch (response.getStatusCode()) {
case OK:
return true;
case ACCEPTED:
return false;
default:
throw new ExportException("Unable to export dashboard: " + dashboardUri +
", unknown HTTP response code: " + response.getStatusCode());
}
}
@Override
protected void onFinish() {
try {
restTemplate.execute(task.getUri(), GET, null, new OutputStreamResponseExtractor(output));
} catch (GoodDataException | RestClientException e) {
throw new ExportException("Unable to export dashboard: " + dashboardUri, e);
}
}
@Override
public void handlePollException(final GoodDataRestException e) {
throw new ExportException("Unable to export dashboard: " + dashboardUri, e);
}
});
}
/**
* Export the given Report using the raw export (without columns/rows limitations)
* @param report report
* @param output output
* @return polling result
* @throws ExportException in case export fails
*/
public FutureResult exportCsv(final Report report, final OutputStream output) {
notNull(report, "report");
return exportCsv(report, new ExecuteReport(report), output);
}
/**
* Export the given Report Definition using the raw export (without columns/rows limitations)
* @param definition report definition
* @param output output
* @return polling result
* @throws ExportException in case export fails
*/
public FutureResult exportCsv(final ReportDefinition definition, final OutputStream output) {
final ReportRequest request = new ExecuteReportDefinition(definition);
return exportCsv(definition, request, output);
}
private FutureResult exportCsv(final AbstractObj obj, final ReportRequest request, final OutputStream output) {
notNull(obj, "obj");
notNull(request, "request");
notNull(output, "output");
final String projectId = extractProjectId(obj);
final String uri = obj.getUri();
final UriResponse response;
try {
response = restTemplate.postForObject(RAW_EXPORT_URI, request, UriResponse.class, projectId);
} catch (RestClientException | GoodDataRestException e) {
throw new ExportException("Unable to export: " + uri);
}
if (response == null || response.getUri() == null) {
throw new ExportException("Empty response, unable to export: " + uri);
}
return new PollResult<>(this, new SimplePollHandler(response.getUri(), Void.class) {
@Override
public boolean isFinished(ClientHttpResponse response) throws IOException {
switch (response.getStatusCode()) {
case OK:
return true;
case ACCEPTED:
return false;
case NO_CONTENT:
throw new NoDataExportException();
default:
throw new ExportException("Unable to export: " + uri +
", unknown HTTP response code: " + response.getStatusCode());
}
}
@Override
protected void onFinish() {
try {
restTemplate.execute(getPolling(), GET, null, new OutputStreamResponseExtractor(output));
} catch (GoodDataException | RestClientException e) {
throw new ExportException("Unable to export: " + uri, e);
}
}
@Override
public void handlePollException(final GoodDataRestException e) {
throw new ExportException("Unable to export: " + uri, e);
}
});
}
static String extractProjectId(final AbstractObj obj) {
notNull(obj, "obj");
notNull(obj.getUri(), "obj.uri");
final String projectId = OBJ_TEMPLATE.match(obj.getUri()).get("projectId");
notNull(projectId, "obj uri - project id");
return projectId;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy