package es.uv.saic.service; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.Reader; import java.io.UncheckedIOException; import java.math.BigInteger; import java.nio.file.Files; import java.text.DecimalFormat; import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.springframework.util.FileCopyUtils; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import es.uv.saic.shared.domain.Plantilla; import es.uv.saic.shared.domain.PlantillaComentario; import es.uv.saic.shared.domain.PlantillaConversation; import es.uv.saic.shared.domain.PlantillaRepository; import es.uv.saic.shared.dto.InstanciaTascaDTO; import es.uv.saic.shared.feign.IndicadorClient; import es.uv.saic.shared.feign.OrganClient; import es.uv.saic.shared.feign.ProceduresClient; import es.uv.saic.shared.feign.TascaClient; @Service public class PlantillaService { @Autowired private PlantillaRepository r; @Value("${saic.data.filePath}") private String filePath; @Value("${saic.data.tmpPath}") private String tmpPath; @Value("${saic.data.templates.fileNotFound}") private String fileNotFound; @Value("${saic.data.templates.filePath}") private String templatePath; @Value("${saic.data.templates.logoPath}") private String logoPath; @Autowired private TascaClient tc; @Autowired private OrganClient oc; @Autowired private ProceduresClient pc; @Autowired private IndicadorClient ic; private static final DecimalFormat df = new DecimalFormat("0.00"); public List findAll(){ return this.r.findAll(); } public Plantilla findByID(Integer id) { return this.r.findByIdPlantilla(id); } public Plantilla findByVersioCodiAmbit(Integer versio, String codi, String ambit) { return this.r.findByVersioCodiAmbit(versio, codi, ambit); } public void save(Plantilla p) { this.r.save(p); this.r.flush(); } public void delete(Plantilla p) { this.r.delete(p); } public boolean isUsed(Integer idPlantilla) { List l = this.r.findUsedByIdPlantilla(idPlantilla); if(l.size() > 0) { return true; } return false; } public Plantilla findEvidencia(Integer codiEvidencia, Integer titulacio, String tambit) { Plantilla p = this.findByID(codiEvidencia); Plantilla p2 = null; if(titulacio > 0) { if(!p.getAmbit().equals(tambit)) { p2 = this.findByVersioCodiAmbit(p.getVersio(), p.getCodi(), tambit); } } if(p2 != null) { p = p2; } return p; } public String savePDF(String content, BigInteger idtascai) throws IOException, InterruptedException { content = content.replace("

", "

"); Document d = Jsoup.parse(content, "UTF8"); d.head().append(""); List trs = d.getElementsByTag("tr"); for(Element t : trs) { if(t.hasAttr("height")) { t.removeAttr("height"); } if(t.hasAttr("style")) { String style = t.attr("style"); style = style.replaceAll("height:[ \\d.pxcmin]{1,};", ""); t.attr("style", style); } } List tds = d.getElementsByTag("td"); for(Element t : tds) { if(t.hasAttr("height")) { t.removeAttr("height"); } if(t.hasAttr("style")) { String style = t.attr("style"); style = style.replaceAll("height:[ \\d.pxcmin]{1,};", ""); t.attr("style", style); } } List ignore = d.getElementsByClass("pdfignore"); for(Element e: ignore) { e.remove(); } InstanciaTascaDTO ita = tc.findInstanciaTascaById(idtascai); if(ita.getTasca().getNomRol().equals("u_uq")) { d.body().append(this.parseComments(d.html())); } String basecommand = "google-chrome --headless --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw --no-sandbox"; String dst = idtascai.toString()+".pdf"; File src = File.createTempFile("saic-pdfexport-", ".tmp.html", new File(tmpPath)); src.deleteOnExit(); PrintWriter out = new PrintWriter(src.getAbsolutePath()); out.println(d.html()); out.flush(); out.close(); System.out.println(basecommand+" --print-to-pdf='"+filePath+dst+"' "+src.getAbsolutePath()); ProcessBuilder pb = new ProcessBuilder("bash", "-c", basecommand+" --print-to-pdf='"+filePath+dst+"' "+src.getAbsolutePath()); Process pr = pb.start(); pr.waitFor(); src.delete(); return dst; } public byte[] toPDF(String content, Optional idtascai) throws IOException, InterruptedException { content = content.replace("

", "

"); Document d = Jsoup.parse(content, "UTF8"); d.head().append(""); List trs = d.getElementsByTag("tr"); for(Element t : trs) { if(t.hasAttr("height")) { t.removeAttr("height"); } if(t.hasAttr("style")) { String style = t.attr("style"); style = style.replaceAll("height:[ \\d.pxcmin]{1,};", ""); t.attr("style", style); } } List tds = d.getElementsByTag("td"); for(Element t : tds) { if(t.hasAttr("height")) { t.removeAttr("height"); } if(t.hasAttr("style")) { String style = t.attr("style"); style = style.replaceAll("height:[ \\d.pxcmin]{1,};", ""); t.attr("style", style); } } List ignore = d.getElementsByClass("pdfignore"); for(Element e: ignore) { e.remove(); } if(idtascai.isPresent()) { InstanciaTascaDTO ita = tc.findInstanciaTascaById(idtascai.get()); if(ita.getTasca().getNomRol().equals("u_uq")) { d.body().append(this.parseComments(d.html())); } } d.body().append(this.parseComments(d.html())); String basecommand = "google-chrome --headless --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw --no-sandbox"; File dst = File.createTempFile("saic-pdfpreview-", ".tmp.pdf", new File(tmpPath)); File src = File.createTempFile("saic-pdfpreview-", ".tmp.html", new File(tmpPath)); src.deleteOnExit(); dst.deleteOnExit(); PrintWriter out = new PrintWriter(src.getAbsolutePath()); out.println(d.html()); out.flush(); out.close(); ProcessBuilder pb = new ProcessBuilder("bash", "-c", basecommand+" --print-to-pdf='"+dst+"' "+src.getAbsolutePath()); Process pr = pb.start(); pr.waitFor(); byte[] bytes = Files.readAllBytes(dst.toPath()); src.delete(); dst.delete(); return bytes; } private String parseComments(String content) throws JsonParseException, JsonMappingException, IOException { // Pattern pattern = Pattern.compile("\\<\\!\\-\\-tinycomments\\|2\\.1\\|data\\:application\\/json\\;base64\\,([A-Za-z0-9\\/\\+\\\\]*)\\=*\\-\\-\\>"); Matcher matcher = pattern.matcher(content); String rawComments = ""; if(matcher.find()) { byte[] decoded = Base64.getDecoder().decode(matcher.group(1)); rawComments = new String(decoded, "UTF-8"); if(rawComments.length() < 10) { return ""; } rawComments = rawComments.replaceAll("^.", "["); rawComments = rawComments.replaceAll(".$", "]"); rawComments = rawComments.replaceAll("\"mce-conversation\\_\\d*\":", ""); ObjectMapper mapper = new ObjectMapper(); List comments = mapper.readValue(rawComments, new TypeReference>(){}); String tabComments = "

" + "

COMENTARIOS GENERADOS DURANTE LA REVISIÓN DEL DOCUMENTO

" + "

Nota: Esta página no será visible en la versión final publicada del documento.

" + "" + "" + " " + " " + " " + " " + " " + " " + ""; for(PlantillaConversation conv: comments) { for(PlantillaComentario c: conv.getComments()) { tabComments += (" " + " " + " " + " " + " "); } } tabComments += "
UsuarioNombreComentario
"+c.getAuthor()+""+c.getAuthorName()+""+c.getContent()+"
"; return tabComments; } return ""; } public static String asString(Resource resource) { try (Reader reader = new InputStreamReader(resource.getInputStream(), "UTF-8")) { return FileCopyUtils.copyToString(reader); } catch (IOException e) { throw new UncheckedIOException(e); } } public static String readFileToString(String path) { ResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource(path); return asString(resource); } }