All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dpfmanager.conformancechecker.tiff.reporting.HtmlReport Maven / Gradle / Ivy

/**
 * 

HtmlReport.java

This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version; or, at your * choice, under the terms of the Mozilla Public License, v. 2.0. SPDX GPL-3.0+ or MPL-2.0+.

*

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License and the Mozilla Public License for more details.

You should * have received a copy of the GNU General Public License and the Mozilla Public License along with * this program. If not, see http://www.gnu.org/licenses/ * and at http://mozilla.org/MPL/2.0 .

NB: for the * © statement, include Easy Innova SL or other company/Person contributing the code.

© * 2015 Easy Innova, SL

* * @author Víctor Muñoz Solà * @version 1.0 * @since 23/7/2015 */ package dpfmanager.conformancechecker.tiff.reporting; import dpfmanager.conformancechecker.tiff.TiffConformanceChecker; import dpfmanager.conformancechecker.tiff.implementation_checker.ImplementationCheckerLoader; import dpfmanager.conformancechecker.tiff.implementation_checker.rules.RuleResult; import dpfmanager.conformancechecker.tiff.implementation_checker.rules.model.RuleType; import dpfmanager.shell.modules.report.core.IndividualReport; import dpfmanager.shell.modules.report.core.ReportGenerator; import com.easyinnova.tiff.model.Metadata; import com.easyinnova.tiff.model.TagValue; import com.easyinnova.tiff.model.TiffDocument; import com.easyinnova.tiff.model.TiffTags; import com.easyinnova.tiff.model.types.IFD; import com.easyinnova.tiff.model.types.IPTC; import com.easyinnova.tiff.model.types.XMP; import com.easyinnova.tiff.model.types.abstractTiffType; import org.apache.commons.lang.StringUtils; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; /** * Created by easy on 05/05/2016. */ public class HtmlReport extends Report { /** * Parse an individual report to HTML. * * @param ir the individual report. * @param mode the mode (1, 2). */ public String parseIndividual(IndividualReport ir, int mode, int id) { String templatePath = "templates/individual.html"; String htmlBody = readFilefromResources(templatePath); // Image String fileName = getReportName("", ir.getFilePath(), id); String imgPath = "img/" + fileName + ".jpg"; BufferedImage thumb = tiff2Jpg(ir.getFilePath()); if (thumb == null) { imgPath = "img/noise.jpg"; } htmlBody = StringUtils.replace(htmlBody, "##IMG_PATH##", encodeUrl(imgPath)); /** * Basic info / divs conforms */ htmlBody = StringUtils.replace(htmlBody, "##IMG_NAME##", ir.getFileName()); htmlBody = StringUtils.replace(htmlBody, "##IMG_FILEPATH##", ir.getFilePath()); String divs = ""; for (String iso : ir.getCheckedIsos()) { if (ir.hasValidation(iso) || ir.getErrors(iso).isEmpty()) { divs += makeConformsText(ir, iso); } } htmlBody = StringUtils.replace(htmlBody, "##DIVS_CONFORMS##", divs); if (mode == 1) { htmlBody = StringUtils.replace(htmlBody, "##CL_LINKR2##", "show"); htmlBody = StringUtils.replace(htmlBody, "##LINK2##", encodeUrl(new File(fileName).getName() + "_fixed.html")); } if (mode == 2) { htmlBody = StringUtils.replace(htmlBody, "##CL_LINKR1##", "show"); htmlBody = StringUtils.replace(htmlBody, "##LINK1##", encodeUrl(new File(fileName).getName() + ".html")); } /** * Table errors / warnings count */ String rowTmpl = "\n" + " ##TITLE##\n" + " ##ERR##\n" + " ##WAR##\n" + " "; String rows = ""; for (String iso : ir.getIsosCheck()) { if (ir.hasValidation(iso)) { String name = ImplementationCheckerLoader.getIsoName(iso); String row = rowTmpl; int errorsCount = ir.getNErrors(iso); int warningsCount = ir.getNWarnings(iso); row = StringUtils.replace(row, "##TITLE##", name); String difErr = ir.getCompareReport() != null ? getDif(ir.getCompareReport().getNErrors(iso), ir.getNErrors(iso)) : ""; String difWar = ir.getCompareReport() != null ? getDif(ir.getCompareReport().getNWarnings(iso), ir.getNWarnings(iso)) : ""; row = StringUtils.replace(row, "##ERR##", "" + errorsCount + difErr); row = StringUtils.replace(row, "##WAR##", "" + warningsCount + difWar); row = StringUtils.replace(row, "##ERR_CLASS##", errorsCount > 0 ? "error" : "info"); row = StringUtils.replace(row, "##WAR_CLASS##", warningsCount > 0 ? "warning" : "info"); rows += row; } } htmlBody = StringUtils.replace(htmlBody, "##TABLE_RESUME_ERRORS##", rows); /** * Errors / Warnings resume */ String fullTmpl = "
\n" + "\t\t\t\t##CHECK##\n" + "\t\t\t\t
\n" + "\t\t\t\t\t
##TITLE##
\n" + "\t\t\t\t\t##CONTENT##\n" + "\t\t\t\t
\n" + "\t\t\t
"; String checkInfos = "
"; String errorsTmpl = "\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWS##\n" + "\t\t\t\t\t
TypeIDLocationDescription
"; String policyTmpl = "\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWS##\n" + "\t\t\t\t\t
TypeRuleDescription
"; String tdTmpl = "##ID####LOC####DESC##"; String pcTmpl = "##LOC####DESC##"; rows = ""; int count = 0; for (String iso : ir.getIsosCheck()) { if (ir.hasValidation(iso)) { String name = ImplementationCheckerLoader.getIsoName(iso); String row = fullTmpl, icon = "exclamation"; int errorsCount = ir.getNErrors(iso); int warningsCount = ir.getNWarnings(iso); int infosCount = ir.getNInfos(iso); int addedRows = 0, addedInfos = 0; if (errorsCount > 0){ icon = "fa-times-circle"; } else if (warningsCount > 0) { icon = "fa-exclamation-circle"; } else { icon = "fa-check-circle"; } String content = ""; if (errorsCount + warningsCount + infosCount > 0) { if (iso.equals(TiffConformanceChecker.POLICY_ISO)) { content += policyTmpl; } else { content += errorsTmpl; } String allRows = ""; // Errors, Warnings and Infos for (RuleResult val : ir.getAllRuleResults(iso)) { String tdRow, display = "", clasz = "", location = ""; if (val.getRule() == null) { // Policy value tdRow = pcTmpl; if (!val.ok() && !val.getWarning()) { tdRow = tdRow.replace("##FA_CLASS##", "times"); } else if (!val.ok()) { tdRow = tdRow.replace("##FA_CLASS##", "exclamation"); } location = val.getRuleDescription(); } else { // Rule value tdRow = tdTmpl; if (val.getRule().isError() || val.getRule().isCritical()) { tdRow = tdRow.replace("##FA_CLASS##", "times"); } else if (val.getRule().isWarning()) { tdRow = tdRow.replace("##FA_CLASS##", "exclamation"); } else if (val.getRule().isInfo()) { tdRow = tdRow.replace("##FA_CLASS##", "info"); display = "style='display: none;'"; clasz = "class='info##COUNT##'"; addedInfos++; } location = val.getLocation(); } tdRow = tdRow.replace("##ID##", val.getRule() != null ? val.getRule().getId() : ""); tdRow = tdRow.replace("##LOC##", location); tdRow = tdRow.replace("##DESC##", val.getDescription()); tdRow = tdRow.replace("##POPOVER##", makePopoverAttributes(val)); tdRow = tdRow.replace("##DISPLAY##", display); tdRow = tdRow.replace("##CLASS##", clasz); addedRows++; allRows += tdRow; } content = StringUtils.replace(content, "##ROWS##", allRows); } if (addedRows == 0) { content = ""; } if (addedInfos == 0) { row = StringUtils.replace(row, "##CHECK##", ""); } row = StringUtils.replace(row, "##CHECK##", checkInfos); row = StringUtils.replace(row, "##CONTENT##", content); row = StringUtils.replace(row, "##COUNT##", (++count) + ""); row = StringUtils.replace(row, "##TITLE##", name); row = StringUtils.replace(row, "##ICON##", icon); rows += row; } } htmlBody = StringUtils.replace(htmlBody, "##DIVS_ERRORS##", rows); /** * Tags divs */ htmlBody = StringUtils.replace(htmlBody, "##TAGS_DIVS##", generateTagsDivs(ir)); /** * File Structure */ String ul = "
    "; int index = 0; TiffDocument td = ir.getTiffModel(); IFD ifd = td.getFirstIFD(); boolean hasIFDList = false; if (ifd != null && ifd.hasNextIFD()) { hasIFDList = ifd.hasNextIFD(); } while (ifd != null) { String typ = " - Main image"; if (ifd.hasSubIFD() && ifd.getImageSize() < ifd.getsubIFD().getImageSize()) { typ = " - Thumbnail"; } String aIni = ""; String aBody = " " + ifd.toString() + typ; String aEnd = ""; String bold = ""; if (index == 0) { bold = "bold"; } aIni = ""; aEnd = ""; ul += "
  • " + aIni + aBody + aEnd; if (ifd.getsubIFD() != null) { typ = ""; if (ifd.getImageSize() < ifd.getsubIFD().getImageSize()) typ = " - Main image"; else typ = " - Thumbnail"; ul += ""; } if (ifd.containsTagId(34665)) { ul += ""; } if (ifd.containsTagId(700)) { ul += ""; } if (ifd.containsTagId(33723)) { ul += ""; } if (index == 0) { if (ir.getTiffModel().getIccProfile() != null) { String creat = ""; if (ir.getTiffModel().getIccProfile().getCreator() != null) { creat = "
  • Creator: " + ir.getTiffModel().getIccProfile().getCreator().getCreator() + "
  • "; } ul += "
    • ICC
        " + "
      • Description: " + ir.getTiffModel().getIccProfile().getDescription() + "
      • " + creat + "
      • Version: " + ir.getTiffModel().getIccProfile().getVersion() + "
      • " + "
      • Class: " + ir.getTiffModel().getIccProfile().getProfileClass().toString() + "
      " + "
    "; } } ul += ""; index++; ifd = ifd.getNextIFD(); } ul += "
"; htmlBody = StringUtils.replace(htmlBody, "##UL##", ul); /** * Metadata incoherencies */ IFD tdifd = td.getFirstIFD(); int nifd = 1; rows = ""; while (tdifd != null) { XMP xmp = null; IPTC iptc = null; if (tdifd.containsTagId(TiffTags.getTagId("XMP"))) xmp = (XMP) tdifd.getTag("XMP").getValue().get(0); if (tdifd.containsTagId(TiffTags.getTagId("IPTC"))) iptc = (IPTC) tdifd.getTag("IPTC").getValue().get(0); // Author String authorTag = null; if (tdifd.containsTagId(TiffTags.getTagId("Artist"))) authorTag = tdifd.getTag("Artist").toString(); String authorIptc = null; if (iptc != null) authorIptc = iptc.getCreator(); String authorXmp = null; if (xmp != null) authorXmp = xmp.getCreator(); rows += detectIncoherency(authorTag, authorIptc, authorXmp, "Author", nifd); tdifd = tdifd.getNextIFD(); nifd++; } if (rows.isEmpty()){ rows = "No metadata incoherencies found"; } htmlBody = StringUtils.replace(htmlBody, "##META_ROWS##", rows); /** * Finish, write to html file */ htmlBody = StringUtils.replace(htmlBody, "\\.\\./html/", ""); return htmlBody; } private String generateTagsDivs(IndividualReport ir) { Map hasExpert = new HashMap<>(); Map tagsMap = new HashMap<>(); Map templates = new HashMap<>(); String row; /** * Parse TAGs */ for (ReportTag tag : getTags(ir)) { if (tag.tv.getId() == 700) { String mapId = "xmp" + tag.index; String mapIdH = "xmp" + tag.index + "h"; // XMP for (abstractTiffType to : tag.tv.getValue()) { XMP xmp = (XMP) to; try { Metadata metadata = xmp.createMetadata(); for (String key : metadata.keySet()) { row = "" + key + "" + metadata.get(key).toString().trim() + ""; String rows = tagsMap.containsKey(mapId) ? tagsMap.get(mapId) : ""; tagsMap.put(mapId, rows + row); } if (xmp.getHistory() != null) { for (Hashtable kv : xmp.getHistory()) { // TODO WORKARROUND String key = kv.keySet().iterator().next(); String value = kv.get(key); row = "##ATTR####VALUE##"; if (key.equals("action")) { row = row.replace("##LINE##", "line-top"); } else { row = row.replace("##LINE##", ""); } row = row.replace("##ATTR##", key); row = row.replace("##VALUE##", value); String rows = tagsMap.containsKey(mapIdH) ? tagsMap.get(mapIdH) : ""; tagsMap.put(mapIdH, rows + row); } } } catch (Exception ex) { ex.printStackTrace(); } } continue; } if (tag.tv.getId() == 34665) { // EXIF String mapId = "exi" + tag.index; IFD exif = (IFD) tag.tv.getValue().get(0); for (TagValue tv : exif.getTags().getTags()) { if (tv.getId() == 36864){ tv.toString(); } row = "##ICON##"+tv.getId()+"" + (tv.getName().equals(tv.getId()+"") ? "Private tag" : tv.getName()) + "" + tv.getDescriptiveValue() + ""; row = row.replace("##ICON##", ""); String rows = tagsMap.containsKey(mapId) ? tagsMap.get(mapId) : ""; tagsMap.put(mapId, rows + row); } continue; } if (tag.tv.getId() == 330) { // Sub IFD String mapId = "sub" + tag.index; IFD sub = (IFD) tag.tv.getValue().get(0); for (TagValue tv : sub.getTags().getTags()) { String expert = ""; if (!showTag(tv)) { expert = "expert"; hasExpert.put(mapId, true); } row = "##ICON####ID####KEY####VALUE##"; row = row.replace("##ICON##", ""); row = row.replace("##ID##", tv.getId() + ""); row = row.replace("##KEY##", (tv.getName().equals(tv.getId()+"") ? "Private tag" : tv.getName())); row = row.replace("##VALUE##", tv.getDescriptiveValue()); String rows = tagsMap.containsKey(mapId) ? tagsMap.get(mapId) : ""; tagsMap.put(mapId, rows + row); } continue; } if (tag.tv.getId() == 33723) { String mapId = "ipt" + tag.index; // IPTC for (abstractTiffType to : tag.tv.getValue()) { IPTC iptc = (IPTC) to; try { Metadata metadata = iptc.createMetadata(); for (String key : metadata.keySet()) { row = "" + key + "" + metadata.get(key).toString().trim() + ""; String rows = tagsMap.containsKey(mapId) ? tagsMap.get(mapId) : ""; tagsMap.put(mapId, rows + row); } } catch (Exception ex) { ex.printStackTrace(); } } continue; } // IFD String mapId = "ifd" + tag.index; String expert = ""; if (tag.expert) { expert = " expert"; hasExpert.put(mapId, true); } row = "##ICON####ID####KEY####VALUE##"; String sDif = ""; if (tag.dif < 0) sDif = ""; else if (tag.dif > 0) sDif = ""; row = row.replace("##ICON##", ""); row = row.replace("##ID##", tag.tv.getId() + sDif); row = row.replace("##KEY##", (tag.tv.getName().equals(tag.tv.getId()) ? "Private tag" : tag.tv.getName())); row = row.replace("##VALUE##", tag.tv.getDescriptiveValue()); String rows = tagsMap.containsKey(mapId) ? tagsMap.get(mapId) : ""; tagsMap.put(mapId, rows + row); } /** * Generate divs */ String finalResult = ""; String expertTmpl = "
"; String genTmpl = "
\n" + "\t\t\t\t\t##EXPERT##\n" + "\t\t\t\t\t

##TITLE##

\n" + "\t\t\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWS##\n" + "\t\t\t\t\t
Tag IdTag NameValue
\n" + "\t\t\t\t
"; String subTmpl = StringUtils.replace(genTmpl, "##TITLE##", "Sub IFD Tags"); String ifdTmpl = StringUtils.replace(genTmpl, "##TITLE##", "IFD Tags"); String exifTmpl = StringUtils.replace(genTmpl, "##TITLE##", "EXIF"); String iptcTmpl = "
\n" + "\t\t\t\t\t##EXPERT##\n" + "\t\t\t\t\t

IPTC

\n" + "\t\t\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWS##\n" + "\t\t\t\t\t
NameValue
\n" + "\t\t\t\t
"; String xmpTmpl = "
\n" + "\t\t\t\t\t##EXPERT##\n" + "\t\t\t\t\t

XMP

\n" + "\t\t\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWS##\n" + "\t\t\t\t\t
NameValue
\n" + "\t\t\t\t\t
\n" + "\t\t\t\t\t

History

\n" + "\t\t\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t \n" + "\t\t\t\t ##ROWSH##\n" + "\t\t\t\t\t
AttributeValue
\n" + "\t\t\t\t\t
\n" + "\t\t\t\t
"; templates.put("ifd", ifdTmpl); templates.put("sub", subTmpl); templates.put("ipt", iptcTmpl); templates.put("xmp", xmpTmpl); templates.put("exi", exifTmpl); /** * Generate HTMLs */ for (String key : tagsMap.keySet()) { if (key.endsWith("h")) continue; String type = key.substring(0, 3); String display = "none;", expert = ""; if (key.equals("ifd0")) display = "block;"; if (hasExpert.containsKey(key)) expert = expertTmpl; String tmpl = templates.get(type); tmpl = StringUtils.replace(tmpl, "##EXPERT##", expert); tmpl = StringUtils.replace(tmpl, "##INDEX##", key); tmpl = StringUtils.replace(tmpl, "##DISPLAY##", display); tmpl = StringUtils.replace(tmpl, "##ROWS##", tagsMap.get(key)); if (type.equals("xmp") && tagsMap.containsKey(key + "h")) { tmpl = StringUtils.replace(tmpl, "##ROWSH##", tagsMap.get(key + "h")); tmpl = StringUtils.replace(tmpl, "##DISH##", "block"); } else { tmpl = StringUtils.replace(tmpl, "##DISH##", "none"); } finalResult += tmpl; } return finalResult; } private String detectIncoherency(String valueTag, String valueIptc, String valueXmp, String name, int nifd) { String tmpl = "##TEXT##"; String incoherencies = ""; if (valueTag != null && valueIptc != null && !valueTag.equals(valueIptc)) { incoherencies += StringUtils.replace(tmpl, "##TEXT##", name + " on TAG and IPTC in IFD " + nifd + " (" + valueTag + ", " + valueIptc + ")"); } if (valueTag != null && valueXmp != null && !valueTag.equals(valueXmp)) { incoherencies += StringUtils.replace(tmpl, "##TEXT##", name + " on TAG and XMP in IFD " + nifd + " (" + valueTag + ", " + valueXmp + ")"); } if (valueIptc != null && valueXmp != null && !valueIptc.equals(valueXmp)) { incoherencies += StringUtils.replace(tmpl, "##TEXT##", name + " on IPTC and XMP in IFD " + nifd + " (" + valueIptc + ", " + valueXmp + ")"); } return incoherencies; } private String makePopoverAttributes(RuleResult val) { RuleType rule = val.getRule(); if (rule != null && !rule.getTitle().getValue().isEmpty() && !rule.getDescription().getValue().isEmpty()) { String description = rule.getDescription().getValue(); if (val.getReference() != null) { description += "
" + val.getReference() + ""; } if (rule.getId().equals("RECOMMENDED-TAG-270")){ val.toString(); } description = description.replaceAll("\"","'"); return "data-toggle=\"popover\" title=\"" + rule.getTitle().getValue() + "\" data-content=\"" + description + "\" data-placement=\"auto bottom\" data-trigger=\"hover\""; } return ""; } private String makeConformsText(IndividualReport ir, String iso) { String tmplPassed = "
##TITLE##
"; // String tmplWarn = "
##TITLE##
"; String tmplError = "
##TITLE##
"; String name = ImplementationCheckerLoader.getIsoName(iso); int err = ir.getNErrors(iso); int war = ir.getNWarnings(iso); if (err == 0 && war == 0) { return StringUtils.replace(tmplPassed, "##TITLE##", name); } else if (err == 0 && war > 0) { return StringUtils.replace(tmplPassed, "##TITLE##", name); } else { return StringUtils.replace(tmplError, "##TITLE##", name); } } /** * Gets the report name of a given tiff file. * * @param internalReportFolder the internal report folder * @param realFilename the real file name * @param idReport the report id * @return the report name */ public static String getReportName(String internalReportFolder, String realFilename, int idReport) { String reportName = internalReportFolder + idReport + "-" + new File(realFilename).getName(); File file = new File(reportName); int index = 0; while (file.exists()) { index++; String ext = getFileType(reportName); reportName = internalReportFolder + idReport + "-" + new File(realFilename.substring(0, realFilename.lastIndexOf(".")) + index + "." + ext) .getName(); file = new File(reportName); } return reportName; } /** * Gets the file type. * * @param path the path * @return the file type */ static String getFileType(String path) { String fileType = null; fileType = path.substring(path.lastIndexOf('.') + 1).toUpperCase(); return fileType; } /** * Read filefrom resources string. * * @param pathStr the path str * @return the string */ public String readFilefromResources(String pathStr) { String text = ""; Path path = Paths.get(pathStr); try { if (Files.exists(path)) { // Look in current dir BufferedReader br = new BufferedReader(new FileReader(pathStr)); StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } text = sb.toString(); br.close(); } else { // Look in JAR Class cls = ReportGenerator.class; ClassLoader cLoader = cls.getClassLoader(); InputStream in = cLoader.getResourceAsStream(pathStr); if (in != null) { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder out = new StringBuilder(); String newLine = System.getProperty("line.separator"); String line; while ((line = reader.readLine()) != null) { out.append(line); out.append(newLine); } text = out.toString(); } } } catch (FileNotFoundException e) { } catch (IOException e) { } return text; } private String encodeUrl(String str) { return str.replaceAll("#", "%23"); } }