private static final List HEADER_LABELS = List.of(“Risk ID”, “Hazard Type/Group”, “Hazard (potential source of harm)”, “FMEA ID/Other tool ID”,
“Device Category”, “Failure Mode (initial cause of hazard)”, “Causes/ mechanisms of failure/ sequence of events”, “End effect of failure”,
“Hazardous Situation”, “Probability§ of Occurrence”, “Severity(S)”, “Risk(PS)", “Inherit safety by design or manufacture”, “Requirements”,
“Protective Measures(PM)”, “PM Requirements”, “Information for safety (IFS)”, “IFS Requirements”, “SW Contribution”, “Reference”, “Harm”,
“Probability§ of Occurrence”, “Severity(S)”, "Residual Risk(PS)”, “Benefit Risk Analysis”, “Risks Reduced as far as Possible?”,
“New risk introduced due to control measure?”, “New Risk ID”, “Risk Control Verification(Effectiveness Check)”, “Status of Risk Control Effectiveness”,
“Remarks”);
@SneakyThrows
@Override
public com.scubetech.rm.domain.Document generateRMMPDF(RmmPdfDTO rmmPdfDTO) {
log.info("GenerateRMMPDF has started");
File file = null;
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
com.scubetech.rm.domain.Document document = null;
if (StringUtils.hasText(rmmPdfDTO.getDocumentId())) {
document = dbPersistencePort.findById(rmmPdfDTO.getDocumentId());
}
String contentId = document != null ? document.getContentId() : UUID.randomUUID().toString();
Map<Integer, String> probabilityNameById = new HashMap<>();
Map<Integer, String> severityNameById = new HashMap<>();
Map<ValueRange, String> colorByRange = new HashMap<>();
ObjectNode probabilityAndSeverityData = rmmPdfDTO.getViewProbSevOptsMatrix();
if (probabilityAndSeverityData != null) {
probabilityNameById = this.segregateProbabilityNameById((ArrayNode) probabilityAndSeverityData.get("probability"));
severityNameById = this.segregateSeverityNameById((ArrayNode) probabilityAndSeverityData.get("severity"));
colorByRange = this.segregateColorByRange((ArrayNode) probabilityAndSeverityData.get("matrix"));
}
com.aspose.pdf.Document rmmPdfDoc = new com.aspose.pdf.Document();
rmmPdfDoc.setTitle("Risk Management Matrix");
this.addFirstPage(rmmPdfDoc, "Risk Management Matrix", 1000.0, 1000.0);
Page page = rmmPdfDoc.getPages().add();
page.setPageSize(1000.0, 1000.0);
page.getPageInfo().setLandscape(true);
MarginInfo pageMargin = new MarginInfo(10, 90, 10, 70);
page.getPageInfo().setMargin(pageMargin);
MarginInfo tableMargin = new MarginInfo(3, 10, 3, 10);
Table table = new Table();
table.setColumnWidths("3.2%");
table.setBorder(new BorderInfo(BorderSide.All, 0.1F, Color.getLightSalmon()));
table.setDefaultCellBorder(new BorderInfo(BorderSide.All, 0.1F, Color.getLightSalmon()));
table.setDefaultCellPadding(tableMargin);
TextState headerTextStyle = new TextState();
headerTextStyle.setFontStyle(FontStyles.Bold);
headerTextStyle.setFontSize(11.0F);
//Add labels for Heading in the table
Row tableHeaderRow = table.getRows().add();
tableHeaderRow.setBackgroundColor(Color.getLightGray());
tableHeaderRow.setDefaultCellTextState(headerTextStyle);
this.addCellsToRowOfTable(tableHeaderRow);
int counter = 0;
//Add data to the table
for (RiskManagementMatrixDTO riskManagementMatrixDTO : rmmPdfDTO.getRmmList()) {
if (counter >= 1) {
break;
}
Row dataRow = table.getRows().add();
dataRow.getCells().add(riskManagementMatrixDTO.getCustomId());
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getHazardType()) ? riskManagementMatrixDTO.getHazardType() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getHazard()) ? riskManagementMatrixDTO.getHazard() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getCustomRiskFmeaId()) ? riskManagementMatrixDTO.getCustomRiskFmeaId() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getDeviceCategory()) ? riskManagementMatrixDTO.getDeviceCategory() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getFailureMode()) ? riskManagementMatrixDTO.getFailureMode() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getCauses()) ? riskManagementMatrixDTO.getCauses() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getEndEffectOfFailure()) ? riskManagementMatrixDTO.getEndEffectOfFailure() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getHazardousSituation()) ? riskManagementMatrixDTO.getHazardousSituation() : "");
ObjectNode beforeProbAndSevRiskData = riskManagementMatrixDTO.getViewBeforeProbSevRiskOptsMatrix();
if (beforeProbAndSevRiskData != null) {
int probabilityId = beforeProbAndSevRiskData.get("probability").asInt();
int severityId = beforeProbAndSevRiskData.get("severity").asInt();
int risk = probabilityId * severityId;
dataRow.getCells().add(probabilityNameById.get(probabilityId) != null ? probabilityNameById.get(probabilityId) : "");
dataRow.getCells().add(severityNameById.get(severityId) != null ? severityNameById.get(severityId) : "");
Cell riskCell = dataRow.getCells().add(String.valueOf(risk));
String colorName = this.getColorNameIfValueInRange(risk, colorByRange);
if (StringUtils.hasText(colorName)) {
riskCell.setBackgroundColor(this.getColorByName(colorName));
}
} else {
dataRow.getCells().add("-");
dataRow.getCells().add("-");
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getSafeByDesign()) ? riskManagementMatrixDTO.getSafeByDesign() : "");
if (riskManagementMatrixDTO.getRequirementsDetails() != null && !riskManagementMatrixDTO.getRequirementsDetails().isEmpty()) {
dataRow.getCells().add(riskManagementMatrixDTO.getRequirementsDetails().stream().map(RequirementShortDTO::getCustomId).collect(Collectors.joining(",")));
} else {
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getProtectiveMeasure()) ? riskManagementMatrixDTO.getProtectiveMeasure() : "");
if (riskManagementMatrixDTO.getPmRequirementsDetails() != null && !riskManagementMatrixDTO.getPmRequirementsDetails().isEmpty()) {
dataRow.getCells().add(riskManagementMatrixDTO.getPmRequirementsDetails().stream().map(RequirementShortDTO::getCustomId).collect(Collectors.joining(",")));
} else {
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getInformationForSafety()) ? riskManagementMatrixDTO.getInformationForSafety() : "");
if (riskManagementMatrixDTO.getIfsRequirementsDetails() != null && !riskManagementMatrixDTO.getIfsRequirementsDetails().isEmpty()) {
dataRow.getCells().add(riskManagementMatrixDTO.getIfsRequirementsDetails().stream().map(RequirementShortDTO::getCustomId).collect(Collectors.joining(",")));
} else {
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getSwContribution()) ? riskManagementMatrixDTO.getSwContribution() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getReference()) ? riskManagementMatrixDTO.getReference() : "");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getHarm()) ? riskManagementMatrixDTO.getHarm() : "");
ObjectNode afterProbAndSevRiskData = riskManagementMatrixDTO.getViewAfterProbSevRiskOptsMatrix();
if (afterProbAndSevRiskData != null) {
int probabilityId = afterProbAndSevRiskData.get("probability").asInt();
int severityId = afterProbAndSevRiskData.get("severity").asInt();
int risk = probabilityId * severityId;
dataRow.getCells().add(probabilityNameById.get(probabilityId) != null ? probabilityNameById.get(probabilityId) : "");
dataRow.getCells().add(severityNameById.get(severityId) != null ? severityNameById.get(severityId) : "");
Cell riskCell = dataRow.getCells().add(String.valueOf(risk));
String colorName = this.getColorNameIfValueInRange(risk, colorByRange);
if (StringUtils.hasText(colorName)) {
riskCell.setBackgroundColor(this.getColorByName(colorName));
}
} else {
dataRow.getCells().add("-");
dataRow.getCells().add("-");
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getLocalRiskBenefitAnalysis()) ? riskManagementMatrixDTO.getLocalRiskBenefitAnalysis() :"");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getNewRiskReduced()) ? riskManagementMatrixDTO.getNewRiskReduced() :"");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getNewRiskIntroduced()) ? riskManagementMatrixDTO.getNewRiskIntroduced() :"");
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getNewRiskId()) ? riskManagementMatrixDTO.getNewRiskId() :"");
if (riskManagementMatrixDTO.getRiskControlEffectivenessDetails() != null &&
!riskManagementMatrixDTO.getRiskControlEffectivenessDetails().isEmpty()) {
//Adds data for columns Risk Control Verification(Effectiveness Check),Status of Risk Control Effectiveness
this.addRiskControlVerificationAndStatusToCellOfRow(dataRow, riskManagementMatrixDTO.getRiskControlEffectivenessDetails());
} else {
dataRow.getCells().add("-");
dataRow.getCells().add("-");
}
dataRow.getCells().add(StringUtils.hasText(riskManagementMatrixDTO.getRemarks()) ? riskManagementMatrixDTO.getRemarks() : "");
counter++;
}
page.getParagraphs().add(table);
rmmPdfDoc.save(byteArrayOutputStream, SaveFormat.Pdf);
// System.out.print("--------------"+ Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray())+"--------------");
//Create a file using byte[] last downloaded, file name is value of contentId
file = new File("/tmp/" + contentId);
FileUtils.writeByteArrayToFile(file, byteArrayOutputStream.toByteArray());
Tika tika = new Tika();
String mimeType = tika.detect(file);
//Store file in Azure
if (document != null) {
blobStoragePersistencePort.deleteFile(TenantContext.getCurrentTenant().toLowerCase(), contentId);
}
blobStoragePersistencePort.upload(TenantContext.getCurrentTenant().toLowerCase(), contentId, file);
String checksum = getFileChecksum(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
if (document == null) {
document = com.scubetech.rm.domain.Document.builder()
.documentId(UUID.randomUUID().toString())
.contentId(contentId)
.contentLength(file.length())
.fileName("Risk Management Matrix".concat(".pdf"))
.mimeType(mimeType)
.tenantId(TenantContext.getCurrentTenant())
.objectId(rmmPdfDTO.getProjectId())
.objectType(Constants.RMM)
.fileChecksum(checksum)
.creAt(Instant.now())
.creBy(TenantContext.getCurrentUser())
.build();
document.getVersions().add(this.getVersion(document, document.getFileVersion()));
document = dbPersistencePort.save(document);
}
return document;
} catch (Exception e) {
log.error(String.format("Exception in generateRMMPDF - %s", e.getMessage()),e);
throw e;
} finally {
if (file != null) {
file.delete();
}
}
}
private void addRiskControlVerificationAndStatusToCellOfRow(Row row, List<TestcaseExecutionPlanShortDTO> riskControlEffectivenessDetailsList) {
List<String> riskControlVerifications = new ArrayList<>();
List<String> riskControlStatus = new ArrayList<>();
for (TestcaseExecutionPlanShortDTO riskControlEffectivenesDetails : riskControlEffectivenessDetailsList) {
riskControlVerifications.add(riskControlEffectivenesDetails.getCustomTestcaseExecutionPlanId().concat("-").concat(riskControlEffectivenesDetails.getTitle()));
riskControlStatus.add(riskControlEffectivenesDetails.getTestExecutionStatus().concat("-").concat(riskControlEffectivenesDetails.getCustomTestcaseExecutionPlanId()));
}
row.getCells().add(String.join(",", riskControlVerifications));
row.getCells().add(String.join(",", riskControlStatus));
}
private void addCellsToRowOfTable(Row tableHeaderRow) {
for (String headerLabel : RMMServicePortImpl.HEADER_LABELS) {
tableHeaderRow.getCells().add(headerLabel);
}
}
private String getColorNameIfValueInRange(int value, Map<ValueRange, String> colorNameByRange) {
if (colorNameByRange != null && !colorNameByRange.isEmpty()) {
for (ValueRange valueRange : colorNameByRange.keySet()) {
if (valueRange.isValidValue(value)) {
return colorNameByRange.get(valueRange);
}
}
}
return null;
}
private Map<Integer, String> segregateProbabilityNameById(ArrayNode probabilityNameAndId) {
Map<Integer, String> probabilityNameById = new HashMap<>();
for (JsonNode matrix :probabilityNameAndId) {
probabilityNameById.put(matrix.get("value").asInt(), matrix.get("name").asText());
}
return probabilityNameById;
}
private Map<Integer, String> segregateSeverityNameById(ArrayNode severityNameAndId) {
Map<Integer, String> severityNameById = new HashMap<>();
for (JsonNode matrix :severityNameAndId) {
severityNameById.put(matrix.get("value").asInt(), matrix.get("name").asText());
}
return severityNameById;
}
private Map<ValueRange, String> segregateColorByRange(ArrayNode colorRangeMatrix) {
Map<ValueRange, String> colorNameByRange = new HashMap<>();
if (colorRangeMatrix != null) {
for (JsonNode matrix : colorRangeMatrix) {
JsonNode range = matrix.get("range");
ValueRange rangeData = ValueRange.of(range.get("min").asInt(), range.get("max").asInt());
String color = matrix.get("colour").asText();
colorNameByRange.put(rangeData, color);
}
}
return colorNameByRange;
}
private Color getColorByName(String colorName) {
if (colorName.equalsIgnoreCase("green")) {
return Color.fromArgb(123, 185, 81);
} else if (colorName.equalsIgnoreCase("blue")) {
return Color.fromArgb(84, 131, 215);
} else if (colorName.equalsIgnoreCase("red")) {
return Color.fromArgb(255, 48, 48);
} else if (colorName.equalsIgnoreCase("amber")) {
return Color.fromArgb(255, 191, 0);
}
return null;
}
private static String getFileChecksum(InputStream inputStream) throws Exception {
//Use MD5 algorithm
MessageDigest md5Digest = MessageDigest.getInstance("MD5");
//Get file input stream for reading the file content
BufferedInputStream fis = new BufferedInputStream(inputStream);
//Create byte array to read data in chunks
byte[] byteArray = new byte[1024];
int bytesCount;
//Read file data and update in message digest
while ((bytesCount = fis.read(byteArray)) != -1) {
md5Digest.update(byteArray, 0, bytesCount);
}
//close the stream; We don't need it now.
fis.close();
//Get the hash's bytes
byte[] bytes = md5Digest.digest();
//This bytes[] has bytes in decimal format;
//Convert it to hexadecimal format
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
}
//return complete hash
return sb.toString();
}
//Prepare document version detail to store in db
private Version getVersion(com.scubetech.rm.domain.Document document, Double newFileVersion) {
if (newFileVersion != null) {
return Version.builder()
.contentId(document.getContentId())
.contentLength(document.getContentLength())
.fileVersion(newFileVersion)
.customFileVersion(document.getCustomFileVersion())
.status(Status.valueOf(document.getStatus()))
.build();
} else {
return Version.builder()
.contentId(document.getContentId())
.contentLength(document.getContentLength())
.fileVersion(document.getFileVersion())
.customFileVersion(document.getCustomFileVersion())
.status(Status.valueOf(document.getStatus()))
.build();
}
}
com.aspose.pdf.Document addFirstPage(com.aspose.pdf.Document pdfDocument, String tenantName, Double width, Double height) {
Page firstPage = pdfDocument.getPages().insert(1);
if (width != 0 && height != 0) {
firstPage.setPageSize(width, height);
}
TextStamp textStamp = new TextStamp(tenantName);
textStamp.setHorizontalAlignment(HorizontalAlignment.Center);
textStamp.setVerticalAlignment(VerticalAlignment.Center);
textStamp.setTextAlignment(TextAlignment.Center);
textStamp.getTextState().setFontSize(20);
firstPage.addStamp(textStamp);
return pdfDocument;
}