PlantillaService.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. package es.uv.saic.service;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.PrintWriter;
  6. import java.io.Reader;
  7. import java.io.UncheckedIOException;
  8. import java.math.BigInteger;
  9. import java.nio.file.Files;
  10. import java.text.DecimalFormat;
  11. import java.util.Base64;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Optional;
  15. import java.util.regex.Matcher;
  16. import java.util.regex.Pattern;
  17. import org.jsoup.Jsoup;
  18. import org.jsoup.nodes.Document;
  19. import org.jsoup.nodes.Element;
  20. import org.jsoup.select.Elements;
  21. import org.springframework.beans.factory.annotation.Autowired;
  22. import org.springframework.beans.factory.annotation.Value;
  23. import org.springframework.core.io.ClassPathResource;
  24. import org.springframework.core.io.DefaultResourceLoader;
  25. import org.springframework.core.io.Resource;
  26. import org.springframework.core.io.ResourceLoader;
  27. import org.springframework.stereotype.Service;
  28. import org.springframework.util.FileCopyUtils;
  29. import com.fasterxml.jackson.core.JsonParseException;
  30. import com.fasterxml.jackson.core.type.TypeReference;
  31. import com.fasterxml.jackson.databind.JsonMappingException;
  32. import com.fasterxml.jackson.databind.ObjectMapper;
  33. import es.uv.saic.domain.Indicador;
  34. import es.uv.saic.domain.Plantilla;
  35. import es.uv.saic.domain.PlantillaComentario;
  36. import es.uv.saic.domain.PlantillaConversation;
  37. import es.uv.saic.domain.PlantillaRepository;
  38. import es.uv.saic.dto.IndicadorEnquestaDTO;
  39. import es.uv.saic.dto.IndicadorEnquestaValorDTOImp;
  40. import es.uv.saic.dto.InstanciaTascaDTO;
  41. import es.uv.saic.dto.NomProcesOrganDTO;
  42. import es.uv.saic.dto.OrganTransferDTO;
  43. import es.uv.saic.feign.CoreClient;
  44. @Service
  45. public class PlantillaService {
  46. @Autowired
  47. private PlantillaRepository r;
  48. @Value("${saic.data.filePath}")
  49. private String filePath;
  50. @Value("${saic.data.tmpPath}")
  51. private String tmpPath;
  52. @Value("${saic.data.templates.fileNotFound}")
  53. private String fileNotFound;
  54. @Value("${saic.data.templates.filePath}")
  55. private String templatePath;
  56. @Value("${saic.data.templates.logoPath}")
  57. private String logoPath;
  58. @Autowired
  59. private CoreClient core;
  60. private static final DecimalFormat df = new DecimalFormat("0.00");
  61. public List<Plantilla> findAll(){
  62. return this.r.findAll();
  63. }
  64. public Plantilla findByID(Integer id) {
  65. return this.r.findByIdPlantilla(id);
  66. }
  67. public Plantilla findByVersioCodiAmbit(Integer versio, String codi, String ambit) {
  68. return this.r.findByVersioCodiAmbit(versio, codi, ambit);
  69. }
  70. public void save(Plantilla p) {
  71. this.r.save(p);
  72. this.r.flush();
  73. }
  74. public void delete(Plantilla p) {
  75. this.r.delete(p);
  76. }
  77. public boolean isUsed(Integer idPlantilla) {
  78. List<Plantilla> l = this.r.findUsedByIdPlantilla(idPlantilla);
  79. if(l.size() > 0) {
  80. return true;
  81. }
  82. return false;
  83. }
  84. public String addTemplateData(InstanciaTascaDTO it, String template){
  85. HashMap<String, String> context = new HashMap<String, String>();
  86. HashMap<String, String> header = new HashMap<String, String>();
  87. HashMap<String, String> img = new HashMap<String, String>();
  88. Integer idTitulacio = it.getInstancia().getTitulacio();
  89. Integer cursAvaluat = it.getInstancia().getCursAvaluat();
  90. Integer idCentre = it.getInstancia().getCentre();
  91. String ambit = "G";
  92. String opcionsStr = it.getTasca().getOpcions().replaceAll("^\\.$", "");
  93. String [] opcions = new String[0];
  94. if(!opcionsStr.isEmpty()) {
  95. opcions = opcionsStr.split(";");
  96. }
  97. if(it.getInstancia().getTlugar().equals("C")) {
  98. if(it.getInstancia().getTitulacio() == 2) {
  99. ambit = "M";
  100. }
  101. }
  102. /** Add header information **/
  103. addHeaderData(it.getInstancia().getNomval(), it.getInstancia().getLugar(), it.getInstancia().getNomValTitulacio(), it.getInstancia().getCursAvaluat(), header, img);
  104. /** Iterate elements inside {[loop]} ... {[endloop]} **/
  105. template = this.iterateLoopTag(template, idCentre, ambit, cursAvaluat, context);
  106. /** Iterate elements with data-loop attribute **/
  107. Document doc = Jsoup.parse(template);
  108. doc = iterateLoopAttr(idCentre, cursAvaluat, doc, context);
  109. /** Add template data (non iterated data)**/
  110. getTemplateData(idTitulacio, idCentre, cursAvaluat, context);
  111. this.replaceValues(doc, context, header, img);
  112. /** Replace sections if specified in options **/
  113. this.replaceSection(opcions, it, doc);
  114. return doc.html();
  115. }
  116. public String addTemplateData(Integer idTitulacio, Integer idCentre, Integer curs, String template){
  117. HashMap<String, String> context = new HashMap<String, String>();
  118. HashMap<String, String> header = new HashMap<String, String>();
  119. HashMap<String, String> img = new HashMap<String, String>();
  120. OrganTransferDTO centre = core.findOrganById("C", idCentre);
  121. OrganTransferDTO titulacio = core.findOrganById("T", idTitulacio);
  122. /** Add header information **/
  123. addHeaderData(centre.getNomVal(), centre.getLugarCentre(), titulacio.getNomVal(), curs, header, img);
  124. /** Iterate elements inside {[loop]} ... {[endloop]} **/
  125. template = this.iterateLoopTag(template, idCentre, titulacio.getTambit(), curs, context);
  126. /** Iterate elements with data-loop attribute **/
  127. Document doc = Jsoup.parse(template);
  128. doc = iterateLoopAttr(idCentre, curs, doc, context);
  129. /** Add template data (non iterated data)**/
  130. getTemplateData(idTitulacio, idCentre, curs, context);
  131. this.replaceValues(doc, context, header, img);
  132. return doc.html();
  133. }
  134. private void addHeaderData(String nomVal, Integer lugar, String nomValTitulacion, Integer curs, HashMap<String, String> header, HashMap<String, String> img) {
  135. header.put("centre", nomVal);
  136. header.put("titulacio", nomValTitulacion);
  137. header.put("curs", "CURSO "+Integer.toString(curs-1)+" - "+Integer.toString(curs));
  138. header.put("curs_anterior", Integer.toString(curs-2)+" - "+Integer.toString(curs-1));
  139. header.put("conv-ant1", "CONVOCATORIA "+Integer.toString(curs-1)+" - "+Integer.toString(curs));
  140. header.put("conv-ant2", "CONVOCATORIA "+Integer.toString(curs-2)+" - "+Integer.toString(curs-1));
  141. header.put("periode-ant1", Integer.toString(curs-6)+" - "+Integer.toString(curs-1));
  142. header.put("periode-ant2", Integer.toString(curs-7)+" - "+Integer.toString(curs-2));
  143. ClassPathResource fuv = new ClassPathResource("/static/logos/UV.png");
  144. ClassPathResource fc = new ClassPathResource("/static/logos/C"+Integer.toString(lugar)+".png");
  145. String logouv_b64;
  146. String logoc_b64;
  147. try {
  148. logouv_b64 = "data:image/png;base64, "+Base64.getEncoder().encodeToString(fuv.getInputStream().readAllBytes());
  149. } catch (IOException e) {
  150. logouv_b64 = "https://saic.uv.es/public/logos/UV.png";
  151. }
  152. try {
  153. logoc_b64 = "data:image/png;base64, "+Base64.getEncoder().encodeToString(fc.getInputStream().readAllBytes());
  154. } catch (IOException e) {
  155. logoc_b64 = "https://saic.uv.es/public/logos/C"+Integer.toString(lugar)+".png";
  156. }
  157. img.put("logo_centre", logoc_b64);
  158. img.put("logo_uv", logouv_b64);
  159. }
  160. private Document iterateLoopAttr(Integer idCentre, Integer curs, Document doc, HashMap<String, String> context) {
  161. Elements loop_elements = doc.select("*[data-loop]");
  162. for(Element e : loop_elements) {
  163. String Tambit = e.attr("data-loop");
  164. List<OrganTransferDTO> tits = core.getTitulacionsByCentreTambit(idCentre, Tambit);
  165. for(OrganTransferDTO org : tits) {
  166. context.clear();
  167. Element e_copy = e.clone();
  168. getTemplateData(org.getLugarTitulacion(), org.getLugarCentre(), curs, context);
  169. context.put("titulacio_loop", org.getNomVal());
  170. Elements ielements = e_copy.select("*:matchesWholeOwnText(\\{\\{([^\\}]*)\\}\\})");
  171. for(Element ielem : ielements) {
  172. String t = ielem.html().replace("{", "").replace("}", "");
  173. String i = this.formatValue(context.get(t));
  174. if(i != null) {
  175. if(ielem.tagName().equals("td")) {
  176. ielem.attr("class", "mceEditable");
  177. ielem.attr("id", "ind_"+t);
  178. ielem.html(i);
  179. }
  180. else {
  181. ielem.html(i);
  182. }
  183. }
  184. else {
  185. if(ielem.tagName().equals("td")) {
  186. ielem.attr("class", "mceEditable");
  187. ielem.attr("id", "ind_"+t);
  188. ielem.html("");
  189. }
  190. else {
  191. ielem.html("");
  192. }
  193. }
  194. }
  195. e.after(e_copy);
  196. }
  197. e.remove();
  198. }
  199. context.clear();
  200. return doc;
  201. }
  202. private String iterateLoopTag(String template, Integer idCentre, String Tambit, Integer curs, HashMap<String, String> context) {
  203. Pattern pattern = Pattern.compile(".*<p>\\{\\[loop\\]\\}</p>([\\S\\s]*)<p>\\{\\[endloop\\]\\}</p>.*");
  204. Matcher matcher = pattern.matcher(template);
  205. String replaced = "";
  206. while(matcher.find()) {
  207. String group = matcher.group(1);
  208. Document tab = Jsoup.parse(group);
  209. List<OrganTransferDTO> tits = core.getTitulacionsByCentreTambit(idCentre, Tambit);
  210. for(OrganTransferDTO t : tits) {
  211. Document tabcopy = Jsoup.parse(tab.html());
  212. context.clear();
  213. getTemplateData(t.getLugarTitulacion(), t.getLugarCentre(), curs, context);
  214. context.put("titulacio_loop", t.getNomVal());
  215. tabcopy = this.replaceValuesLoop(tabcopy, context);
  216. replaced += tabcopy.html()+"<p></p>";
  217. }
  218. template = template.replace("<p>{[loop]}</p>"+group+"<p>{[endloop]}</p>", replaced);
  219. }
  220. context.clear();
  221. return template;
  222. }
  223. private Document replaceValues(Document doc, HashMap<String, String> context, HashMap<String, String> header, HashMap<String, String> img) {
  224. Elements elems = doc.select("*:matchesWholeOwnText(\\{\\{([^\\}]*)\\}\\})");
  225. for(Element e : elems) {
  226. String t = e.html().replace("{", "").replace("}", "");
  227. if(header.containsKey(t)) {
  228. e.html(header.get(t));
  229. }
  230. else if(img.containsKey(t)) {
  231. Element x = new Element("img");
  232. x.attr("src", img.get(t));
  233. x.attr("style", "display:block; margin-left:auto; margin-right:auto; width:100px; max-width:100px;");
  234. x.attr("class", "logo");
  235. e.html("");
  236. e.appendChild(x);
  237. }
  238. else {
  239. String i = this.formatValue(context.get(t));
  240. if(i != null) {
  241. if(e.parent().tagName().equals("td")) {
  242. e.parent().attr("class", "mceEditable");
  243. e.parent().attr("id", "ind_"+t);
  244. e.parent().attr("style", e.attr("style"));
  245. e.parent().html(i);
  246. }
  247. else {
  248. e.attr("class", "mceEditable");
  249. e.attr("ind", "ind_"+t);
  250. e.html(i);
  251. }
  252. }
  253. else {
  254. if(e.parent().tagName().equals("td")) {
  255. e.parent().attr("class", "mceEditable");
  256. e.parent().attr("id", "ind_"+t);
  257. e.parent().attr("style", e.attr("style"));
  258. e.parent().html("");
  259. }
  260. else {
  261. e.attr("class", "mceEditable");
  262. e.attr("ind", "ind_"+t);
  263. e.html("");
  264. }
  265. }
  266. }
  267. }
  268. return doc;
  269. }
  270. private void getTemplateData(Integer idTitulacio, Integer idCentre, Integer curs, HashMap<String, String> context) {
  271. /* Indicadores del data warehouse */
  272. try {
  273. List<Indicador> indicadores;
  274. indicadores = core.getFromTitulacion(idTitulacio, curs);
  275. for(Indicador i : indicadores) {
  276. context.put(i.getIndicador(), i.getValor());
  277. }
  278. }
  279. catch(Exception e) { }
  280. /* Indicadores de encuestas y otros almacenados en BD */
  281. IndicadorEnquestaDTO indicadorEnquestaDTO = new IndicadorEnquestaDTO(idTitulacio, idCentre, curs);
  282. List<IndicadorEnquestaValorDTOImp> enquestesT = core.getAllInds2(indicadorEnquestaDTO);
  283. for(IndicadorEnquestaValorDTOImp i : enquestesT) {
  284. String indicador = i.getAmbit().toLowerCase().equals("t") ? (i.getEnquesta().toLowerCase()+"_"+i.getIndicador().toLowerCase()) : (i.getEnquesta().toLowerCase()+"_"+i.getIndicador().toLowerCase()+"_"+i.getAmbit().toLowerCase());
  285. if(i.getNum() == null) {
  286. indicador = i.getTipus().toLowerCase().equals("avg") ? indicador : (indicador += "_"+i.getTipus().toLowerCase());
  287. indicador = i.getCursd() == null ? indicador : (indicador += "_"+i.getCursd().toLowerCase());
  288. context.put(indicador, formatValue(i.getValor()));
  289. }
  290. else {
  291. context.put(indicador, i.getNum());
  292. }
  293. }
  294. }
  295. private Document replaceValuesLoop(Document doc, HashMap<String, String> context) {
  296. Elements elems = doc.select("*:matchesWholeOwnText(\\{\\{([^\\}]*)\\}\\})");
  297. for(Element e : elems) {
  298. String t = e.html().replace("{", "").replace("}", "");
  299. String i = this.formatValue(context.get(t));
  300. if(i != null) {
  301. if(e.parent().tagName().equals("td")) {
  302. e.parent().attr("class", "mceEditable");
  303. e.parent().attr("id", "ind_"+t);
  304. e.parent().attr("style", e.attr("style"));
  305. e.parent().html(i);
  306. }
  307. else {
  308. e.attr("class", "mceEditable");
  309. e.attr("ind", "ind_"+t);
  310. e.html(i);
  311. }
  312. }
  313. else {
  314. if(e.parent().tagName().equals("td")) {
  315. e.parent().attr("class", "mceEditable");
  316. e.parent().attr("id", "ind_"+t);
  317. e.parent().attr("style", e.attr("style"));
  318. e.parent().html("");
  319. }
  320. else {
  321. e.attr("class", "mceEditable");
  322. e.attr("ind", "ind_"+t);
  323. e.html("");
  324. }
  325. }
  326. }
  327. return doc;
  328. }
  329. private String formatValue(String v) {
  330. if(v == null) return "";
  331. if(v.isEmpty() | v.isBlank()) return "";
  332. if(v.equals("NP")) return "NP";
  333. try {
  334. double d = Double.parseDouble(v);
  335. return (Integer.toString((int)d).equals(v) ? v : df.format(d).replace(",", "."));
  336. }
  337. catch (NumberFormatException e) { }
  338. if(v.endsWith("%") && v.startsWith(".")) {
  339. return "0"+v;
  340. }
  341. return v;
  342. }
  343. public String savePDF(String content, BigInteger idtascai) throws IOException, InterruptedException {
  344. content = content.replace("<p><!-- pagebreak --></p>", "<p class=\"pagebreak\"><!-- pagebreak --></p>");
  345. Document d = Jsoup.parse(content, "UTF8");
  346. d.head().append("<style>"
  347. + "@page{size: 297mm 210mm;} "
  348. + "html{ max-width:297mm; max-height:210mm; margin:0; padding:0; transform:scale(0.925); transform-origin:left top; } "
  349. + "table { padding:2px !important; }"
  350. + "th, td { padding:2px !important; }"
  351. + ".pagebreak { page-break-before:always; }"
  352. + "</style>");
  353. List<Element> trs = d.getElementsByTag("tr");
  354. for(Element t : trs) {
  355. if(t.hasAttr("height")) {
  356. t.removeAttr("height");
  357. }
  358. if(t.hasAttr("style")) {
  359. String style = t.attr("style");
  360. style = style.replaceAll("height:[ \\d.pxcmin]{1,};", "");
  361. t.attr("style", style);
  362. }
  363. }
  364. List<Element> tds = d.getElementsByTag("td");
  365. for(Element t : tds) {
  366. if(t.hasAttr("height")) {
  367. t.removeAttr("height");
  368. }
  369. if(t.hasAttr("style")) {
  370. String style = t.attr("style");
  371. style = style.replaceAll("height:[ \\d.pxcmin]{1,};", "");
  372. t.attr("style", style);
  373. }
  374. }
  375. List<Element> ignore = d.getElementsByClass("pdfignore");
  376. for(Element e: ignore) {
  377. e.remove();
  378. }
  379. InstanciaTascaDTO ita = core.findInstanciaTascaById2(idtascai);
  380. if(ita.getTasca().getNomRol().equals("u_uq")) {
  381. d.body().append(this.parseComments(d.html()));
  382. }
  383. String basecommand = "google-chrome --headless --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw --no-sandbox";
  384. String dst = idtascai.toString()+".pdf";
  385. File src = File.createTempFile("saic-pdfexport-", ".tmp.html", new File(tmpPath));
  386. src.deleteOnExit();
  387. PrintWriter out = new PrintWriter(src.getAbsolutePath());
  388. out.println(d.html());
  389. out.flush();
  390. out.close();
  391. System.out.println(basecommand+" --print-to-pdf='"+filePath+dst+"' "+src.getAbsolutePath());
  392. ProcessBuilder pb = new ProcessBuilder("bash", "-c", basecommand+" --print-to-pdf='"+filePath+dst+"' "+src.getAbsolutePath());
  393. Process pr = pb.start();
  394. pr.waitFor();
  395. src.delete();
  396. return dst;
  397. }
  398. public byte[] toPDF(String content, Optional<BigInteger> idtascai) throws IOException, InterruptedException {
  399. content = content.replace("<p><!-- pagebreak --></p>", "<p class=\"pagebreak\"><!-- pagebreak --></p>");
  400. Document d = Jsoup.parse(content, "UTF8");
  401. d.head().append("<style>"
  402. + "@page{size: 297mm 210mm;} "
  403. + "html{ max-width:297mm; max-height:210mm; margin:0; padding:0; transform:scale(0.925); transform-origin:left top; } "
  404. + "table { padding:2px !important; }"
  405. + "th, td { padding:2px !important; }"
  406. + ".pagebreak { page-break-before:always; }"
  407. + "</style>");
  408. List<Element> trs = d.getElementsByTag("tr");
  409. for(Element t : trs) {
  410. if(t.hasAttr("height")) {
  411. t.removeAttr("height");
  412. }
  413. if(t.hasAttr("style")) {
  414. String style = t.attr("style");
  415. style = style.replaceAll("height:[ \\d.pxcmin]{1,};", "");
  416. t.attr("style", style);
  417. }
  418. }
  419. List<Element> tds = d.getElementsByTag("td");
  420. for(Element t : tds) {
  421. if(t.hasAttr("height")) {
  422. t.removeAttr("height");
  423. }
  424. if(t.hasAttr("style")) {
  425. String style = t.attr("style");
  426. style = style.replaceAll("height:[ \\d.pxcmin]{1,};", "");
  427. t.attr("style", style);
  428. }
  429. }
  430. List<Element> ignore = d.getElementsByClass("pdfignore");
  431. for(Element e: ignore) {
  432. e.remove();
  433. }
  434. if(idtascai.isPresent()) {
  435. InstanciaTascaDTO ita = core.findInstanciaTascaById2(idtascai.get());
  436. if(ita.getTasca().getNomRol().equals("u_uq")) {
  437. d.body().append(this.parseComments(d.html()));
  438. }
  439. }
  440. d.body().append(this.parseComments(d.html()));
  441. String basecommand = "google-chrome --headless --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw --no-sandbox";
  442. File dst = File.createTempFile("saic-pdfpreview-", ".tmp.pdf", new File(tmpPath));
  443. File src = File.createTempFile("saic-pdfpreview-", ".tmp.html", new File(tmpPath));
  444. src.deleteOnExit();
  445. dst.deleteOnExit();
  446. PrintWriter out = new PrintWriter(src.getAbsolutePath());
  447. out.println(d.html());
  448. out.flush();
  449. out.close();
  450. ProcessBuilder pb = new ProcessBuilder("bash", "-c", basecommand+" --print-to-pdf='"+dst+"' "+src.getAbsolutePath());
  451. Process pr = pb.start();
  452. pr.waitFor();
  453. byte[] bytes = Files.readAllBytes(dst.toPath());
  454. src.delete();
  455. dst.delete();
  456. return bytes;
  457. }
  458. private String parseComments(String content) throws JsonParseException, JsonMappingException, IOException {
  459. // <!--tinycomments\|2\.1\|data:application\/json;base64,([A-Za-z0-9]*)=-->
  460. Pattern pattern = Pattern.compile("\\<\\!\\-\\-tinycomments\\|2\\.1\\|data\\:application\\/json\\;base64\\,([A-Za-z0-9\\/\\+\\\\]*)\\=*\\-\\-\\>");
  461. Matcher matcher = pattern.matcher(content);
  462. String rawComments = "";
  463. if(matcher.find()) {
  464. byte[] decoded = Base64.getDecoder().decode(matcher.group(1));
  465. rawComments = new String(decoded, "UTF-8");
  466. if(rawComments.length() < 10) {
  467. return "";
  468. }
  469. rawComments = rawComments.replaceAll("^.", "[");
  470. rawComments = rawComments.replaceAll(".$", "]");
  471. rawComments = rawComments.replaceAll("\"mce-conversation\\_\\d*\":", "");
  472. ObjectMapper mapper = new ObjectMapper();
  473. List<PlantillaConversation> comments = mapper.readValue(rawComments, new TypeReference<List<PlantillaConversation>>(){});
  474. String tabComments = "<p class=\"pagebreak\"><!-- pagebreak --></p>"
  475. + "<h3>COMENTARIOS GENERADOS DURANTE LA REVISIÓN DEL DOCUMENTO</h3>"
  476. + "<h3><small>Nota: Esta página no será visible en la versión final publicada del documento.</small></h3>"
  477. + "<table style=\"border-collapse: collapse; width: 297mm; border-width: 1px; border-spacing: 0px; border-color: rgb(149, 165, 166); margin-left: 0px; margin-right: auto;\" border=\"1\" width=\"297mm\" cellspacing=\"0\" cellpadding=\"8\">"
  478. + "<thead>"
  479. + " <tr style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166);\" bgcolor=\"#153d63\">"
  480. + " <th style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166); color:white;\" scope=\"col\">Usuario</th>"
  481. + " <th style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166); color:white;\" scope=\"col\">Nombre</th>"
  482. + " <th style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166); color:white;\" scope=\"col\">Comentario</th>"
  483. + " </tr>"
  484. + " </thead>"
  485. + "<tbody>";
  486. for(PlantillaConversation conv: comments) {
  487. for(PlantillaComentario c: conv.getComments()) {
  488. tabComments += ("<tr style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166);\"> "
  489. + " <td style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166);\">"+c.getAuthor()+"</td>"
  490. + " <td style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166);\">"+c.getAuthorName()+"</td>"
  491. + " <td style=\"padding: 0px; border-width: 1px; border-color: rgb(149, 165, 166);\">"+c.getContent()+"</td>"
  492. + "</tr> ");
  493. }
  494. }
  495. tabComments += "</tbody></table>";
  496. return tabComments;
  497. }
  498. return "";
  499. }
  500. public Document replaceSection(String[] opcions, InstanciaTascaDTO it, Document doc) {
  501. if(opcions.length > 0) {
  502. NomProcesOrganDTO nomProcesOrganDTO = new NomProcesOrganDTO(opcions[0],
  503. it.getInstancia().getTlugar(),
  504. it.getInstancia().getLugar(),
  505. it.getInstancia().getCentre(),
  506. it.getInstancia().getTitulacio());
  507. InstanciaTascaDTO itOld = core.getReportFromNomProcesOrgan(nomProcesOrganDTO);
  508. try {
  509. Document doc2 = Jsoup.parse(itOld.getText());
  510. Elements target = null;
  511. Elements source = null;
  512. if(opcions.length == 2) {
  513. target = this.extractTemplateAnchor(doc2, true, opcions[1]);
  514. source = this.extractTemplateAnchor(doc, false, opcions[1]);
  515. }
  516. else {
  517. target = this.extractTemplateAnchor(doc2, true, opcions[1], opcions[2]);
  518. source = this.extractTemplateAnchor(doc, false, opcions[1], opcions[2]);
  519. }
  520. if(target == null || source == null) {
  521. return doc;
  522. }
  523. Element e = source.get(0);
  524. e.before(this.clear(target.outerHtml()));
  525. source.remove();
  526. }
  527. catch(NullPointerException e){
  528. System.out.println("No previous version found for "+it.getIdInstanciaTasca().toString());
  529. }
  530. }
  531. return doc;
  532. }
  533. public Elements extractTemplateAnchor(Document doc, Boolean target, String... args) {
  534. // <a id="pam"></a>
  535. /* Hardcoded to fix anchor positions in existing templates */
  536. try{
  537. String anchor_ini = args[0];
  538. Element eFirst = doc.select("p:has(a#"+anchor_ini+")").first();
  539. Elements elems = eFirst.nextElementSiblings();
  540. Elements table = elems.select("table:not(.pdfignore)");
  541. return table;
  542. }
  543. catch(Exception e){
  544. return null;
  545. }
  546. /* Use this code in future */
  547. /*
  548. if(args.length == 2){
  549. String anchor_end = args[1];
  550. Element eLast = doc.select("p:has(a#"+anchor_end+")").first();
  551. boolean remove = false;
  552. for(Iterator<Element> iter = elems.iterator(); iter.hasNext();){
  553. Element x = iter.next();
  554. if(remove){
  555. iter.remove();
  556. }
  557. if(x.id().equals(anchor_end) || x.html().contains(anchor_end)){
  558. remove = true;
  559. }
  560. }
  561. }
  562. */
  563. }
  564. public String clear(String html){
  565. return html.replaceAll("data-mce-style=\"[ ,;:.\\d\\w\\(\\)\\#\\%-]{1,}\"", "")
  566. .replaceAll("font-family:[ \\d\\w-,]{1,};", "")
  567. .replaceAll("font-size:[ \\d\\w,\\.]{1,};", "")
  568. .replaceAll("\\<\\!\\-\\-tinycomments\\|2\\.1\\|data\\:application\\/json\\;base64\\,[A-Za-z0-9\\/\\+\\\\]*\\=*\\-\\-\\>", "")
  569. .replaceAll("data\\-mce\\-annotation\\-uid\\=\"mce\\-conversation\\_[a-zA-Z0-9]+\"", "")
  570. .replaceAll("data\\-mce\\-annotation\\=\"tinycomments\"", "")
  571. .replaceAll("class=\"mce-annotation\"", "");
  572. }
  573. public static String asString(Resource resource) {
  574. try (Reader reader = new InputStreamReader(resource.getInputStream(), "UTF-8")) {
  575. return FileCopyUtils.copyToString(reader);
  576. } catch (IOException e) {
  577. throw new UncheckedIOException(e);
  578. }
  579. }
  580. public static String readFileToString(String path) {
  581. ResourceLoader resourceLoader = new DefaultResourceLoader();
  582. Resource resource = resourceLoader.getResource(path);
  583. return asString(resource);
  584. }
  585. }