package de.superx.bianalysis.rest; import java.io.ByteArrayOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Base64; import java.util.Date; import org.apache.log4j.Logger; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import de.superx.bianalysis.ExcelSheetBuilder; import de.superx.bianalysis.ReportDefinition; import de.superx.bianalysis.StoredReport; import de.superx.bianalysis.metadata.Identifier; import de.superx.bianalysis.models.Dimension; import de.superx.bianalysis.models.DimensionAttribute; import de.superx.bianalysis.models.FactTable; import de.superx.bianalysis.models.Measure; import de.superx.bianalysis.models.Right; import de.superx.bianalysis.service.BiAnalysisManager; import de.superx.bianalysis.service.BiAnalysisRightService; import de.superx.bianalysis.service.DbMetaAdapter; import de.superx.common.NotYetImplementedException; import de.superx.rest.RestControllerBase; import de.superx.rest.model.Download; import de.superx.rest.model.Result; import de.superx.rest.model.ResultType; import de.superx.rest.model.Row; @RestController @RequestMapping("/api/reportwizard") public class BiAnalysisApi extends RestControllerBase { /* Autor: Robin Wübbeling * Achtung: Code ist schnell und unschön zusammengestellt, für einen ersten Entwurf * TODO: Filter * TODO: Berechnete Kennzahlen * TODO: Kennzahlenfilter momentan nur über 1 Dimensionsattribut möglich * TODO: Strings schöner durch "Platzhalter" * */ static Logger logger = Logger.getLogger(BiAnalysisApi.class); @Autowired DbMetaAdapter dbAdapter; @Autowired BiAnalysisRightService rightsService; @Autowired BiAnalysisManager biAnalysisManager; @Override protected Logger getLogger() { return logger; } @RequestMapping(method = RequestMethod.GET, path = "/facttables") public List listFactTables() throws NotYetImplementedException { List sachgebiete = rightsService.getSachgebiete(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); List factTables = rightsService.getFactTables(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); List facts = dbAdapter.getFactTables(sachgebiete, factTables); return facts; } @RequestMapping(method = RequestMethod.GET, path = "/dimensions") public List listDimensions(@RequestParam(value = "facttable_id") String facttable_id) { int sachgebietTid = dbAdapter.getSachgebietByFactTableId(facttable_id); rightsService.checkSachgebiet(sachgebietTid, Right.CREATE_ANALYSIS); rightsService.checkFactTable(new Identifier(facttable_id), Right.CREATE_ANALYSIS); return dbAdapter.getDimensionsWithoutHidden(new Identifier(facttable_id)); } // TODO: zeig in benamung does es sich vllt. um eine reduzierte liste handelt // granted vs allowed // umstellen auf camel case @RequestMapping(method = RequestMethod.GET, path = "/dimensionAttributeValues") public List listAttributeValues (@RequestParam(value = "attribute_id") List attribute_id, @RequestParam(value = "facts") List facts) { List tids = rightsService.getSachgebiete(Right.CREATE_ANALYSIS); List factTables = rightsService.getFactTables(Right.CREATE_ANALYSIS); List attributes = dbAdapter.getAllowedDimensionAttributes(attribute_id, tids, factTables); return dbAdapter.getDimensionAttributeValues(attributes, facts); } @RequestMapping(method = RequestMethod.GET, path = "/dimensionAttributeValuesHierarchy") public List> listAttributeValuesHierarchy(@RequestParam(value = "attribute_id") String attribute_id) { rightsService.checkCreateRights(); return dbAdapter.getDimensionAttributeValuesHierarchy(new Identifier(attribute_id)); } @RequestMapping(method = RequestMethod.GET, path = "/measures") public List listMeasures(@RequestParam(value = "facttable_id") String facttable_id) { rightsService.checkSachgebiet(dbAdapter.getSachgebietByFactTableId(facttable_id), Right.CREATE_ANALYSIS, Right.VIEW_REPORT); rightsService.checkFactTable(new Identifier(facttable_id), Right.CREATE_ANALYSIS, Right.VIEW_REPORT); return dbAdapter.getMeasures(new Identifier(facttable_id)); } @RequestMapping(method = RequestMethod.GET, path = "/findReportDefinition") public List findReportDefinition( @RequestParam(value = "title") Optional title, @RequestParam(value = "sach") Optional sach, @RequestParam(value = "facts") Optional> facts) { List allowedSachgebiete = rightsService.getSachgebiete(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); List allowedFacts = rightsService.getFactTables(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); List result = new ArrayList<>(); for (StoredReport report : dbAdapter.findAllStoredReports()) { List sachgebieteOfReport = dbAdapter.getSachgebieteForReport(report.reportDefinition); if (!allowedSachgebiete.isEmpty() && !allowedSachgebiete.containsAll(sachgebieteOfReport)) { continue; } if (title.isPresent()) { if (!report.name.toLowerCase().contains(title.get().toLowerCase())) { continue; } } if (sach.isPresent()) { if (!sachgebieteOfReport.contains(sach.get())) { continue; } } if(allowedFacts != null && allowedFacts.size() > 0) { boolean isFactAllowed = true; for (Identifier reportFactId : report.reportDefinition.factTableIds) { if(!allowedFacts.isEmpty() && !allowedFacts.contains(reportFactId)) { isFactAllowed = false; } } if (!isFactAllowed) { continue; } } if (facts.isPresent()) { boolean isFactMissing = false; for (Identifier reportFactId : report.reportDefinition.factTableIds) { if (!facts.get().contains(reportFactId.composedId)) { isFactMissing = true; break; } } if (isFactMissing) { continue; } } result.add(report); } return result; } @RequestMapping(method = RequestMethod.GET, path = "/getStoredReport") public StoredReport getStoredReport(@RequestParam(value = "id") int id) { Optional storedReportOpt = dbAdapter.findById(id); if(storedReportOpt.isPresent()) { StoredReport storedReport = storedReportOpt.get(); checkCreateOrViewRightForFactTables(storedReport.reportDefinition.factTableIds); try { storedReport.exportedResult = biAnalysisManager.createResult(storedReport.reportDefinition, dbAdapter); } catch (Exception e) { logger.error("Couldn't create report", e); e.printStackTrace(); } storedReport.isReadOnly = Boolean.valueOf(!this.rightsService.isCreateRight()); return storedReport; } return null; } @RequestMapping(method = RequestMethod.POST, path = "/report") public Result getReport(@RequestBody final ReportDefinition reportDefinition) throws Exception { List factTableIds = reportDefinition.factTableIds; checkCreateRightForFactTables(factTableIds); return biAnalysisManager.createResult(reportDefinition, dbAdapter); } @RequestMapping(method = RequestMethod.POST, path = "/persistReportDefinition") public int persistReportDefinition(@RequestBody final StoredReport storedReport) throws Exception { StoredReport.setReportDefinitionJson(storedReport); List factTableIds = storedReport.reportDefinition.factTableIds; checkCreateRightForFactTables(factTableIds); return dbAdapter.saveReportDefinition(storedReport); } @RequestMapping(value = "/report/download", method = RequestMethod.POST) public Download getFile(@RequestBody final StoredReport storedReport) throws Exception { checkCreateOrViewRightForFactTables(storedReport.reportDefinition.factTableIds); Date date = new Date(); String fileName = "BI-Analyse_"; if(storedReport.id != 0) { fileName += dbAdapter.findById(storedReport.id).get().name + "_"; if(fileName.length() > 206) { fileName = fileName.substring(0, 160); } fileName = fileName.replaceAll("[^a-zA-Z0-9äöüÄÖÜß_]+", "_"); } fileName += new SimpleDateFormat("yyyyMMdd_HHmmss").format(date); if(!storedReport.exportedResult.resultType.equals(ResultType.FlatTable)) { Row totalRow = storedReport.exportedResult.getTotalRow(); storedReport.exportedResult.rows = (BiAnalysisManager.hierarchyToRows(storedReport.hierarchy)); storedReport.exportedResult.rows.add(totalRow); } XSSFWorkbook workbook = new ExcelSheetBuilder(storedReport.exportedResult) .withFileName(fileName) .withReportName(storedReport.name) .withDescription(storedReport.description) .withDate(date) .build(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); workbook.write(bos); String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return new Download(fileName, contentType, base64String); } @RequestMapping(method = RequestMethod.POST, path = "/deleteReportDefinition") public boolean deleteReportDefinition(@RequestBody final int id) throws Exception { try { Optional reportOpt = dbAdapter.findById(id); if(reportOpt.isEmpty()) { throw new Exception("FEHLER: Berichtskonfiguration konnte nicht gefunden werden."); } checkCreateRightForFactTables(reportOpt.get().reportDefinition.factTableIds); rightsService.checkDeleteRights(); dbAdapter.deleteById(id); return true; } catch(Exception e) { throw new Exception("FEHLER: Berichtskonfiguration konnte nicht gelöscht werden.", e); } } @RequestMapping(method = RequestMethod.GET, path = "/reportDefinitions") public List listReportDefinitions() throws Exception { rightsService.checkCreateOrViewRights(); List storedReports = null; try { storedReports = dbAdapter.findAllStoredReports(); // TODO mit Marnie abklären, für überschreiben notwendig? } catch (Exception e) { e.printStackTrace(); if (e.getCause().getMessage().contains("FEHLER: Relation »metadata.rw_report_definitions« existiert nicht")) { throw new NotYetImplementedException("Bitte installieren Sie zuerst die Komponente 'BI-Analyse-Daten' und führen Sie anschließend den Konnektor aus."); } throw e; } return storedReports; } private void checkCreateOrViewRightForFactTables(List factTableIds) { for (Identifier factId : factTableIds) { int sachgebiet = dbAdapter.getSachgebietByFactTableId(factId.composedId); rightsService.checkSachgebiet(sachgebiet, Right.CREATE_ANALYSIS, Right.VIEW_REPORT); rightsService.checkFactTable(factId, Right.CREATE_ANALYSIS, Right.VIEW_REPORT); } } private void checkCreateRightForFactTables(List factTableIds) { for (Identifier factId : factTableIds) { int sachgebiet = dbAdapter.getSachgebietByFactTableId(factId.composedId); rightsService.checkSachgebiet(sachgebiet, Right.CREATE_ANALYSIS); rightsService.checkFactTable(factId, Right.CREATE_ANALYSIS); } } }