From b0579849649961b5fff56940e47edefaf3d15c11 Mon Sep 17 00:00:00 2001 From: nisha Date: Fri, 25 Oct 2024 01:53:50 +0530 Subject: [PATCH] Updated code for pdf correction --- .../gepafin/tendermanagement/dao/PdfDao.java | 399 +++++++----------- .../gepafin/tendermanagement/util/Utils.java | 54 +++ 2 files changed, 205 insertions(+), 248 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 1e2d938e..efdc3798 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -10,11 +10,15 @@ import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.*; import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Validator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; //import com.itextpdf.layout.element. @@ -37,6 +41,7 @@ public class PdfDao { @Autowired private Validator validator; + public static final Logger log = LoggerFactory.getLogger(PdfDao.class); public byte[] generatePdf(HttpServletRequest request,Long applicationId) { try { @@ -79,16 +84,7 @@ public class PdfDao { for(FormApplicationResponse formApplicationResponse: applicationGetResponseBean.getForm()) { document.add(new Paragraph(formApplicationResponse.getLabel(),sectionFont)); document.add(new Paragraph(" ")); // Add line break - List fieldLabelValuePairRequests = getFormFieldsToLabels(formApplicationResponse); - for (FieldLabelValuePairRequest pair : fieldLabelValuePairRequests) { - String label = pair.getLabel(); - Object value = pair.getValue(); - Integer pages=0; - pages=addLabelValuePair(writer,document, label, value, labelFont,valueFont,call.getName(),pages); - if(pages !=0 ){ -// pageEvent.setTotalPages(writer.getPageNumber()); - } - } + List fieldLabelValuePairRequests = getFormFieldsToLabels(formApplicationResponse,writer,document); addColoredLines(writer,document,greenColor); document.add(new Paragraph(" ")); // Add line break } @@ -164,15 +160,6 @@ public class PdfDao { addColoredLines(writer,document,greenColor); -// System.out.println(writer.getPageSize()); -// System.out.println(document.getPageSize()); -// System.out.println(document.getPageNumber()); -// System.out.println(writer.getPageNumber()); -// document.setPageCount(100); -// document.setPageCount(writer.getPageNumber()); -// System.out.println(document.getPageNumber()); - - // Close the document document.close(); // Convert to byte array for response @@ -185,12 +172,13 @@ public class PdfDao { return null; } - private Integer addLabelValuePair(PdfWriter writer,Document document, String label, Object value, Font labelFont,Font valueFont,String title,Integer totalPages) throws DocumentException { + private void addLabelValuePair(PdfWriter writer,Document document, String label, Object value, Font labelFont,Font valueFont,ContentResponseBean contentResponseBean) throws DocumentException { // Add label + Map stateFieldMap= new HashMap<>(); + Paragraph labelParagraph = new Paragraph(label, labelFont); document.add(labelParagraph); float leftMargin = 20f; - PdfContentByte canvas = writer.getDirectContent(); // Setting the color and width of the line @@ -204,8 +192,6 @@ public class PdfDao { if (yPos <= 140) { // If xEnd is less than or equal to 200, generate a new page - - totalPages++; document.newPage(); } // Add a gap between the label and value document.add(new Paragraph(" ")); // Adding an empty paragraph for spacing @@ -235,44 +221,13 @@ public class PdfDao { // Finally, add the table to the document document.add(valueTable); - } else { - boolean containsThreeValues = false; // Variable to track if any map contains three keys - List> dataList = (List>) value; // Cast Object to List of Maps - for (Map entry : dataList) { - if (entry.size() == 3) { // Check if the current map has three keys - containsThreeValues = true; // If found, set the variable to true - break; // No need to check further, exit loop - } - } - List> extractedData = new ArrayList<>(); // To hold extracted data - for (Map entry : dataList) { - Map extractedMap = new HashMap<>(); // To hold the current extracted row of data + } + else if (!list.isEmpty() && list.get(0) instanceof Map) { + Object object = value; + String stringvalue = Utils.convertToString(object); + List> fieldValueList = Utils.convertJsonStringIntoJsonList(stringvalue); - List keys = new ArrayList<>(entry.keySet()); // Get all keys in the current map - - // Handle based on the number of keys in the map - if (Boolean.FALSE.equals(containsThreeValues) && (keys.size() == 2 || keys.size()<2)) { - // Treat the first key as the "key" and second key as the "value" - String heading = (String) entry.get(keys.get(0)); // Get value of first key - String value1 = (String) entry.get(keys.get(1)); // Get value of second key - extractedMap.put(heading,value1); // Store the first key's value as "heading" - } if (Boolean.TRUE.equals(containsThreeValues) ) { - String amount=""; - // Treat the first as number, second as description, third as amount - if(keys.size()==3){ - amount = (String) entry.get(keys.get(2)); // Third key's value - } - String number = (String) entry.get(keys.get(0)); // First key's value - String description = (String) entry.get(keys.get(1)); // Second key's value - - // Store the combined result as a value in the map, with a suitable key - String combinedValue = number + "; " + description + "; " + amount; // Concatenate them as a single value - extractedMap.put("combined", combinedValue); // Store as a single entry, key as "combined" - } - - extractedData.add(extractedMap); // Add each extracted map to the list - } - document=createPdfTable(extractedData,document); + document = createPdfTable(fieldValueList, document, contentResponseBean); } } else { @@ -289,150 +244,89 @@ public class PdfDao { } document.add(new Paragraph("\n")); // Add line break after each value - return totalPages; } - private Document createPdfTable(List> extractedData,Document document) throws DocumentException { - // Create a PdfPTable with 2 columns - PdfPTable table = new PdfPTable(2); // Initial assumption for 2 columns + private Document createPdfTable(List> extractedData, Document document, ContentResponseBean contentResponseBean) throws DocumentException { + // Create a PdfPTable with dynamic column count based on stateFieldMap size + Map stateFieldMap = new HashMap<>(); + + // Populate stateFieldMap from contentResponseBean settings + contentResponseBean.getSettings().stream() + .filter(setting -> "table_columns".equals(setting.getName())) // Check for "table_columns" + .map(SettingResponseBean::getValue) + .filter(Objects::nonNull) // Ensure value is not null + .filter(settingValue -> settingValue instanceof Map) // Ensure value is a Map + .map(settingValue -> (Map) settingValue) // Cast to Map + .map(valueMap -> (List>) valueMap.get("stateFieldData")) // Extract stateFieldData list + .filter(Objects::nonNull) // Ensure stateFieldData is not null + .flatMap(List::stream) // Flatten the list of field data maps + .forEach(fieldData -> { + String fieldName = (String) fieldData.get("name"); // Get the name field + String fieldDataValue = (String) fieldData.get("label"); // Get the predefined field + + if (fieldName != null && fieldDataValue != null) { + stateFieldMap.put(fieldName, fieldDataValue); + } + }); + + PdfPTable table = new PdfPTable(stateFieldMap.size()); // Number of columns equals the number of map entries table.setWidthPercentage(100); // Set table width to 100% table.setTableEvent(new RoundedBorderEvent()); + Font textFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new BaseColor(105, 105, 105)); // Gray text - boolean combinedHeaderAdded = false; // Flag to track if headers for combined have been added - float rowHeight = 50f; // Example row height, adjust as necessary + float rowHeight = 20f; // Example row height float maxTableHeight = 700f; // Maximum height of the table before a page break - float[] columnWidths = {0.7f, 0.3f}; - table.setWidths(columnWidths); + boolean headersAdded = false; // Flag to check if headers have been added + // Iterate through extracted data to populate the table + for (Map row : extractedData) { + // Add headers once + if (!headersAdded) { + for (Map.Entry stateField : stateFieldMap.entrySet()) { + String headerValue = stateField.getValue(); // Header text -// Add table header -// Populate the table with extracted data and style rows - for (Map row : extractedData) { - for (Map.Entry entry : row.entrySet()) { - String key = entry.getKey(); // This will give you the key - String value = entry.getValue(); // This will give you the value + PdfPCell headerCell = new PdfPCell(new Phrase(headerValue)); // Create a new PdfPCell for the header + headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align + headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE); + headerCell.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - // Check if the current entry is for the combined section - if ("combined".equals(key)) { - // Ensure the combined header is added only once - if (!combinedHeaderAdded) { - // Create a new table for combined entries - table = new PdfPTable(3); // 3 columns for combined entries - - PdfPCell headerCell1 = new PdfPCell(new Phrase("Number")); - headerCell1.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align - headerCell1.setVerticalAlignment(Element.ALIGN_MIDDLE); - headerCell1.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - table.addCell(headerCell1); - - PdfPCell headerCell2 = new PdfPCell(new Phrase("Details")); - headerCell2.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align - headerCell2.setVerticalAlignment(Element.ALIGN_MIDDLE); - headerCell2.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - table.addCell(headerCell2); - - PdfPCell headerCell3 = new PdfPCell(new Phrase("Amount")); - headerCell3.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align - headerCell3.setVerticalAlignment(Element.ALIGN_MIDDLE); - headerCell3.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - table.addCell(headerCell3); - - combinedHeaderAdded = true; // Mark header as added - } - - // Split the value for "combined" into separate parts - String[] combinedValues = value.split("; "); - - // Check if we have 3 parts (number, description, amount) - String number = combinedValues[0]; // 1st part (number) - String description = combinedValues[1]; // 2nd part (description) - String amount = ""; - if (combinedValues.length == 3) { - amount = combinedValues[2]; // 3rd part (amount) - } - - // Create PDF cells using the split values - PdfPCell cellNumber = new PdfPCell(new Phrase(number, textFont)); // Cell for number - PdfPCell cellDescription = new PdfPCell(new Phrase(description, textFont)); // Cell for description - PdfPCell cellAmount = new PdfPCell(new Phrase(amount, textFont)); // Cell for amount - - // Set row background color for combined values - cellNumber.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for combined rows - cellDescription.setBackgroundColor(new BaseColor(239, 243, 248)); - cellAmount.setBackgroundColor(new BaseColor(239, 243, 248)); - - // Set cell height and add rounded borders -// cellNumber.setFixedHeight(rowHeight); -// cellDescription.setFixedHeight(rowHeight); -// cellAmount.setFixedHeight(rowHeight); - - cellNumber.setMinimumHeight(20f); // Set minimum height for better appearance - cellDescription.setMinimumHeight(20f); // Set minimum height for better appearance - cellAmount.setMinimumHeight(20f); // Set minimum height for better appearance - - cellNumber.setPadding(7f); - cellDescription.setPadding(7f); - cellAmount.setPadding(7f); - - // Add the cells to the table only once - table.addCell(cellNumber); - table.addCell(cellDescription); - table.addCell(cellAmount); - - - } else { - if (!combinedHeaderAdded) { - // Create a new table for combined entries - table= new PdfPTable(2); // 3 columns for combined entries - table.setWidthPercentage(100); - - PdfPCell headerCell1 = new PdfPCell(new Phrase("Details")); - headerCell1.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align - headerCell1.setVerticalAlignment(Element.ALIGN_MIDDLE); - headerCell1.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - table.addCell(headerCell1); - - PdfPCell headerCell2 = new PdfPCell(new Phrase("Amount")); - headerCell2.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align - headerCell2.setVerticalAlignment(Element.ALIGN_MIDDLE); - headerCell2.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - table.addCell(headerCell2); - combinedHeaderAdded=true; -} - // Add cells for regular key-value pairs without headers - PdfPCell cellKey = new PdfPCell(new Phrase(key, textFont)); - PdfPCell cellValue = new PdfPCell(new Phrase(value, textFont)); - - // Set background color for both cells - cellKey.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for other rows - cellValue.setBackgroundColor(new BaseColor(239, 243, 248)); - - cellKey.setPadding(7f); - cellValue.setPadding(7f); - // Set cell height and add rounded borders - cellKey.setFixedHeight(rowHeight); - cellValue.setFixedHeight(rowHeight); - - // Add the cells to the table - table.addCell(cellKey); - table.addCell(cellValue); + table.addCell(headerCell); // Add the header cell to the table } - if (table.getTotalHeight() + rowHeight > maxTableHeight) { - // Start a new page if needed - document.add(table); - table = new PdfPTable(2); // Reset table for new page - table.setWidthPercentage(100); // Reset width percentage - combinedHeaderAdded = false; // Reset header flag + headersAdded = true; // Prevent headers from being added again + } + + // Add data rows matching stateFieldMap keys + for (Map.Entry stateField : stateFieldMap.entrySet()) { + String stateKey = stateField.getKey(); // Get the key from stateFieldMap + if (row.containsKey(stateKey)) { // If row contains the stateKey + Object value = row.get(stateKey); // Get the value from the row map + + PdfPCell dynamicCell = new PdfPCell(new Phrase(value != null ? value.toString() : "", textFont)); + dynamicCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell + dynamicCell.setMinimumHeight(rowHeight); + dynamicCell.setPadding(7f); + + table.addCell(dynamicCell); // Add the dynamically created cell to the table } } + + // Check if adding another row would exceed max height + if (table.getTotalHeight() + rowHeight > maxTableHeight) { + document.add(table); // Add the table to the document + document.newPage(); // Start a new page + table = new PdfPTable(stateFieldMap.size()); // Create a new table for the new page + table.setWidthPercentage(100); // Reset table width + + headersAdded = false; // Reset the header flag for the new page + } } - document.add(table); // Add the last table before returning + // Add the last table to the document + document.add(table); - // Check if adding a new row would exceed the maximum height -// Return the populated table return document; } + public static class RoundedBorderEvent implements PdfPTableEvent { @Override public void tableLayout(PdfPTable table, float[][] widths, float[] heights, @@ -453,89 +347,98 @@ public class PdfDao { canvas.stroke(); } } - public List getFormFieldsToLabels(FormApplicationResponse responseBean) { + public List getFormFieldsToLabels(FormApplicationResponse responseBean,PdfWriter writer,Document document) { List labelValuePairs = new ArrayList<>(); - // Iterate through each form in the application response - - List formFields = responseBean.getFormFields(); - List contents = responseBean.getContent(); - - // Iterate through each formField in the current form - for (ApplicationFormFieldResponseBean formField : formFields) { - String fieldId = formField.getFieldId(); - Object fieldValue = formField.getFieldValue(); - - // Find the content in the form that matches the fieldId - Optional matchingContent = contents.stream() - .filter(content -> content.getId().equals(fieldId)) - .findFirst(); + Font labelFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,new BaseColor(113,121,126)); // Light grey); + Font valueFont=FontFactory.getFont(FontFactory.HELVETICA_BOLD,10,new BaseColor(178, 190, 181)); - // If the content with the matching fieldId is found, create a label-value pair - if (matchingContent.isPresent()) { - String name = matchingContent.get().getName(); - ContentResponseBean content = matchingContent.get(); + // Get form fields and contents from the response + List formFields = responseBean.getFormFields(); + List contents = responseBean.getContent(); - // Find the setting where the name is "label" - String contentLabel = content.getSettings().stream() - .filter(setting -> "label".equals(setting.getName())) // Filter settings by name - .map(SettingResponseBean::getValue) // Extract the value from the matching setting - .map(Object::toString) // Convert the value to a string - .findFirst() // Get the first matching value - .orElse(null); // If no match is found, set label to null + // Iterate through each content in the response + for (ContentResponseBean content : contents) { + String contentId = content.getId(); // Content ID + String label = content.getLabel(); // Content label + String name = content.getName(); // Content name + Object fieldValue = null; - if (name.equals("fileupload")) { + String contentLabel = content.getSettings().stream() + .filter(setting -> "label".equals(setting.getName())) // Filter settings by name + .map(SettingResponseBean::getValue) // Extract the value from the matching setting + .map(Object::toString) // Convert the value to a string + .findFirst() // Get the first matching value + .orElse(null); // If no match is found, set label to null + // Find the form field in the response that matches the contentId + Optional matchingFormField = formFields.stream() + .filter(formField -> formField.getFieldId().equals(contentId)) + .findFirst(); -// Step 1: Check if fieldValue is an instance of List - if (fieldValue instanceof List && ((List) fieldValue).stream().allMatch(item -> item instanceof DocumentResponseBean)) { - // Step 2: Safely cast to List - List documentList = (List) fieldValue; + // If a matching form field is found, process its value + if (matchingFormField.isPresent()) { + ApplicationFormFieldResponseBean formField = matchingFormField.get(); + fieldValue = formField.getFieldValue(); - // Step 3: Extract names from the document list - List names = documentList.stream() - .map(DocumentResponseBean::getName) // Extract the name from each DocumentResponseBean - .collect(Collectors.toList()); + // If fieldValue is null, set it to an empty string + if (fieldValue == null) { + fieldValue = ""; + } - fieldValue=names; - } + // Process 'fileupload' and 'checkboxes' cases as in the original logic + if (name.equals("fileupload")) { + if (fieldValue instanceof List && ((List) fieldValue).stream().allMatch(item -> item instanceof DocumentResponseBean)) { + List documentList = (List) fieldValue; + List names = documentList.stream() + .map(DocumentResponseBean::getName) + .collect(Collectors.toList()); + fieldValue = names; } - if(name.equals("checkboxes")) { - List check = (List) fieldValue; - List settingResponseBeans = matchingContent.get().getSettings(); - for (SettingResponseBean settingResponseBean : settingResponseBeans) { - // Initialize a list to hold matched labels for each SettingResponseBean - List matchedLabels = new ArrayList<>(); - if (settingResponseBean.getValue() instanceof List) { + } else if (name.equals("checkboxes")) { + List check = (List) fieldValue; + List settingResponseBeans = content.getSettings(); + List matchedLabels = new ArrayList<>(); - List valueList = (List) settingResponseBean.getValue(); - if (!valueList.isEmpty() && valueList.get(0) instanceof Map) { - // Cast to List> - List> options = (List>) valueList; - for (Map field : options) { - for (String val : check) { - String name1=field.get("name"); - if (val.equals(name1)) { // Check if the key exists in the current field map - String label = field.get("label"); // Extract the label - if (field != null) { // Check if the value is not null - matchedLabels.add(label); // Add the value to the matchedValues list - } - } + for (SettingResponseBean settingResponseBean : settingResponseBeans) { + if (settingResponseBean.getValue() instanceof List) { + List> options = (List>) settingResponseBean.getValue(); + + for (Map field : options) { + for (String val : check) { + String name1 = field.get("name"); + if (val.equals(name1)) { + String labelVal = field.get("label"); + if (labelVal != null) { + matchedLabels.add(labelVal); } } - fieldValue = matchedLabels; } } } } - // Add the label-value pair to the list - fieldValue = findLabelInOptions(matchingContent.get().getSettings(), fieldValue); - labelValuePairs.add(new FieldLabelValuePairRequest(contentLabel, fieldValue)); + fieldValue = matchedLabels; } + + // Further processing of field value (e.g., finding labels in options) + fieldValue = findLabelInOptions(content.getSettings(), fieldValue); + } else { + // If no matching form field is found, store contentId with an empty string + fieldValue = ""; } + try { + addLabelValuePair(writer,document, contentLabel, fieldValue, labelFont,valueFont,content); + } catch (DocumentException e) { + log.error("Error checking object: " + e.getMessage(), e); + + } +// } labelValuePairs.add(new FieldLabelValuePairRequest(contentLabel, fieldValue)); + } + return labelValuePairs; } + public static Object findLabelInOptions(List settings, Object valueToFind) { ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index bc8aff6c..5da90a21 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -31,6 +31,8 @@ import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundExcep import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException; import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException; +import static org.apache.commons.lang3.StringUtils.isEmpty; + public class Utils { @@ -315,4 +317,56 @@ public class Utils { } return content.trim().replace(" ", "_"); } + public static List> convertJsonStringIntoJsonList(String jsonString) { + try { + if(isEmpty(jsonString)) + { + return new ArrayList<>(); + } + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true); + return mapper.readValue(jsonString, List.class); + } catch (Exception e) { + log.error(e.getMessage()); + } + return null; + } + public static String convertToString(Object input) { + if (input == null) { + return "null"; // Return string "null" for null input + } + + if (input instanceof String) { + return (String) input; // Return the string directly if input is a string + } + + if (input instanceof Collection) { + // Handle collections (List, Set, etc.) + return convertCollectionToString((Collection) input); + } + + if (input instanceof Map) { + // Handle maps + return convertMapToString((Map) input); + } + + // For other types (like Integer, Boolean, etc.), use toString() + return input.toString(); + } + + private static String convertCollectionToString(Collection collection) { + try { + return mapper.writeValueAsString(collection); // Convert the collection to a JSON string + } catch (JsonProcessingException e) { + throw new RuntimeException("Error converting collection to string", e); + } + } + + private static String convertMapToString(Map map) { + try { + return mapper.writeValueAsString(map); // Convert the map to a JSON string + } catch (JsonProcessingException e) { + throw new RuntimeException("Error converting map to string", e); + } + } }