From 63a0f69100c58877b40a56455094fe7841ab2908 Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Sat, 1 Nov 2025 14:09:33 +0530 Subject: [PATCH] dashboard --- .../Dashboard1/Entity/Dashbord1_Line.java | 3 + .../Dashboard1/Service/HeaderService.java | 37 +- .../Controllers/ChartBuilder.java | 657 ++-------- .../Controllers/ChartBuilder2.java | 1062 +++++++++++++++++ .../Controllers/DashboardMockController.java | 49 + .../Controllers/Data_lakeController.java | 6 +- .../realnet/DataLake/Entity/Data_lake.java | 6 + .../Repository/Data_lakeRepository.java | 3 + .../DataLake/Services/Data_lakeService.java | 301 ++++- 9 files changed, 1508 insertions(+), 616 deletions(-) create mode 100644 backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder2.java create mode 100644 backend/src/main/java/com/realnet/Dashboard_builder/Controllers/DashboardMockController.java diff --git a/backend/src/main/java/com/realnet/Dashboard1/Entity/Dashbord1_Line.java b/backend/src/main/java/com/realnet/Dashboard1/Entity/Dashbord1_Line.java index bf2c9be..24caf89 100644 --- a/backend/src/main/java/com/realnet/Dashboard1/Entity/Dashbord1_Line.java +++ b/backend/src/main/java/com/realnet/Dashboard1/Entity/Dashbord1_Line.java @@ -38,6 +38,9 @@ public class Dashbord1_Line extends dashbord_Who_collumn { @Column(length = 5000) private String Model; + @Column(length = 5000) + private String common_filter; + @JsonBackReference @ManyToOne private Dashbord_Header dashbord_Header; diff --git a/backend/src/main/java/com/realnet/Dashboard1/Service/HeaderService.java b/backend/src/main/java/com/realnet/Dashboard1/Service/HeaderService.java index db488cf..634b91a 100644 --- a/backend/src/main/java/com/realnet/Dashboard1/Service/HeaderService.java +++ b/backend/src/main/java/com/realnet/Dashboard1/Service/HeaderService.java @@ -12,88 +12,73 @@ import com.realnet.Dashboard1.Repository.HeaderRepository; @Service public class HeaderService { - + @Autowired private HeaderRepository headerRepository; - + @Autowired private Dashboard_lineRepository dashboard_lineRepository; public Dashbord_Header Savedata(Dashbord_Header dashbord_Header) { - return headerRepository.save(dashbord_Header); + return headerRepository.save(dashbord_Header); } - public List getdetails() { // TODO Auto-generated method stub return (List) headerRepository.findAll(); } - public Dashbord_Header getdetailsbyId(int id) { // TODO Auto-generated method stub return headerRepository.findById(id); } - public void delete_by_id(int id) { // TODO Auto-generated method stub - headerRepository.deleteById(id); + headerRepository.deleteById(id); } - public Dashbord_Header update_dashboard_header(Dashbord_Header dashbord_Header) { return headerRepository.save(dashbord_Header); } - - - public Dashbord1_Line update_Dashbord1_Line(Dashbord1_Line dashbord1_Line) { // TODO Auto-generated method stub return dashboard_lineRepository.save(dashbord1_Line); } - public List get_by_module_id(int module_id) { // TODO Auto-generated method stub return (List) headerRepository.findbydashboardmodule(module_id); } - public List get_all_lines() { // TODO Auto-generated method stub return (List) dashboard_lineRepository.findAll(); } - + // public List get_by_module_id(int module_id) { // // TODO Auto-generated method stub // return (List) headerRepository.findAllById(module_id); // } - + // public List get_by_module_id(String module_id) { // // TODO Auto-generated method stub // return (List) headerRepository.findBymodule_id(module_id); // } public Dashbord1_Line update_Dashbord1_Lineby_id(int id, Dashbord1_Line dashbord1_Line) { - - - Dashbord1_Line oldline= dashboard_lineRepository.findById(id); + + Dashbord1_Line oldline = dashboard_lineRepository.findById(id); // .orElseThrow(() -> new ResourceNotFoundException(Constant.NOT_FOUND_EXCEPTION + " :" + id)); - oldline.setAccountId(dashbord1_Line.getAccountId()); oldline.setHeader_id(dashbord1_Line.getHeader_id()); oldline.setModel(dashbord1_Line.getModel()); - final Dashbord1_Line newline= dashboard_lineRepository.save(oldline); + oldline.setCommon_filter(dashbord1_Line.getCommon_filter()); + + final Dashbord1_Line newline = dashboard_lineRepository.save(oldline); return newline; } - - - - - - } diff --git a/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder.java b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder.java index 00723d9..a390749 100644 --- a/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder.java +++ b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder.java @@ -11,9 +11,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -31,6 +33,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.realnet.SureConnect.Entities.Sure_Connect; import com.realnet.SureConnect.Service.SureService; @@ -112,96 +116,74 @@ public class ChartBuilder { return tableData; } -//...........................22.07.2023.............................// + @GetMapping(value = "/getValue") + public ResponseEntity getValue(@RequestParam String apiUrl, @RequestParam Integer sureId, + @RequestParam(required = false) String key) throws IOException { -// @GetMapping(value = "/getdashjson/{job_type}") -// public ResponseEntity jsonretun(@RequestParam String tableName, @PathVariable String job_type, -// @RequestParam String xAxis, @RequestParam String yAxis) throws IOException { -// -// List> tableData = getAllDataFromTable(tableName); // Retrieve all data from the table -// -// List yAxisValues = new ArrayList<>(); -// List xAxisValues = new ArrayList<>(); -// -// for (Map row : tableData) { -// for (Entry entry : row.entrySet()) { -// String key = entry.getKey(); -// Object value = entry.getValue(); -// -// if (key.equalsIgnoreCase(xAxis)) { -// xAxisValues.add(value.toString()); -// } else if (key.equalsIgnoreCase(yAxis)) { -// yAxisValues.add(value); -// } -// } -// } -// -// StringBuilder jsonmap = new StringBuilder(); -// -// if (job_type.equalsIgnoreCase("Bar Chart")) { -// jsonmap.append("[\n"); -// } else if (job_type.equalsIgnoreCase("Line Chart")) { -// jsonmap.append(" {\r\n" + " \"chartData\": [\r\n" + " { \"data\": ["); -// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { -// jsonmap.append("{\"chartData\": [["); -// } -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// String xValue = xAxisValues.get(i); -// Object yValue = yAxisValues.get(i); -// -// if (job_type.equalsIgnoreCase("Bar Chart")) { -// jsonmap.append("{\"name\": \"" + xValue + "\", \"progress\":\"" + yValue + "\"},\n"); -// } else if (job_type.equalsIgnoreCase("Line Chart")) { -// jsonmap.append(yValue + ","); -// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { -// jsonmap.append(yValue + ","); -// } -// } -// -// if (!xAxisValues.isEmpty() && !yAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// if (job_type.equalsIgnoreCase("Bar Chart")) { -// jsonmap.append("]"); -// } else if (job_type.equalsIgnoreCase("Line Chart")) { -// jsonmap.append("], \"label\": \"" + yAxis + "\" }\r\n" + " ],\r\n" + " \"chartLabels\": [ "); -// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { -// jsonmap.append("]],\r\n" + " \"chartLabels\": ["); -// } -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// if (job_type.equalsIgnoreCase("Line Chart")) { -// jsonmap.append("] \n }\n"); -// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { -// jsonmap.append("]\n" + "}"); -// } -// -// return new ResponseEntity<>(jsonmap.toString(), HttpStatus.CREATED); -// } + System.out.println(" value get.."); + // Step 1: Fetch all table data from API + List> tableData = getAllDataFromApi(apiUrl, sureId); + + // Step 2: Handle null or empty key + if (key == null || key.trim().isEmpty()) { + return ResponseEntity.badRequest().body("Key parameter is required"); + } + + // Step 3: Extract unique values for that key + Set uniqueValues = tableData.stream().map(row -> row.get(key)) // get value by key + .filter(Objects::nonNull) // remove nulls + .collect(Collectors.toCollection(LinkedHashSet::new)); // keep unique + order + + // Step 4: Convert to List + List resultList = new ArrayList<>(uniqueValues); + + // Step 5: Return as ResponseEntity + return ResponseEntity.ok(resultList); + } @GetMapping(value = "/getdashjson/{job_type}") - public ResponseEntity jsonretun2(@PathVariable String job_type, @RequestParam String tableName, + public ResponseEntity jsonretun(@PathVariable String job_type, @RequestParam String tableName, @RequestParam(required = false) String xAxis, @RequestParam(required = false) List yAxes, @RequestParam Integer sureId, @RequestParam(required = false) String parameter, - @RequestParam(required = false) String parameterValue) throws IOException { + @RequestParam(required = false) String parameterValue, @RequestParam(required = false) String filters) + throws IOException { + + System.out.println(" chart data getting..."); + + List> tableData = getAllDataFromApi(tableName, sureId); // Retrieve all data from the table + + // ✅ Filter table data if parameter and parameterValue are provided + if (parameter != null && !parameter.trim().isEmpty() && parameterValue != null + && !parameterValue.trim().isEmpty()) { + + tableData = tableData.stream().filter(row -> { + Object paramVal = row.get(parameter); + return paramVal != null && paramVal.toString().equalsIgnoreCase(parameterValue); + }).collect(Collectors.toList()); + } + ObjectMapper mapper = new ObjectMapper(); + + // ✅ Parse filters JSON (supports both string and array values) + if (filters != null && !filters.trim().isEmpty()) { + Map filtersMap; + try { + filtersMap = mapper.readValue(filters, new TypeReference>() { + }); + } catch (Exception e) { + return new ResponseEntity<>("Invalid filters JSON format", HttpStatus.BAD_REQUEST); + } + + // ✅ Call reusable filter method + tableData = applyFilters(tableData, filtersMap); + } StringBuilder jsonmap = new StringBuilder(); if (job_type.equalsIgnoreCase("Grid")) { - List> allData = getAllDataFromApi(tableName, sureId); jsonmap.append("[\n"); - for (Map row : allData) { + for (Map row : tableData) { jsonmap.append("{\n"); int colCount = 0; @@ -220,7 +202,7 @@ public class ChartBuilder { jsonmap.append("}"); - if (!row.equals(allData.get(allData.size() - 1))) { + if (!row.equals(tableData.get(tableData.size() - 1))) { jsonmap.append(", "); } } @@ -231,12 +213,11 @@ public class ChartBuilder { } if (job_type.equalsIgnoreCase("Todo List") && yAxes != null && !yAxes.isEmpty()) { - List> allData = getAllDataFromApi(tableName, sureId); String listName = yAxes.get(0); // Assuming the first column in yAxes to be the list name List listData = new ArrayList<>(); - for (Map row : allData) { + for (Map row : tableData) { Object value = row.get(listName); if (value != null) { @@ -251,16 +232,6 @@ public class ChartBuilder { return new ResponseEntity<>(response, HttpStatus.CREATED); } - List> tableData = getAllDataFromApi(tableName, sureId); // Retrieve all data from the table - // ✅ Filter table data if parameter and parameterValue are provided - if (parameter != null && !parameter.trim().isEmpty() && parameterValue != null - && !parameterValue.trim().isEmpty()) { - - tableData = tableData.stream().filter(row -> { - Object paramVal = row.get(parameter); - return paramVal != null && paramVal.toString().equalsIgnoreCase(parameterValue); - }).collect(Collectors.toList()); - } List> yAxisValuesList = new ArrayList<>(); List xAxisValues = new ArrayList<>(); List parameterValues = new ArrayList<>(); @@ -289,404 +260,47 @@ public class ChartBuilder { jsonmap = getJson(jsonmap, yAxes, xAxisValues, yAxisValuesList, parameterValues); -// if (job_type.equalsIgnoreCase("Bar Chart") || job_type.equalsIgnoreCase("Bar")) { -// jsonmap.append("{\n \"barChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -//// Object yValue = yAxisValuesList.get(j).get(i); -// -// List list = yAxisValuesList.get(j); -// if (list.isEmpty()) { -// continue; -// -// } -// Object yValue = list.get(i); -// // ✅ Accept Integer, Long, Double, Float, or numeric Strings -// if (yValue instanceof Number) { -// jsonmap.append(yValue); -// } else if (yValue instanceof String) { -// String yStr = ((String) yValue).trim(); -// try { -// // Parse and append only if numeric -// Double num = Double.parseDouble(yStr); -// jsonmap.append(num); -// } catch (NumberFormatException e) { -// // not numeric — skip -// continue; -// } -// } else { -// continue; // skip non-numeric values -// } -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// // 🧹 Remove trailing comma if any -// int lastIndex = jsonmap.lastIndexOf(","); -// if (lastIndex == jsonmap.length() - 1) { -// jsonmap.deleteCharAt(lastIndex); -// } -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"barChartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } -// -// else if (job_type.equalsIgnoreCase("Line Chart") || job_type.equalsIgnoreCase("Line")) { -// jsonmap.append("{\n \"chartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// List list = yAxisValuesList.get(j); -// if (list.isEmpty()) { -// continue; -// -// } -// Object yValue = list.get(i); -// // ✅ Accept Integer, Long, Double, Float, or numeric Strings -// if (yValue instanceof Number) { -// jsonmap.append(yValue); -// } else if (yValue instanceof String) { -// String yStr = ((String) yValue).trim(); -// try { -// // Parse and append only if numeric -// Double num = Double.parseDouble(yStr); -// jsonmap.append(num); -// } catch (NumberFormatException e) { -// // not numeric — skip -// continue; -// } -// } else { -// continue; // skip non-numeric values -// } -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// // 🧹 Remove trailing comma if any -// int lastIndex = jsonmap.lastIndexOf(","); -// if (lastIndex == jsonmap.length() - 1) { -// jsonmap.deleteCharAt(lastIndex); -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"chartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } else if (job_type.equalsIgnoreCase("Doughnut Chart") || job_type.equalsIgnoreCase("Doughnut")) { -// jsonmap.append("{\"chartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object yValue = yAxisValuesList.get(j).get(i); -// jsonmap.append(yValue); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("]"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"chartLabels\": ["); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("]\n}"); -// } -// -// else if (job_type.equalsIgnoreCase("Radar Chart") || job_type.equalsIgnoreCase("Radar")) { -// jsonmap.append("{\n \"radarChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object yValue = yAxisValuesList.get(j).get(i); -// jsonmap.append(yValue); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"radarChartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } -// -// else if (job_type.equalsIgnoreCase("PolarArea Chart") || job_type.equalsIgnoreCase("PolarArea")) { -// jsonmap.append("{\n \"polarAreaChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object yValue = yAxisValuesList.get(j).get(i); -// jsonmap.append(yValue); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"polarAreaChartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } -// -// if (job_type.equalsIgnoreCase("Pie Chart") || job_type.equalsIgnoreCase("Pie")) { -// jsonmap.append("{\n \"pieChartData\": ["); -// -// for (int i = 0; i < yAxisValuesList.get(0).size(); i++) { // Assuming "mark" is the first item in yAxes -// jsonmap.append(yAxisValuesList.get(0).get(i)); // Use the y-axis values -// -// if (i < yAxisValuesList.get(0).size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"pieChartLabels\": [ "); -// -// for (int i = 0; i < xAxisValues.size(); i++) { // Assuming "name" is the x-axis -// jsonmap.append("\"" + xAxisValues.get(i) + "\""); // Use the x-axis values -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("] \n }\n"); -// } -// -// else if (job_type.equalsIgnoreCase("Bubble Chart") || job_type.equalsIgnoreCase("Bubble")) { -// jsonmap.append("{\n \"bubbleChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object xValue = xAxisValues.get(i); -// Object yValue = yAxisValuesList.get(j).get(i); -// int radius = 5 + (i % 3) * 3; // Adjust the radius as needed -// -// jsonmap.append("{ \"x\": " + xValue + ", \"y\": " + yValue + ", \"r\": " + radius + "}"); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"bubbleChartLabels\": [ "); -// -// for (String label : xAxisValues) { -// jsonmap.append("\"" + label + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } else if (job_type.equalsIgnoreCase("Scatter Chart") || job_type.equalsIgnoreCase("Scatter")) { -// jsonmap.append("{\n \"scatterChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object xValue = xAxisValues.get(i); -// Object yValue = yAxisValuesList.get(j).get(i); -// -// jsonmap.append("{ \"x\": " + xValue + ", \"y\": " + yValue + "}"); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"scatterChartLabels\": [ "); -// -// for (String label : xAxisValues) { -// jsonmap.append("\"" + label + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } -// -// else if (job_type.equalsIgnoreCase("Dynamic Chart") || job_type.equalsIgnoreCase("Dynamic")) { -// jsonmap.append("{\n \"dynamicChartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// Object yValue = yAxisValuesList.get(j).get(i); -// jsonmap.append(yValue); -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"dynamicChartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// } - return new ResponseEntity<>(jsonmap.toString(), HttpStatus.CREATED); } + /** + * ✅ Reusable filter method Supports both single-value and multi-value filters + */ + private List> applyFilters(List> tableData, + Map filtersMap) { + if (filtersMap == null || filtersMap.isEmpty()) + return tableData; + + return tableData.stream().filter(row -> { + for (Map.Entry entry : filtersMap.entrySet()) { + Object filterValue = entry.getValue(); + Object rowValue = row.get(entry.getKey()); + + // skip empty filters + if (filterValue == null) + continue; + + // ✅ Multi-value filter (List or Array) + if (filterValue instanceof List) { + List filterList = (List) filterValue; + if (filterList.isEmpty()) + continue; + if (rowValue == null + || !filterList.stream().anyMatch(v -> v.toString().equalsIgnoreCase(rowValue.toString()))) { + return false; + } + } + // ✅ Single-value filter + else { + if (rowValue == null || !rowValue.toString().equalsIgnoreCase(filterValue.toString())) { + return false; + } + } + } + return true; + }).collect(Collectors.toList()); + } + public StringBuilder getJson(StringBuilder jsonmap, List yAxes, List xAxisValues, List> yAxisValuesList, List parameterValues) { @@ -770,77 +384,6 @@ public class ChartBuilder { return jsonmap; } -// get json data -// public StringBuilder getJson(StringBuilder jsonmap, List yAxes, List xAxisValues, -// List> yAxisValuesList, List parameterValues) { -// jsonmap.append("{\n \"chartData\": [\n"); -// -// for (int j = 0; j < yAxes.size(); j++) { -// String yAxis = yAxes.get(j); -// -// jsonmap.append("{"); -// jsonmap.append("\"data\": ["); -// -// for (int i = 0; i < xAxisValues.size(); i++) { -// List list = yAxisValuesList.get(j); -// if (list.isEmpty()) { -// continue; -// -// } -// Object yValue = list.get(i); -// // ✅ Accept Integer, Long, Double, Float, or numeric Strings -// if (yValue instanceof Number) { -// jsonmap.append(yValue); -// } else if (yValue instanceof String) { -// String yStr = ((String) yValue).trim(); -// try { -// // Parse and append only if numeric -// Double num = Double.parseDouble(yStr); -// jsonmap.append(num); -// } catch (NumberFormatException e) { -// // not numeric — skip -// continue; -// } -// } else { -// continue; // skip non-numeric values -// } -// -// if (i < xAxisValues.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// // 🧹 Remove trailing comma if any -// int lastIndex = jsonmap.lastIndexOf(","); -// if (lastIndex == jsonmap.length() - 1) { -// jsonmap.deleteCharAt(lastIndex); -// } -// -// jsonmap.append("],"); -// jsonmap.append("\"label\": \"" + yAxis + "\""); -// jsonmap.append("}"); -// -// if (j < yAxes.size() - 1) { -// jsonmap.append(","); -// } -// } -// -// jsonmap.append("],\n \"chartLabels\": [ "); -// -// for (String xValue : xAxisValues) { -// jsonmap.append("\"" + xValue + "\","); -// } -// -// if (!xAxisValues.isEmpty()) { -// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); -// } -// -// jsonmap.append("] \n }\n"); -// -// return jsonmap; -// } -// - @GetMapping("/getAllKeys") public Set getAllKeys(@RequestParam String apiUrl, @RequestParam Integer sureId) { List> apiData = getAllKeyFromApi(apiUrl, sureId); diff --git a/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder2.java b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder2.java new file mode 100644 index 0000000..e1f30cb --- /dev/null +++ b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/ChartBuilder2.java @@ -0,0 +1,1062 @@ +package com.realnet.Dashboard_builder.Controllers; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.realnet.SureConnect.Entities.Sure_Connect; +import com.realnet.SureConnect.Service.SureService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j + +@RequestMapping("/chart2") +@RestController +public class ChartBuilder2 { + + @Autowired + private SureService sureService; + + public List> getAllDataFromTable(String tableName) { + List> tableData = new ArrayList<>(); + + Connection connection = null; + Statement statement = null; + ResultSet resultSet = null; + + try { + // Establish a database connection + connection = DriverManager.getConnection( + "jdbc:mysql://realnet.cdtynkxfiu2h.ap-south-1.rds.amazonaws.com:3306/suresetu", "cnsdev", + "cnsdev1234"); + + // Create a SQL statement + statement = connection.createStatement(); + + // Execute the query to retrieve all data from the table + String query = "SELECT * FROM " + tableName; + resultSet = statement.executeQuery(query); + + // Retrieve the column names from the result set + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + List columnNames = new ArrayList<>(); + for (int i = 1; i <= columnCount; i++) { + columnNames.add(metaData.getColumnName(i)); + } + + // Iterate over the result set and store each row in a map + while (resultSet.next()) { + Map rowData = new HashMap<>(); + for (String columnName : columnNames) { + Object value = resultSet.getObject(columnName); + rowData.put(columnName, value); + } + tableData.add(rowData); + } + } catch (SQLException e) { + log.error(e.getLocalizedMessage()); + } finally { + // Close the resources + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + log.error(e.getLocalizedMessage()); + } + } + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + log.error(e.getLocalizedMessage()); + } + } + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + log.error(e.getLocalizedMessage()); + } + } + } + + return tableData; + } + +//...........................22.07.2023.............................// + +// @GetMapping(value = "/getdashjson/{job_type}") +// public ResponseEntity jsonretun(@RequestParam String tableName, @PathVariable String job_type, +// @RequestParam String xAxis, @RequestParam String yAxis) throws IOException { +// +// List> tableData = getAllDataFromTable(tableName); // Retrieve all data from the table +// +// List yAxisValues = new ArrayList<>(); +// List xAxisValues = new ArrayList<>(); +// +// for (Map row : tableData) { +// for (Entry entry : row.entrySet()) { +// String key = entry.getKey(); +// Object value = entry.getValue(); +// +// if (key.equalsIgnoreCase(xAxis)) { +// xAxisValues.add(value.toString()); +// } else if (key.equalsIgnoreCase(yAxis)) { +// yAxisValues.add(value); +// } +// } +// } +// +// StringBuilder jsonmap = new StringBuilder(); +// +// if (job_type.equalsIgnoreCase("Bar Chart")) { +// jsonmap.append("[\n"); +// } else if (job_type.equalsIgnoreCase("Line Chart")) { +// jsonmap.append(" {\r\n" + " \"chartData\": [\r\n" + " { \"data\": ["); +// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { +// jsonmap.append("{\"chartData\": [["); +// } +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// String xValue = xAxisValues.get(i); +// Object yValue = yAxisValues.get(i); +// +// if (job_type.equalsIgnoreCase("Bar Chart")) { +// jsonmap.append("{\"name\": \"" + xValue + "\", \"progress\":\"" + yValue + "\"},\n"); +// } else if (job_type.equalsIgnoreCase("Line Chart")) { +// jsonmap.append(yValue + ","); +// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { +// jsonmap.append(yValue + ","); +// } +// } +// +// if (!xAxisValues.isEmpty() && !yAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// if (job_type.equalsIgnoreCase("Bar Chart")) { +// jsonmap.append("]"); +// } else if (job_type.equalsIgnoreCase("Line Chart")) { +// jsonmap.append("], \"label\": \"" + yAxis + "\" }\r\n" + " ],\r\n" + " \"chartLabels\": [ "); +// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { +// jsonmap.append("]],\r\n" + " \"chartLabels\": ["); +// } +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// if (job_type.equalsIgnoreCase("Line Chart")) { +// jsonmap.append("] \n }\n"); +// } else if (job_type.equalsIgnoreCase("Doughnut Chart")) { +// jsonmap.append("]\n" + "}"); +// } +// +// return new ResponseEntity<>(jsonmap.toString(), HttpStatus.CREATED); +// } + + @GetMapping(value = "/getValue") + public ResponseEntity getValue(@RequestParam String apiUrl, @RequestParam Integer sureId, + @RequestParam(required = false) String key) throws IOException { + + System.out.println(" value get.."); + // Step 1: Fetch all table data from API + List> tableData = getAllDataFromApi(apiUrl, sureId); + + // Step 2: Handle null or empty key + if (key == null || key.trim().isEmpty()) { + return ResponseEntity.badRequest().body("Key parameter is required"); + } + + // Step 3: Extract unique values for that key + Set uniqueValues = tableData.stream().map(row -> row.get(key)) // get value by key + .filter(Objects::nonNull) // remove nulls + .collect(Collectors.toCollection(LinkedHashSet::new)); // keep unique + order + + // Step 4: Convert to List + List resultList = new ArrayList<>(uniqueValues); + + // Step 5: Return as ResponseEntity + return ResponseEntity.ok(resultList); + } + + @GetMapping(value = "/getdashjson/{job_type}") + public ResponseEntity jsonretun(@PathVariable String job_type, @RequestParam String tableName, + @RequestParam(required = false) String xAxis, @RequestParam(required = false) List yAxes, + @RequestParam Integer sureId, @RequestParam(required = false) String parameter, + @RequestParam(required = false) String parameterValue, @RequestParam(required = false) String filters) + throws IOException { + + System.out.println(" chart data getting..."); + + List> tableData = getAllDataFromApi(tableName, sureId); // Retrieve all data from the table + + // ✅ Filter table data if parameter and parameterValue are provided + if (parameter != null && !parameter.trim().isEmpty() && parameterValue != null + && !parameterValue.trim().isEmpty()) { + + tableData = tableData.stream().filter(row -> { + Object paramVal = row.get(parameter); + return paramVal != null && paramVal.toString().equalsIgnoreCase(parameterValue); + }).collect(Collectors.toList()); + } + +// // ✅ Filters logic (multi-field filtering) +// if (filters != null && !filters.isEmpty()) { +// tableData = tableData.stream() +// .filter(row -> { +// for (Map.Entry entry : filters.entrySet()) { +// Object fieldVal = row.get(entry.getKey()); +// if (fieldVal == null || !fieldVal.toString().equalsIgnoreCase(entry.getValue().toString())) { +// return false; // agar koi bhi filter match nahi karta +// } +// } +// return true; // sab match kar gaye +// }) +// .collect(Collectors.toList()); +// } + + ObjectMapper mapper = new ObjectMapper(); + + // ✅ Parse filters JSON string (if provided) + Map parsedFilters = new HashMap<>(); + if (filters != null && !filters.trim().isEmpty()) { + try { + parsedFilters = mapper.readValue(filters, new TypeReference>() { + }); + } catch (Exception e) { + return new ResponseEntity<>("Invalid filters JSON format", HttpStatus.BAD_REQUEST); + } + } + + // Make it effectively final for lambda use + final Map filtersMap = parsedFilters; + // ✅ Multi-field filters (ignore empty/null values) +// if (filters != null && !filters.isEmpty()) { +// tableData = tableData.stream() +// .filter(row -> filters.entrySet().stream() +// .filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty()) // ignore +// // empty +// // filters +// .allMatch(entry -> { +// Object fieldVal = row.get(entry.getKey()); +// return fieldVal != null +// && fieldVal.toString().equalsIgnoreCase(entry.getValue().trim()); +// })) +// .collect(Collectors.toList()); +// } + + // ✅ Filters logic (ignore empty values) + // ✅ Filters logic (ignore empty values) + if (filtersMap != null && !filtersMap.isEmpty()) { + tableData = tableData.stream() + .filter(row -> filtersMap.entrySet().stream() + .filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty()) // ignore + // empty + // filters + .allMatch(entry -> { + Object fieldVal = row.get(entry.getKey()); + return fieldVal != null + && fieldVal.toString().equalsIgnoreCase(entry.getValue().trim()); + })) + .collect(Collectors.toList()); + } + + StringBuilder jsonmap = new StringBuilder(); + + if (job_type.equalsIgnoreCase("Grid")) { +// List> allData = getAllDataFromApi(tableName, sureId); + + jsonmap.append("[\n"); + + for (Map row : tableData) { + jsonmap.append("{\n"); + + int colCount = 0; + for (String yAxis : yAxes) { + String key = yAxis; + Object value = row.get(key); + + jsonmap.append("\"" + key + "\": \"" + value + "\""); + + colCount++; + if (colCount < yAxes.size()) { + jsonmap.append(", "); + } + jsonmap.append("\n"); + } + + jsonmap.append("}"); + + if (!row.equals(tableData.get(tableData.size() - 1))) { + jsonmap.append(", "); + } + } + + jsonmap.append("\n]\n"); + + return new ResponseEntity<>(jsonmap.toString(), HttpStatus.CREATED); + } + + if (job_type.equalsIgnoreCase("Todo List") && yAxes != null && !yAxes.isEmpty()) { +// List> allData = getAllDataFromApi(tableName, sureId); + + String listName = yAxes.get(0); // Assuming the first column in yAxes to be the list name + List listData = new ArrayList<>(); + + for (Map row : tableData) { + Object value = row.get(listName); + + if (value != null) { + listData.add(value); + } + } + + Map response = new HashMap<>(); + response.put("listName", listName); + response.put("List", listData); + + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + List> yAxisValuesList = new ArrayList<>(); + List xAxisValues = new ArrayList<>(); + List parameterValues = new ArrayList<>(); + + // Initialize a list for each y-axis parameter + for (int i = 0; i < yAxes.size(); i++) { + yAxisValuesList.add(new ArrayList<>()); + } + + for (Map row : tableData) { + for (Entry entry : row.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value != null && key.equalsIgnoreCase(xAxis)) { + xAxisValues.add(value.toString()); + } else { + int yIndex = yAxes.indexOf(key); + if (yIndex >= 0) { + yAxisValuesList.get(yIndex).add(value); + } + } + + } + } + + jsonmap = getJson(jsonmap, yAxes, xAxisValues, yAxisValuesList, parameterValues); + +// if (job_type.equalsIgnoreCase("Bar Chart") || job_type.equalsIgnoreCase("Bar")) { +// jsonmap.append("{\n \"barChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +//// Object yValue = yAxisValuesList.get(j).get(i); +// +// List list = yAxisValuesList.get(j); +// if (list.isEmpty()) { +// continue; +// +// } +// Object yValue = list.get(i); +// // ✅ Accept Integer, Long, Double, Float, or numeric Strings +// if (yValue instanceof Number) { +// jsonmap.append(yValue); +// } else if (yValue instanceof String) { +// String yStr = ((String) yValue).trim(); +// try { +// // Parse and append only if numeric +// Double num = Double.parseDouble(yStr); +// jsonmap.append(num); +// } catch (NumberFormatException e) { +// // not numeric — skip +// continue; +// } +// } else { +// continue; // skip non-numeric values +// } +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// // 🧹 Remove trailing comma if any +// int lastIndex = jsonmap.lastIndexOf(","); +// if (lastIndex == jsonmap.length() - 1) { +// jsonmap.deleteCharAt(lastIndex); +// } +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"barChartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } +// +// else if (job_type.equalsIgnoreCase("Line Chart") || job_type.equalsIgnoreCase("Line")) { +// jsonmap.append("{\n \"chartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// List list = yAxisValuesList.get(j); +// if (list.isEmpty()) { +// continue; +// +// } +// Object yValue = list.get(i); +// // ✅ Accept Integer, Long, Double, Float, or numeric Strings +// if (yValue instanceof Number) { +// jsonmap.append(yValue); +// } else if (yValue instanceof String) { +// String yStr = ((String) yValue).trim(); +// try { +// // Parse and append only if numeric +// Double num = Double.parseDouble(yStr); +// jsonmap.append(num); +// } catch (NumberFormatException e) { +// // not numeric — skip +// continue; +// } +// } else { +// continue; // skip non-numeric values +// } +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// // 🧹 Remove trailing comma if any +// int lastIndex = jsonmap.lastIndexOf(","); +// if (lastIndex == jsonmap.length() - 1) { +// jsonmap.deleteCharAt(lastIndex); +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"chartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } else if (job_type.equalsIgnoreCase("Doughnut Chart") || job_type.equalsIgnoreCase("Doughnut")) { +// jsonmap.append("{\"chartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object yValue = yAxisValuesList.get(j).get(i); +// jsonmap.append(yValue); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("]"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"chartLabels\": ["); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("]\n}"); +// } +// +// else if (job_type.equalsIgnoreCase("Radar Chart") || job_type.equalsIgnoreCase("Radar")) { +// jsonmap.append("{\n \"radarChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object yValue = yAxisValuesList.get(j).get(i); +// jsonmap.append(yValue); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"radarChartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } +// +// else if (job_type.equalsIgnoreCase("PolarArea Chart") || job_type.equalsIgnoreCase("PolarArea")) { +// jsonmap.append("{\n \"polarAreaChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object yValue = yAxisValuesList.get(j).get(i); +// jsonmap.append(yValue); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"polarAreaChartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } +// +// if (job_type.equalsIgnoreCase("Pie Chart") || job_type.equalsIgnoreCase("Pie")) { +// jsonmap.append("{\n \"pieChartData\": ["); +// +// for (int i = 0; i < yAxisValuesList.get(0).size(); i++) { // Assuming "mark" is the first item in yAxes +// jsonmap.append(yAxisValuesList.get(0).get(i)); // Use the y-axis values +// +// if (i < yAxisValuesList.get(0).size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"pieChartLabels\": [ "); +// +// for (int i = 0; i < xAxisValues.size(); i++) { // Assuming "name" is the x-axis +// jsonmap.append("\"" + xAxisValues.get(i) + "\""); // Use the x-axis values +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("] \n }\n"); +// } +// +// else if (job_type.equalsIgnoreCase("Bubble Chart") || job_type.equalsIgnoreCase("Bubble")) { +// jsonmap.append("{\n \"bubbleChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object xValue = xAxisValues.get(i); +// Object yValue = yAxisValuesList.get(j).get(i); +// int radius = 5 + (i % 3) * 3; // Adjust the radius as needed +// +// jsonmap.append("{ \"x\": " + xValue + ", \"y\": " + yValue + ", \"r\": " + radius + "}"); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"bubbleChartLabels\": [ "); +// +// for (String label : xAxisValues) { +// jsonmap.append("\"" + label + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } else if (job_type.equalsIgnoreCase("Scatter Chart") || job_type.equalsIgnoreCase("Scatter")) { +// jsonmap.append("{\n \"scatterChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object xValue = xAxisValues.get(i); +// Object yValue = yAxisValuesList.get(j).get(i); +// +// jsonmap.append("{ \"x\": " + xValue + ", \"y\": " + yValue + "}"); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"scatterChartLabels\": [ "); +// +// for (String label : xAxisValues) { +// jsonmap.append("\"" + label + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } +// +// else if (job_type.equalsIgnoreCase("Dynamic Chart") || job_type.equalsIgnoreCase("Dynamic")) { +// jsonmap.append("{\n \"dynamicChartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// Object yValue = yAxisValuesList.get(j).get(i); +// jsonmap.append(yValue); +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"dynamicChartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// } + + return new ResponseEntity<>(jsonmap.toString(), HttpStatus.CREATED); + } + + public StringBuilder getJson(StringBuilder jsonmap, List yAxes, List xAxisValues, + List> yAxisValuesList, List parameterValues) { + + jsonmap.append("{\n \"chartData\": [\n"); + + for (int j = 0; j < yAxes.size(); j++) { + String yAxis = yAxes.get(j); + + jsonmap.append("{"); + jsonmap.append("\"data\": ["); + + // --- Y-Axis Data --- + for (int i = 0; i < xAxisValues.size(); i++) { + List list = yAxisValuesList.get(j); + if (list == null || list.isEmpty() || i >= list.size()) { + continue; + } + + Object yValue = list.get(i); + if (yValue instanceof Number) { + jsonmap.append(yValue); + } else if (yValue instanceof String) { + String yStr = ((String) yValue).trim(); + try { + Double num = Double.parseDouble(yStr); + jsonmap.append(num); + } catch (NumberFormatException e) { + continue; // skip non-numeric + } + } else { + continue; // skip invalid + } + + if (i < xAxisValues.size() - 1) { + jsonmap.append(","); + } + } + + // 🧹 Remove trailing comma + int lastIndex = jsonmap.lastIndexOf(","); + if (lastIndex == jsonmap.length() - 1) { + jsonmap.deleteCharAt(lastIndex); + } + + jsonmap.append("],"); + jsonmap.append("\"label\": \"" + yAxis + "\""); + jsonmap.append("}"); + + if (j < yAxes.size() - 1) { + jsonmap.append(","); + } + } + + // --- Chart Labels (X-Axis) --- + jsonmap.append("],\n \"chartLabels\": ["); + for (String xValue : xAxisValues) { + jsonmap.append("\"").append(xValue).append("\","); + } + + if (!xAxisValues.isEmpty()) { + jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); + } + jsonmap.append("],"); + + // --- Parameter Values --- + jsonmap.append("\n \"parameterValues\": ["); + if (parameterValues != null && !parameterValues.isEmpty()) { + for (String param : parameterValues) { + if (param != null && !param.trim().isEmpty()) { + jsonmap.append("\"").append(param.trim()).append("\","); + } + } + // Remove trailing comma + int lastComma = jsonmap.lastIndexOf(","); + if (lastComma == jsonmap.length() - 1) { + jsonmap.deleteCharAt(lastComma); + } + } + jsonmap.append("]\n}"); + + return jsonmap; + } + +// get json data +// public StringBuilder getJson(StringBuilder jsonmap, List yAxes, List xAxisValues, +// List> yAxisValuesList, List parameterValues) { +// jsonmap.append("{\n \"chartData\": [\n"); +// +// for (int j = 0; j < yAxes.size(); j++) { +// String yAxis = yAxes.get(j); +// +// jsonmap.append("{"); +// jsonmap.append("\"data\": ["); +// +// for (int i = 0; i < xAxisValues.size(); i++) { +// List list = yAxisValuesList.get(j); +// if (list.isEmpty()) { +// continue; +// +// } +// Object yValue = list.get(i); +// // ✅ Accept Integer, Long, Double, Float, or numeric Strings +// if (yValue instanceof Number) { +// jsonmap.append(yValue); +// } else if (yValue instanceof String) { +// String yStr = ((String) yValue).trim(); +// try { +// // Parse and append only if numeric +// Double num = Double.parseDouble(yStr); +// jsonmap.append(num); +// } catch (NumberFormatException e) { +// // not numeric — skip +// continue; +// } +// } else { +// continue; // skip non-numeric values +// } +// +// if (i < xAxisValues.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// // 🧹 Remove trailing comma if any +// int lastIndex = jsonmap.lastIndexOf(","); +// if (lastIndex == jsonmap.length() - 1) { +// jsonmap.deleteCharAt(lastIndex); +// } +// +// jsonmap.append("],"); +// jsonmap.append("\"label\": \"" + yAxis + "\""); +// jsonmap.append("}"); +// +// if (j < yAxes.size() - 1) { +// jsonmap.append(","); +// } +// } +// +// jsonmap.append("],\n \"chartLabels\": [ "); +// +// for (String xValue : xAxisValues) { +// jsonmap.append("\"" + xValue + "\","); +// } +// +// if (!xAxisValues.isEmpty()) { +// jsonmap.deleteCharAt(jsonmap.lastIndexOf(",")); +// } +// +// jsonmap.append("] \n }\n"); +// +// return jsonmap; +// } +// + + @GetMapping("/getAllKeys") + public Set getAllKeys(@RequestParam String apiUrl, @RequestParam Integer sureId) { + List> apiData = getAllKeyFromApi(apiUrl, sureId); + return getAllKeys(apiData); + } + + public List> getAllKeyFromApi(String apiUrl, Integer sureId) { + List> apiData = new ArrayList<>(); + + try { + // Make a GET request using the provided URL + ResponseEntity responseEntity = GETWithObject(apiUrl, sureId); + + // Convert the response to a List> + if (responseEntity.getBody() instanceof List) { + // If the response is a list, assume it's a list of maps + apiData = (List>) responseEntity.getBody(); + } else { + // If the response is not a list, assume it's a single map + Map singleMap = new HashMap<>(); + singleMap.put("data", responseEntity.getBody()); + apiData.add(singleMap); + } + + } catch (Exception e) { + log.error(e.getLocalizedMessage()); + } + + return apiData; + } + + private Set getAllKeys(List> apiData) { + Set allKeys = new HashSet<>(); + + for (Map data : apiData) { + allKeys.addAll(data.keySet()); + } + + return allKeys; + } + + public List> getAllDataFromApi(String apiUrl, Integer sureId) { + List> apiData = new ArrayList<>(); + + try { + // Make a GET request using the provided URL + ResponseEntity responseEntity = GETWithObject(apiUrl, sureId); + + // Convert the response to a List> + if (responseEntity.getBody() instanceof List) { + // If the response is a list, assume it's a list of maps + apiData = (List>) responseEntity.getBody(); + } else { + // If the response is not a list, assume it's a single map + Map singleMap = new HashMap<>(); + singleMap.put("data", responseEntity.getBody()); + apiData.add(singleMap); + } + + } catch (Exception e) { + log.error(e.getLocalizedMessage()); + + } + + return apiData; + } + + public ResponseEntity GET1(String get) { + RestTemplate restTemplate = new RestTemplate(); + + ResponseEntity u = restTemplate.getForEntity(get, Object.class); + + return u; + + } + + public ResponseEntity GET(String url, Integer sureid) { + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.ALL)); // accept JSON or XML + headers.setContentType(MediaType.APPLICATION_JSON); + + // 🔹 Add your token here (you can make it dynamic) + String token = getToken(sureid); // helper method (see below) + if (token != null && !token.isEmpty()) { + headers.set("Authorization", "Bearer " + token); + } + + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); + + return response; + } + + public ResponseEntity GETWithObject(String url, Integer sureid) { + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.ALL)); // accept JSON or XML + headers.setContentType(MediaType.APPLICATION_JSON); + + // 🔹 Add your token here (you can make it dynamic) + String token = getToken(sureid); // helper method (see below) + if (token != null && !token.isEmpty()) { + headers.set("Authorization", "Bearer " + token); + } + + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class); + + return response; + } + + private String getToken(Integer sureid) { + Sure_Connect connect = sureService.getbyid(sureid); + String access_token = connect.getAccess_token(); + + return access_token; // optional + } + +} diff --git a/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/DashboardMockController.java b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/DashboardMockController.java new file mode 100644 index 0000000..d0c05ba --- /dev/null +++ b/backend/src/main/java/com/realnet/Dashboard_builder/Controllers/DashboardMockController.java @@ -0,0 +1,49 @@ +package com.realnet.Dashboard_builder.Controllers; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.util.*; + +@RestController +public class DashboardMockController { + + @GetMapping("/api/getDummyDashboardData") + public ResponseEntity>> getDummyDashboardData() { + List> dataList = new ArrayList<>(); + + String[] salesReps = { "Gaurav", "Ravi", "Ankit", "Neha", "Kiran" }; + String[] partners = { "IBM", "Microsoft", "TCS", "Infosys", "Wipro" }; + String[] regions = { "Asia", "Europe", "North America", "South America", "Africa" }; + String[] channels = { "Online", "Retail", "Direct", "Distributor", "Reseller" }; + String[] products = { "Laptops", "Servers", "Networking", "Cloud", "AI" }; + + for (int i = 1; i <= 50; i++) { + Map row = new LinkedHashMap<>(); + + // 🧩 Fixed pattern numeric data + row.put("leadCount", 100 + (i * 10)); + row.put("dealValue", 5000 + (i * 750)); + row.put("conversionRate", (i % 100)); + row.put("activeUsers", 50 + (i * 5)); + row.put("visits", 200 + (i * 15)); + + // 🧠 Repeated pattern text data + row.put("salesRep", salesReps[i % salesReps.length]); + row.put("partner", partners[i % partners.length]); + row.put("region", regions[i % regions.length]); + row.put("channel", channels[i % channels.length]); + row.put("productLine", products[i % products.length]); + + // 📅 Sequential date data + row.put("createdDate", LocalDate.of(2024, (i % 12) + 1, ((i % 28) + 1))); + row.put("lastUpdated", LocalDate.of(2025, ((i + 2) % 12) + 1, ((i + 3) % 28) + 1)); + + dataList.add(row); + } + + return ResponseEntity.ok(dataList); + } +} diff --git a/backend/src/main/java/com/realnet/DataLake/Controllers/Data_lakeController.java b/backend/src/main/java/com/realnet/DataLake/Controllers/Data_lakeController.java index 4d7eaad..8badd64 100644 --- a/backend/src/main/java/com/realnet/DataLake/Controllers/Data_lakeController.java +++ b/backend/src/main/java/com/realnet/DataLake/Controllers/Data_lakeController.java @@ -92,12 +92,12 @@ public class Data_lakeController { } -// json Updtaed +// json Upadted @PutMapping("/Data_lake/json/{id}") public Data_lake update(@PathVariable Integer id) throws JsonProcessingException { - Data_lake update = Service.Updatejson(id); - System.out.println("json update..." + update); + Data_lake update = Service.applyCalculation(id); + System.out.println("clculation applied..." + update); return update; } diff --git a/backend/src/main/java/com/realnet/DataLake/Entity/Data_lake.java b/backend/src/main/java/com/realnet/DataLake/Entity/Data_lake.java index dfe3deb..5e8e34e 100644 --- a/backend/src/main/java/com/realnet/DataLake/Entity/Data_lake.java +++ b/backend/src/main/java/com/realnet/DataLake/Entity/Data_lake.java @@ -42,10 +42,16 @@ public class Data_lake extends Extension { private String url_endpoint; + private Integer ref_datalake_id; + @Lob @Column(columnDefinition = "TEXT") private String calculated_field_json; + @Lob + @Column(columnDefinition = "TEXT") + private String groupby_json; + private Boolean iscalculatedfield; } diff --git a/backend/src/main/java/com/realnet/DataLake/Repository/Data_lakeRepository.java b/backend/src/main/java/com/realnet/DataLake/Repository/Data_lakeRepository.java index 6601dee..2e6d106 100644 --- a/backend/src/main/java/com/realnet/DataLake/Repository/Data_lakeRepository.java +++ b/backend/src/main/java/com/realnet/DataLake/Repository/Data_lakeRepository.java @@ -18,4 +18,7 @@ public interface Data_lakeRepository extends JpaRepository { @Query(value = "select * from data_lake where created_by=?1", nativeQuery = true) Page findAll(Long creayedBy, Pageable page); + + @Query(value = "select * from data_lake where created_by=?1 && ref_datalake_id=?2", nativeQuery = true) + List findAllByRefDatlakeId(Long creayedBy, Integer ref_datalake_id); } \ No newline at end of file diff --git a/backend/src/main/java/com/realnet/DataLake/Services/Data_lakeService.java b/backend/src/main/java/com/realnet/DataLake/Services/Data_lakeService.java index 2fb3dd8..b60cd49 100644 --- a/backend/src/main/java/com/realnet/DataLake/Services/Data_lakeService.java +++ b/backend/src/main/java/com/realnet/DataLake/Services/Data_lakeService.java @@ -2,10 +2,15 @@ package com.realnet.DataLake.Services; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -126,24 +131,61 @@ public class Data_lakeService { old.setIscalculatedfield(data.getIscalculatedfield()); } + if (data.getGroupby_json() != null) { + old.setGroupby_json(data.getGroupby_json()); + + } + + if (data.getRef_datalake_id() != null) { + old.setRef_datalake_id(data.getRef_datalake_id()); + + } + final Data_lake test = Repository.save(old); return test; } - public Data_lake Updatejson(Integer id) throws JsonProcessingException { + public Data_lake applyCalculation(Integer id) throws JsonProcessingException { Data_lake old = Repository.findById(id).get(); String url = old.getUrl(); ResponseEntity response = GETAsString(url); + String rawBody = response.getBody(); + + List datlakes = Repository.findAllByRefDatlakeId(getUser().getUserId(), id); + + datlakes.forEach(lake -> { + try { + Updatejson(lake.getId(), rawBody); + } catch (JsonProcessingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }); + + Data_lake saved = Updatejson(id, rawBody); + + System.out.println(" json updated.."); + return saved; + + } + + public Data_lake Updatejson(Integer id, String rawBody) throws JsonProcessingException { + + Data_lake old = Repository.findById(id).get(); + +// String url = old.getUrl(); +// +// ResponseEntity response = GETAsString(url); +// String rawBody = response.getBody(); // Convert the JSON object (ArrayList, Map, etc.) to a String // Object responseBody = response.getBody(); ObjectMapper mapper = new ObjectMapper(); - String rawBody = response.getBody(); // String jsonString = mapper.writeValueAsString(rawBody); ObjectMapper jsonMapper = new ObjectMapper(); Object responseBody; @@ -176,7 +218,7 @@ public class Data_lakeService { // ✅ Handle calculated fields before batch processing if (Boolean.TRUE.equals(old.getIscalculatedfield()) && old.getCalculated_field_json() != null) { try { - responseBody = applyCalculatedFields(responseBody, old.getCalculated_field_json(), mapper); + responseBody = applyCalculatedFields(responseBody, old.getCalculated_field_json(), mapper, old); System.out.println("Calculated fields applied successfully."); } catch (Exception e) { System.err.println("Failed to process calculated fields: " + e.getMessage()); @@ -204,56 +246,201 @@ public class Data_lakeService { } @SuppressWarnings("unchecked") - private Object applyCalculatedFields(Object responseBody, String calculatedFieldJson, ObjectMapper mapper) - throws JsonProcessingException { + private Object applyCalculatedFields(Object responseBody, String calculatedFieldJson, ObjectMapper mapper, + Data_lake old) throws JsonProcessingException { // Parse the calculated field JSON List> calcFields = mapper.readValue(calculatedFieldJson, List.class); if (!(responseBody instanceof List)) { - // Wrap single object into a list for consistent processing responseBody = Arrays.asList(responseBody); } List> records = (List>) responseBody; - for (Map record : records) { + for (Map calc : calcFields) { + String type = (String) calc.get("type"); + if ("groupby".equalsIgnoreCase(type)) { + // ✅ Handle group-by aggregation + List> groupbyrecords = applyGroupBy(records, calc); + String groupByRecord = mapper.writeValueAsString(groupbyrecords); - for (Map calc : calcFields) { - String fieldName = (String) calc.get("fieldName"); - String operation = (String) calc.get("operation"); - List> components = (List>) calc.get("fieldComponents"); + old.setGroupby_json(groupByRecord); - // Create constant fields separately - for (Map comp : components) { - String subField = (String) comp.get("field"); - Boolean isConstant = comp.get("isConstant") != null && (Boolean) comp.get("isConstant"); - Object constantValue = comp.get("constant"); + } else { + // ✅ Handle calculated / complex operations (as before) + for (Map record : records) { + String fieldName = (String) calc.get("fieldName"); + String operation = (String) calc.get("operation"); + List> components = (List>) calc.get("fieldComponents"); - if (isConstant && subField != null) { - record.put(subField, parseNumberOrString(constantValue)); + // Handle constant fields + if (components != null) { + for (Map comp : components) { + String subField = (String) comp.get("field"); + Boolean isConstant = comp.get("isConstant") != null && (Boolean) comp.get("isConstant"); + Object constantValue = comp.get("constant"); + if (isConstant && subField != null) { + record.put(subField, parseNumberOrString(constantValue)); + } + } } - } - // Collect operand values - List values = new ArrayList<>(); - for (Map comp : components) { - Boolean isConstant = comp.get("isConstant") != null && (Boolean) comp.get("isConstant"); - Object val = isConstant ? comp.get("constant") : record.get(comp.get("field")); - if (val != null) { - values.add(val); + // Handle complex expression + if ("complex".equalsIgnoreCase(operation) && calc.get("complexEquation") != null) { + String equation = (String) calc.get("complexEquation"); + Object result = evaluateComplexExpression(equation, record); + record.put(fieldName, result); + continue; } - } - // Compute final value - Object result = performOperation(values, operation); - record.put(fieldName, result); + // Handle normal arithmetic + List values = new ArrayList<>(); + if (components != null) { + for (Map comp : components) { + Boolean isConstant = comp.get("isConstant") != null && (Boolean) comp.get("isConstant"); + Object val = isConstant ? comp.get("constant") : record.get(comp.get("field")); + if (val != null) { + values.add(val); + } + } + } + + Object result = performOperation(values, operation); + record.put(fieldName, result); + } } } return records; } + @SuppressWarnings("unchecked") + private List> applyGroupBy(List> records, Map groupConfig) { + List groupFields = (List) groupConfig.get("groupFields"); + List> aggregations = (List>) groupConfig.get("aggregations"); + + // Group records by key + Map>> grouped = new LinkedHashMap<>(); + for (Map record : records) { + String key = groupFields.stream().map(f -> String.valueOf(record.getOrDefault(f, ""))) + .collect(Collectors.joining("|")); + grouped.computeIfAbsent(key, k -> new ArrayList<>()).add(record); + } + + // Aggregate results per group + List> result = new ArrayList<>(); + + for (Map.Entry>> entry : grouped.entrySet()) { + Map groupRecord = new LinkedHashMap<>(); + + // Add group fields + String[] parts = entry.getKey().split("\\|"); + for (int i = 0; i < groupFields.size(); i++) { + groupRecord.put(groupFields.get(i), parts[i]); + } + + List> groupRows = entry.getValue(); + + // Apply each aggregation + for (Map agg : aggregations) { + String field = (String) agg.get("field"); + String operation = ((String) agg.get("operation")).toLowerCase(); + List numericValues = groupRows.stream().map(r -> toDouble(r.get(field))) + .filter(v -> !Double.isNaN(v)).collect(Collectors.toList()); + + Object aggResult; + switch (operation) { + case "count": + aggResult = groupRows.size(); + break; + case "sum": + aggResult = numericValues.stream().mapToDouble(Double::doubleValue).sum(); + break; + case "average": + aggResult = numericValues.isEmpty() ? 0.0 + : numericValues.stream().mapToDouble(Double::doubleValue).average().orElse(0.0); + break; + case "minimum": + aggResult = numericValues.isEmpty() ? null + : numericValues.stream().mapToDouble(Double::doubleValue).min().orElse(0.0); + break; + case "maximum": + aggResult = numericValues.isEmpty() ? null + : numericValues.stream().mapToDouble(Double::doubleValue).max().orElse(0.0); + break; + case "median": + aggResult = calculateMedian(numericValues); + break; + case "mode": + aggResult = calculateMode(numericValues); + break; + case "standard deviation": + aggResult = calculateStdDev(numericValues); + break; + default: + aggResult = null; + } + + groupRecord.put(field + "_" + operation, aggResult); + } + + result.add(groupRecord); + } + + return result; + } + + // --- Statistical helpers --- + + private Double calculateMedian(List values) { + if (values == null || values.isEmpty()) + return null; + List sorted = new ArrayList<>(values); + Collections.sort(sorted); + int n = sorted.size(); + if (n % 2 == 1) { + return sorted.get(n / 2); + } else { + return (sorted.get(n / 2 - 1) + sorted.get(n / 2)) / 2.0; + } + } + + private Double calculateMode(List values) { + if (values == null || values.isEmpty()) + return null; + Map freq = values.stream().collect(Collectors.groupingBy(v -> v, Collectors.counting())); + return freq.entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey).orElse(null); + } + + private Double calculateStdDev(List values) { + if (values == null || values.isEmpty()) + return null; + double mean = values.stream().mapToDouble(Double::doubleValue).average().orElse(0.0); + double variance = values.stream().mapToDouble(v -> Math.pow(v - mean, 2)).average().orElse(0.0); + return Math.sqrt(variance); + } + + private Object evaluateComplexExpression(String expression, Map record) { + try { + // Replace field names with values dynamically + for (Map.Entry e : record.entrySet()) { + String field = e.getKey(); + Object val = e.getValue(); + expression = expression.replaceAll("\\b" + field + "\\b", String.valueOf(val != null ? val : 0)); + } + + // Evaluate using ScriptEngine (works on Java 1.8) + javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName("JavaScript"); + Object result = engine.eval(expression); + return result; + } catch (Exception e) { + System.err.println("Complex expression error: " + e.getMessage()); + return null; + } + } + +// perform normal operation private Object performOperation(List values, String operation) { if (values.isEmpty()) return null; @@ -301,6 +488,60 @@ public class Data_lakeService { } } + /** + * ✅ Evaluates complex equations using JavaScript engine Supports math + * operations, parentheses, and string concatenation. + */ + private Object evaluateComplexEquation(String expression, Map record, + List> fieldComponents) { + + if (expression == null || expression.trim().isEmpty()) + return null; + + ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript"); + + try { + // 🔹 Replace constants + if (fieldComponents != null) { + for (Map comp : fieldComponents) { + String field = (String) comp.get("field"); + Object constant = comp.get("constant"); + Boolean isConstant = comp.get("isConstant") != null && (Boolean) comp.get("isConstant"); + + if (isConstant && constant != null) { + String constVal = constant.toString(); + expression = expression.replaceAll("\\b" + field + "\\b", constVal); + } + } + } + + // 🔹 Replace field values from record + for (Map.Entry entry : record.entrySet()) { + String key = entry.getKey(); + Object val = entry.getValue(); + if (val != null) { + String safeValue = val.toString(); + + // If it's a string containing letters, wrap it in quotes for JS + if (!safeValue.matches("^-?\\d+(\\.\\d+)?$")) { + safeValue = "'" + safeValue.replace("'", "\\'") + "'"; + } + + expression = expression.replaceAll("\\b" + key + "\\b", safeValue); + } + } + + // Evaluate the expression safely + Object result = engine.eval(expression); + System.out.println(" exoression is : " + expression + " and " + result); + return result; + + } catch (Exception e) { + System.err.println("❌ Error evaluating complex equation: " + e.getMessage()); + return null; + } + } + private double toDouble(Object val) { if (val == null) return 0.0;