WIP refactor api - export csv refactorings
This commit is contained in:
+6
@@ -1,12 +1,18 @@
|
||||
package org.mifosng.platform;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.mifosng.data.ExtraDatasets;
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
|
||||
public interface ReadExtraDataAndReportingService {
|
||||
|
||||
StreamingOutput retrieveReportCSV(String rptDB, String name,
|
||||
String type, Map<String, String> extractedQueryParams);
|
||||
|
||||
//@PreAuthorize(value = "hasAnyRole('REPORTING_SUPER_USER_ROLE')")
|
||||
GenericResultset retrieveGenericResultset(String rptDB, String name,
|
||||
String type, Map<String, String> extractedQueryParams);
|
||||
|
||||
+87
@@ -1,5 +1,9 @@
|
||||
package org.mifosng.platform;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
@@ -14,6 +18,7 @@ import javax.sql.DataSource;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.mifosng.data.ExtraDatasetRow;
|
||||
import org.mifosng.data.ExtraDatasets;
|
||||
@@ -39,6 +44,88 @@ public class ReadExtraDataAndReportingServiceImpl implements
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public StreamingOutput retrieveReportCSV(final String rptDB,
|
||||
final String name, final String type,
|
||||
final Map<String, String> queryParams) {
|
||||
|
||||
return new StreamingOutput() {
|
||||
public void write(OutputStream out) throws IOException, WebApplicationException {
|
||||
try {
|
||||
|
||||
GenericResultset result = retrieveGenericResultset(rptDB, name, type, queryParams);
|
||||
StringBuffer sb = generateCsvFileBuffer(result);
|
||||
|
||||
InputStream in = new ByteArrayInputStream(sb.toString().getBytes(
|
||||
"UTF-8"));
|
||||
|
||||
byte[] outputByte = new byte[4096];
|
||||
Integer readLen = in.read(outputByte, 0, 4096);
|
||||
|
||||
while (readLen != -1) {
|
||||
out.write(outputByte, 0, readLen);
|
||||
readLen = in.read(outputByte, 0, 4096);
|
||||
}
|
||||
//in.close();
|
||||
//out.flush();
|
||||
//out.close();
|
||||
} catch (Exception e) {
|
||||
throw new WebApplicationException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static StringBuffer generateCsvFileBuffer(GenericResultset result) {
|
||||
StringBuffer writer = new StringBuffer();
|
||||
|
||||
List<ResultsetColumnHeader> columnHeaders = result.getColumnHeaders();
|
||||
logger.info("NO. of Columns: " + columnHeaders.size());
|
||||
Integer chSize = columnHeaders.size();
|
||||
for (int i = 0; i < chSize; i++) {
|
||||
writer.append('"' + columnHeaders.get(i).getColumnName() + '"');
|
||||
if (i < (chSize - 1))
|
||||
writer.append(",");
|
||||
}
|
||||
writer.append('\n');
|
||||
|
||||
List<ResultsetDataRow> data = result.getData();
|
||||
List<String> row;
|
||||
Integer rSize;
|
||||
// String currCol;
|
||||
String currColType;
|
||||
String currVal;
|
||||
logger.info("NO. of Rows: " + data.size());
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
row = data.get(i).getRow();
|
||||
rSize = row.size();
|
||||
for (int j = 0; j < rSize; j++) {
|
||||
// currCol = columnHeaders.get(j).getColumnName();
|
||||
currColType = columnHeaders.get(j).getColumnType();
|
||||
currVal = row.get(j);
|
||||
if (currVal != null) {
|
||||
if (currColType.equals("DECIMAL")
|
||||
|| currColType.equals("DOUBLE")
|
||||
|| currColType.equals("BIGINT")
|
||||
|| currColType.equals("SMALLINT")
|
||||
|| currColType.equals("INT"))
|
||||
writer.append(currVal);
|
||||
else
|
||||
writer.append('"' + currVal + '"');
|
||||
}
|
||||
if (j < (rSize - 1))
|
||||
writer.append(",");
|
||||
}
|
||||
writer.append('\n');
|
||||
}
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public GenericResultset retrieveGenericResultset(final String rptDB,
|
||||
final String name, final String type,
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
package org.mifosng.platform.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
import org.mifosng.data.reports.ResultsetColumnHeader;
|
||||
import org.mifosng.data.reports.ResultsetDataRow;
|
||||
import org.mifosng.platform.ReadExtraDataAndReportingService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
@Controller
|
||||
public class ExportCSVController implements ServletContextAware {
|
||||
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(ExportCSVController.class);
|
||||
|
||||
private final ReadExtraDataAndReportingService readExtraDataAndReportingService;
|
||||
|
||||
@Autowired
|
||||
public ExportCSVController(
|
||||
final ReadExtraDataAndReportingService readExtraDataAndReportingService) {
|
||||
logger.info("ExportCSVController started");
|
||||
this.readExtraDataAndReportingService = readExtraDataAndReportingService;
|
||||
}
|
||||
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public String accessDeniedException() {
|
||||
return "unAuthorizedAction";
|
||||
}
|
||||
|
||||
/*
|
||||
* @ExceptionHandler(ClientValidationException.class) public @ResponseBody
|
||||
* Collection<ErrorResponse> validationException(ClientValidationException
|
||||
* ex, HttpServletResponse response) {
|
||||
*
|
||||
* response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
* response.setContentType("application/json");
|
||||
*
|
||||
* return ex.getValidationErrors(); }
|
||||
*/
|
||||
@RequestMapping(value = "/exportcsv", method = RequestMethod.GET)
|
||||
public void handleExportCSV(final HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
logger.info("handleExportCSV started");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String[]> queryParams = request.getParameterMap();
|
||||
|
||||
String rptDB = queryParams.get("MRP_rptDB")[0];
|
||||
String name = queryParams.get("MRP_Name")[0];
|
||||
String type = queryParams.get("MRP_Type")[0];
|
||||
|
||||
Set<String> keys = queryParams.keySet();
|
||||
Map<String, String> extractedQueryParams = new HashMap<String, String>();
|
||||
String pKey;
|
||||
String pValue;
|
||||
for (String k : keys) {
|
||||
|
||||
if (k.startsWith("MRP_")) {
|
||||
pKey = "${" + k.substring(4) + "}";
|
||||
pValue = queryParams.get(k)[0];
|
||||
// logger.info(name + ": " + pKey + ": " + pValue);
|
||||
extractedQueryParams.put(pKey, pValue);
|
||||
}
|
||||
}
|
||||
|
||||
// if (extractedQueryParams.size() > 3) {
|
||||
// throw new
|
||||
// UnsupportedOperationException("Not able to support this report for export to CSV right now.");
|
||||
// }
|
||||
|
||||
GenericResultset result = this.readExtraDataAndReportingService
|
||||
.retrieveGenericResultset(rptDB, name, type,
|
||||
extractedQueryParams);
|
||||
|
||||
// response.setContentType("application/octet-stream");
|
||||
response.setContentType("application/x-msdownload");
|
||||
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;filename=" + name.replaceAll(" ", "") + ".csv");
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
StringBuffer sb = generateCsvFileBuffer(result);
|
||||
|
||||
InputStream in = new ByteArrayInputStream(sb.toString().getBytes(
|
||||
"UTF-8"));
|
||||
|
||||
byte[] outputByte = new byte[4096];
|
||||
Integer readLen = in.read(outputByte, 0, 4096);
|
||||
|
||||
while (readLen != -1) {
|
||||
out.write(outputByte, 0, readLen);
|
||||
readLen = in.read(outputByte, 0, 4096);
|
||||
}
|
||||
in.close();
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
}
|
||||
|
||||
private static StringBuffer generateCsvFileBuffer(GenericResultset result) {
|
||||
StringBuffer writer = new StringBuffer();
|
||||
|
||||
List<ResultsetColumnHeader> columnHeaders = result.getColumnHeaders();
|
||||
logger.info("NO. of Columns: " + columnHeaders.size());
|
||||
Integer chSize = columnHeaders.size();
|
||||
for (int i = 0; i < chSize; i++) {
|
||||
writer.append('"' + columnHeaders.get(i).getColumnName() + '"');
|
||||
if (i < (chSize - 1))
|
||||
writer.append(",");
|
||||
}
|
||||
writer.append('\n');
|
||||
|
||||
List<ResultsetDataRow> data = result.getData();
|
||||
List<String> row;
|
||||
Integer rSize;
|
||||
// String currCol;
|
||||
String currColType;
|
||||
String currVal;
|
||||
logger.info("NO. of Rows: " + data.size());
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
row = data.get(i).getRow();
|
||||
rSize = row.size();
|
||||
for (int j = 0; j < rSize; j++) {
|
||||
// currCol = columnHeaders.get(j).getColumnName();
|
||||
currColType = columnHeaders.get(j).getColumnType();
|
||||
currVal = row.get(j);
|
||||
if (currVal != null) {
|
||||
if (currColType.equals("DECIMAL")
|
||||
|| currColType.equals("DOUBLE")
|
||||
|| currColType.equals("BIGINT")
|
||||
|| currColType.equals("SMALLINT")
|
||||
|| currColType.equals("INT"))
|
||||
writer.append(currVal);
|
||||
else
|
||||
writer.append('"' + currVal + '"');
|
||||
}
|
||||
if (j < (rSize - 1))
|
||||
writer.append(",");
|
||||
}
|
||||
writer.append('\n');
|
||||
}
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+105
-77
@@ -1,11 +1,16 @@
|
||||
package org.mifosng.platform.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -21,11 +26,14 @@ import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosng.data.ErrorResponse;
|
||||
import org.mifosng.data.ErrorResponseList;
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
import org.mifosng.data.reports.ResultsetColumnHeader;
|
||||
import org.mifosng.data.reports.ResultsetDataRow;
|
||||
import org.mifosng.platform.ReadExtraDataAndReportingService;
|
||||
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
|
||||
import org.mifosng.platform.exceptions.NewDataValidationException;
|
||||
@@ -42,109 +50,129 @@ import org.springframework.stereotype.Component;
|
||||
@Scope("singleton")
|
||||
public class ReportingApiResource {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ReportingApiResource.class);
|
||||
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(ReportingApiResource.class);
|
||||
|
||||
@Autowired
|
||||
private ReadExtraDataAndReportingService ReadExtraDataAndReportingService;
|
||||
|
||||
|
||||
private String _corsHeaders;
|
||||
|
||||
|
||||
private Response makeCORS(ResponseBuilder req, String returnMethod) {
|
||||
ResponseBuilder rb = req
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
|
||||
if (!"".equals(returnMethod)) {
|
||||
rb.header("Access-Control-Allow-Headers", returnMethod);
|
||||
}
|
||||
|
||||
return rb.build();
|
||||
ResponseBuilder rb = req.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
|
||||
if (!"".equals(returnMethod)) {
|
||||
rb.header("Access-Control-Allow-Headers", returnMethod);
|
||||
}
|
||||
|
||||
return rb.build();
|
||||
}
|
||||
|
||||
|
||||
private Response makeCORS(ResponseBuilder req) {
|
||||
return makeCORS(req, _corsHeaders);
|
||||
return makeCORS(req, _corsHeaders);
|
||||
}
|
||||
|
||||
private Response makeCORSExport(ResponseBuilder req, String exportFilename,
|
||||
String returnMethod) {
|
||||
ResponseBuilder rb = req
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
.header("Content-Disposition",
|
||||
"attachment;filename=" + exportFilename);
|
||||
|
||||
if (!"".equals(returnMethod)) {
|
||||
rb.header("Access-Control-Allow-Headers", returnMethod);
|
||||
}
|
||||
|
||||
return rb.build();
|
||||
}
|
||||
|
||||
private Response makeCORSExport(ResponseBuilder req, String exportFilename) {
|
||||
return makeCORSExport(req, exportFilename, _corsHeaders);
|
||||
}
|
||||
|
||||
// This OPTIONS request/response is necessary
|
||||
// if you consumes other format than text/plain or
|
||||
// if you use other HTTP verbs than GET and POST
|
||||
@OPTIONS
|
||||
public Response corsMyResource(@HeaderParam("Access-Control-Request-Headers") String requestH) {
|
||||
_corsHeaders = requestH;
|
||||
return makeCORS(Response.ok(), requestH);
|
||||
public Response corsMyResource(
|
||||
@HeaderParam("Access-Control-Request-Headers") String requestH) {
|
||||
_corsHeaders = requestH;
|
||||
return makeCORS(Response.ok(), requestH);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
@Produces({ MediaType.APPLICATION_JSON})
|
||||
public Response retrieveReport(@Context UriInfo uriInfo, @Context HttpServletResponse httpServletResponse) {
|
||||
|
||||
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response retrieveReport(@Context UriInfo uriInfo,
|
||||
@Context HttpServletResponse httpServletResponse) {
|
||||
|
||||
MultivaluedMap<String, String> queryParams = uriInfo
|
||||
.getQueryParameters();
|
||||
String rptDB = queryParams.getFirst("MRP_rptDB");
|
||||
String name = queryParams.getFirst("MRP_Name");
|
||||
String type = queryParams.getFirst("MRP_Type");
|
||||
|
||||
|
||||
Map<String, String> extractedQueryParams = new HashMap<String, String>();
|
||||
|
||||
Set<String> keys = queryParams.keySet();
|
||||
|
||||
Set<String> keys = queryParams.keySet();
|
||||
String pKey;
|
||||
String pValue;
|
||||
for (String k : keys) {
|
||||
|
||||
if (k.startsWith("MRP_"))
|
||||
{
|
||||
for (String k : keys) {
|
||||
|
||||
if (k.startsWith("MRP_")) {
|
||||
pKey = "${" + k.substring(4) + "}";
|
||||
pValue = queryParams.get(k).get(0);
|
||||
|
||||
|
||||
extractedQueryParams.put(pKey, pValue);
|
||||
}
|
||||
}
|
||||
logger.info("BEGINNING REQUEST FOR: " + name);
|
||||
GenericResultset result = this.ReadExtraDataAndReportingService.retrieveGenericResultset(rptDB, name, type, extractedQueryParams);
|
||||
|
||||
// JSONWithPadding paddedResult = new JSONWithPadding(result,
|
||||
// callbackName);
|
||||
|
||||
return makeCORS(Response.ok().entity(result));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/exportcsv/{reportDb}/{reportName}/{reportType}/office/{officeId}/currency/{currencyId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
public Response exportCsvReport(
|
||||
@PathParam("reportDb") String rptDB,
|
||||
@PathParam("reportName") String name,
|
||||
@PathParam("reportType") String type,
|
||||
@PathParam("officeId") Long officeId, @PathParam("currencyId") Long currencyId) throws IOException {
|
||||
|
||||
try {
|
||||
Map<String, String> extractedQueryParams = new HashMap<String, String>();
|
||||
|
||||
if (officeId != null && officeId > 0) {
|
||||
extractedQueryParams.put("${officeId}", officeId.toString());
|
||||
}
|
||||
|
||||
if (currencyId != null) {
|
||||
extractedQueryParams.put("${currencyId}", currencyId.toString());
|
||||
}
|
||||
|
||||
GenericResultset result = this.ReadExtraDataAndReportingService.retrieveGenericResultset(rptDB, name, type, extractedQueryParams);
|
||||
|
||||
return Response.ok().entity(result).build();
|
||||
} catch (UnAuthenticatedUserException e) {
|
||||
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
|
||||
} catch (AccessDeniedException e) {
|
||||
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
|
||||
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
|
||||
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
|
||||
} catch (ApplicationDomainRuleException e) {
|
||||
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
|
||||
} catch (NewDataValidationException e) {
|
||||
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
|
||||
}
|
||||
logger.info("BEGINNING REQUEST FOR: " + name);
|
||||
GenericResultset result = this.ReadExtraDataAndReportingService
|
||||
.retrieveGenericResultset(rptDB, name, type,
|
||||
extractedQueryParams);
|
||||
return makeCORS(Response.ok().entity(result));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/exportjpw")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ "application/x-msdownload" })
|
||||
public Response retrieveReportExport(@Context UriInfo uriInfo,
|
||||
@Context HttpServletResponse httpServletResponse) {
|
||||
|
||||
MultivaluedMap<String, String> queryParams = uriInfo
|
||||
.getQueryParameters();
|
||||
String rptDB = queryParams.getFirst("MRP_rptDB");
|
||||
String name = queryParams.getFirst("MRP_Name");
|
||||
String type = queryParams.getFirst("MRP_Type");
|
||||
|
||||
Map<String, String> extractedQueryParams = new HashMap<String, String>();
|
||||
|
||||
Set<String> keys = queryParams.keySet();
|
||||
String pKey;
|
||||
String pValue;
|
||||
for (String k : keys) {
|
||||
|
||||
if (k.startsWith("MRP_")) {
|
||||
pKey = "${" + k.substring(4) + "}";
|
||||
pValue = queryParams.get(k).get(0);
|
||||
|
||||
extractedQueryParams.put(pKey, pValue);
|
||||
}
|
||||
}
|
||||
logger.info("BEGINNING Export REQUEST FOR: " + name);
|
||||
|
||||
StreamingOutput result = this.ReadExtraDataAndReportingService
|
||||
.retrieveReportCSV(rptDB, name, type, extractedQueryParams);
|
||||
|
||||
return makeCORSExport(Response.ok().entity(result),
|
||||
name.replaceAll(" ", "") + ".csv");
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("forceauth")
|
||||
public Response hackToForceAuthentication() {
|
||||
|
||||
Reference in New Issue
Block a user