diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ExcelTemplateReportGenerationService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ExcelTemplateReportGenerationService.java index 0e0a947..5a603cd 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ExcelTemplateReportGenerationService.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ExcelTemplateReportGenerationService.java @@ -1,5 +1,48 @@ package com.iqser.red.service.redaction.report.v1.server.service; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_NAME_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.EXCERPT_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_NAME_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_GER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_GER_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PARAGRAPH_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_REASON_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PAGE_PLACEHOLDER; +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_PLACEHOLDER; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Pattern; + +import javax.imageio.ImageIO; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Picture; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.stereotype.Service; + import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DossierAttributeConfig; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttribute; @@ -10,29 +53,10 @@ import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributes import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient; import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder; import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry; + import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.util.Dimension2DDouble; -import org.apache.poi.util.Units; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.stereotype.Service; - -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.time.OffsetDateTime; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.regex.Pattern; - -import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.*; - -import javax.imageio.ImageIO; @Slf4j @Service @@ -240,30 +264,29 @@ public class ExcelTemplateReportGenerationService { if (cell.getStringCellValue().contains(imagePlaceholder.getPlaceholder())) { try (ByteArrayInputStream is = new ByteArrayInputStream(imagePlaceholder.getImage())) { - ByteArrayInputStream scaledImage = getScaledImage(is, sheet.getColumnWidthInPixels(cell.getColumnIndex()), convertPointsToPixel(cell.getRow().getHeightInPoints())); +// ByteArrayInputStream scaledImage = getScaledImage(is, PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())), PixelUtil.heightUnits2Pixel(cell.getRow().getHeight())); +// is.reset(); + + double factor = calculateScale(is, PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())), PixelUtil.heightUnits2Pixel(cell.getRow().getHeight())); is.reset(); - int pictureIdx = workbook.addPicture(scaledImage, XSSFWorkbook.PICTURE_TYPE_JPEG); -// scaledImage.reset(); + int pictureIdx = workbook.addPicture(is, XSSFWorkbook.PICTURE_TYPE_JPEG); + is.reset(); //Returns an object that handles instantiating concrete classes CreationHelper helper = workbook.getCreationHelper(); - //Creates the top-level drawing patriarch. //Create an anchor that is attached to the worksheet ClientAnchor anchor = helper.createClientAnchor(); -// anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE); + anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); anchor.setCol1(cell.getColumnIndex()); anchor.setRow1(cell.getRowIndex()); - anchor.setCol2(cell.getColumnIndex() + 1); - anchor.setRow2(cell.getRowIndex() + 1); + //Creates the top-level drawing patriarch. Drawing drawing = sheet.createDrawingPatriarch(); - drawing.createPicture(anchor, pictureIdx); - //sheet.setColumnWidth(cell.getColumnIndex(), (int) dim.getWidth()); - -// cell.getRow().setHeight((short) dim.getHeight()); + Picture picture = drawing.createPicture(anchor, pictureIdx); + picture.resize(factor); cell.setCellValue(""); } @@ -273,138 +296,26 @@ public class ExcelTemplateReportGenerationService { } - private float convertPointsToPixel(float points) { - return points/0.75f; - } + private double calculateScale(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException { + BufferedImage img = ImageIO.read(imageByteArrayInputStream); + double imageWidth = img.getWidth(); + double imageHeight = img.getHeight(); - private ByteArrayInputStream getScaledImage(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException { - BufferedImage image = ImageIO.read(imageByteArrayInputStream); - - double imageWidth = image.getWidth(); - double imageHeight = image.getHeight(); - - double imageWidthScaleFactor; - double imageHeightScaleFactor; - - double imageRatio = imageWidth/imageHeight; - -// if(cellRatio <= 1 && imageRatio <=1) { -// // cell and image are landscape -// -// -// } else if(cellRatio <= 1 && imageRatio <=1) { -// // cell and image are portrait -// -// } else if(cellRatio <= 1 && imageRatio <=1) { -// // cell is landscape and image is portrait -// -// } else if(cellRatio <= 1 && imageRatio <=1) { -// // cell is portrait and image is landscape -// -// } - - AffineTransform at = new AffineTransform(); - - imageWidthScaleFactor = cellWidth / imageWidth; - imageHeightScaleFactor = cellHeight / imageHeight; - - if(imageWidthScaleFactor <= 1 && imageHeightScaleFactor > 1) { - imageWidth = imageWidth * imageWidthScaleFactor; - imageHeight = imageHeight * imageWidthScaleFactor; - - at.scale(imageWidthScaleFactor, imageRatio); - - } else if(imageWidthScaleFactor > 1 && imageHeightScaleFactor <= 1) { - imageHeight = imageHeight * imageHeightScaleFactor; - imageWidth = imageWidth * imageHeightScaleFactor; - - at.scale(imageHeightScaleFactor, imageHeightScaleFactor/imageWidthScaleFactor); - - } else if(imageWidthScaleFactor <= 1 && imageHeightScaleFactor <= 1) { - if(imageWidthScaleFactor <= imageHeightScaleFactor) { - imageWidth = imageWidth * imageWidthScaleFactor; - imageHeight = imageHeight * imageWidthScaleFactor; - - at.scale(imageWidthScaleFactor, imageWidthScaleFactor/imageHeightScaleFactor); - } else { - imageHeight = imageHeight * imageHeightScaleFactor; - imageWidth = imageWidth * imageHeightScaleFactor; - - at.scale(imageHeightScaleFactor, imageHeightScaleFactor/imageWidthScaleFactor); - } + double widthFactor = (double) cellWidth/ imageWidth; + double heightFactor = (double) cellHeight/ imageHeight; + if (imageWidth < cellWidth && imageHeight < cellHeight) { + return 1; + } else if (cellWidth > cellHeight) { + return heightFactor; } else { - at.scale(1/imageHeightScaleFactor, 1/imageWidthScaleFactor); + return widthFactor; } -// AffineTransform at = new AffineTransform(); -// at.scale(1/imageWidthScaleFactor, 1/imageHeightScaleFactor); - AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); - BufferedImage scaledImage = new BufferedImage((int) imageWidth, (int) imageHeight, image.getType()); - scaledImage = scaleOp.filter(image, scaledImage); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - ImageIO.write(scaledImage, "jpeg", os); - //os.reset(); - return new ByteArrayInputStream(os.toByteArray()); } - -// private ByteArrayInputStream getScaledImage(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException { -// BufferedImage image = ImageIO.read(imageByteArrayInputStream); -// -// double imageWidth = image.getWidth(); -// -// double imageHeight = image.getHeight(); -// -// double cellRatio = cellWidth/cellHeight; -// double imageRatio = imageWidth/imageHeight; -// -// boolean scaleWidth = imageWidth > cellWidth; -// boolean scaleHeight = imageHeight > cellHeight; -// -// double imageWidthScaleFactor; -// double imageHeightScaleFactor; -// -// if (scaleWidth && scaleHeight) { -// // image width and height is greater than cell -// if (imageRatio < cellRatio) { -// // scale width -// imageWidthScaleFactor = cellWidth / imageWidth; -// imageHeightScaleFactor = imageWidthScaleFactor / imageRatio; -// } else { -// // scale height -// imageHeightScaleFactor = cellHeight / imageHeight; -// imageWidthScaleFactor = imageHeightScaleFactor * imageRatio; -// } -// } else if (scaleWidth) { -// // only image width is greater than cell -// imageWidthScaleFactor = cellWidth / imageWidth; -// imageHeightScaleFactor = imageWidthScaleFactor / imageRatio; -// } else if (scaleHeight) { -// // only image height is greater than cell -// imageHeightScaleFactor = cellHeight / imageHeight; -// imageWidthScaleFactor = imageHeightScaleFactor * imageRatio; -// } else { -// // nothing to do, image fits in cell -// imageWidthScaleFactor = 1; -// imageHeightScaleFactor = 1; -// } -// -// AffineTransform at = new AffineTransform(); -// at.scale(imageWidthScaleFactor, imageHeightScaleFactor); -// AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); -// BufferedImage scaledImage = new BufferedImage((int) (imageWidth * imageWidthScaleFactor), (int) (imageHeight * imageHeightScaleFactor), image.getType()); -// scaledImage = scaleOp.filter(image, scaledImage); -// -// ByteArrayOutputStream os = new ByteArrayOutputStream(); -// ImageIO.write(scaledImage, "jpeg", os); -// //os.reset(); -// return new ByteArrayInputStream(os.toByteArray()); -// } -// private String getPlaceholderValue(String placeholder, Dossier project, FileModel fileStatus, Map fileAttributePlaceholders, Map dossierAttributesPlaceholders) { diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PixelUtil.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PixelUtil.java new file mode 100644 index 0000000..538b471 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PixelUtil.java @@ -0,0 +1,29 @@ +package com.iqser.red.service.redaction.report.v1.server.service; + +public class PixelUtil { + + public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256; + public static final short EXCEL_ROW_HEIGHT_FACTOR = 20; + public static final int UNIT_OFFSET_LENGTH = 7; + public static final int[] UNIT_OFFSET_MAP = new int[] { 0, 36, 73, 109, 146, 182, 219 }; + + public static short pixel2WidthUnits(int pxs) { + short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR * (pxs / UNIT_OFFSET_LENGTH)); + widthUnits += UNIT_OFFSET_MAP[pxs % UNIT_OFFSET_LENGTH]; + return widthUnits; + } + + public static int widthUnits2Pixel(short widthUnits) { + int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR) * UNIT_OFFSET_LENGTH; + int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR; + pixels += Math.floor((float) offsetWidthUnits / ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH)); + return pixels; + } + + public static int heightUnits2Pixel(short heightUnits) { + int pixels = heightUnits / EXCEL_ROW_HEIGHT_FACTOR; + int offsetWidthUnits = heightUnits % EXCEL_ROW_HEIGHT_FACTOR; + pixels += Math.floor((float) offsetWidthUnits / ((float) EXCEL_ROW_HEIGHT_FACTOR / UNIT_OFFSET_LENGTH)); + return pixels; + } +} \ No newline at end of file diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java index 0e5617c..05e41a5 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java @@ -12,7 +12,6 @@ import java.util.Arrays; import java.util.Base64; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; import org.apache.commons.io.IOUtils; @@ -34,12 +33,10 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.Re import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttribute; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttributeType; -import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttribute; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttributeConfig; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttributeType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.legalbasis.LegalBasis; -import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.legalbasis.LegalBasisMapping; import com.iqser.red.service.redaction.report.v1.api.model.ReportType; import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesClient; import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesConfigClient; @@ -412,11 +409,11 @@ public class RedactionReportIntegrationTest { public void testIuclidReport() { String dossierTemplateId = "dossierTemplateId"; - ClassPathResource redactionLogResource = new ClassPathResource("files/redactionLog.json"); + ClassPathResource redactionLogResource = new ClassPathResource("files/S11RedactionLog.json"); RedactionLog redactionLog = objectMapper.readValue(redactionLogResource.getInputStream(), RedactionLog.class); - ClassPathResource legalBasisMappingResource = new ClassPathResource("files/legalBasisMapping.json"); + ClassPathResource legalBasisMappingResource = new ClassPathResource("files/S1116LegalBasis.json"); List legalBasisMapping = objectMapper.readValue(legalBasisMappingResource.getInputStream(), new TypeReference<>() { }); @@ -433,7 +430,7 @@ public class RedactionReportIntegrationTest { when(fileAttributesConfigClient.getFileAttributeConfigs(dossierTemplateId)).thenReturn(new ArrayList<>()); - FileModel fileStatus = FileModel.builder().filename("filename").build(); + FileModel fileStatus = FileModel.builder().filename("VV123456").build(); Dossier project = Dossier.builder().id("dossierId").dossierName("projectName").build(); @@ -455,7 +452,7 @@ public class RedactionReportIntegrationTest { .build(); byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileStatus, project); - try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report.docx")) { + try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report_2.docx")) { fileOutputStream.write(report); } } diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage2.jpeg b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage2.jpeg new file mode 100644 index 0000000..e08bec8 Binary files /dev/null and b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage2.jpeg differ diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage3.jpeg b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage3.jpeg new file mode 100644 index 0000000..2c5ce48 Binary files /dev/null and b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage3.jpeg differ diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage4.jpeg b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage4.jpeg new file mode 100644 index 0000000..6573f5a Binary files /dev/null and b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/exampleImage4.jpeg differ diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/TestReport2.xlsx b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/TestReport2.xlsx new file mode 100644 index 0000000..88dfc40 Binary files /dev/null and b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/TestReport2.xlsx differ