| 
					
				 | 
			
			
				@@ -1,15 +1,31 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package co.id.datacomsolusindo.engineservice.report 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.export.FileHtmlResourceHandler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.export.HtmlExporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.export.JRCsvExporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.export.JRPdfExporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.fill.JRSwapFileVirtualizer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.util.FileBufferedOutputStream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.engine.util.JRSwapFile 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.jasperreports.export.* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.beans.factory.annotation.Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.beans.factory.annotation.Value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.springframework.core.annotation.Order 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.springframework.stereotype.Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.File 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.io.IOException 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.io.InputStream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.io.OutputStream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.nio.file.Files 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.nio.file.Path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.nio.file.Paths 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.nio.file.StandardCopyOption 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.sql.DriverManager 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.UUID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.zip.ZipEntry 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.zip.ZipOutputStream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class ReportService(rptService: RptService) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ReportService(val rptService: RptService) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Value("\${spring.datasource.url}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lateinit var jdbcUrl: String 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -26,8 +42,6 @@ class ReportService(rptService: RptService) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val projectDir = System.getProperty("user.dir") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val pathResult = "$projectDir/${rptService.pathResult}" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val pathPreview = "$projectDir/${rptService.pathPreview}" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//    private val pathResult = "$projectDir/result" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//    private val pathPreview = "$projectDir/preview" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val logger = ReportLogger.getLogger(this::class.java) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -62,7 +76,7 @@ class ReportService(rptService: RptService) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private fun generateReport(params: MutableMap<String, Any>, isPreview: Boolean = false): ByteArray? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private fun generateReport(params: MutableMap<String, Any>, isPreview: Boolean = false): InputStream? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         val userSubmitted = params["userSubmitted"].toString() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         val reportJob = ReportJob(userSubmitted = userSubmitted, criteria = U.mapper.writeValueAsString(params)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         val exist = reportJobRepository.findByJobKeyAndUserSubmitted(reportJob.jobKey, reportJob.userSubmitted) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -81,14 +95,110 @@ class ReportService(rptService: RptService) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return existReport?.readBytes()?.let { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return existReport?.inputStream()?.let { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // update reportJob 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val rpt = exist.get() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } ?: run { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val templateFile = "${rptService.pathTemplate}/${params["templateName"]}" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val jasperReport = JasperCompileManager.compileReport(templateFile.byteInputStream()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            generateReportFile(jasperReport, formatType, params) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private fun generateReportFile( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jasperReport: JasperReport, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        formatType: FormatType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        paramReport: MutableMap<String, Any> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ): InputStream? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        val os = FileBufferedOutputStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DriverManager.getConnection(jdbcUrl, dbUser, dbPass).use { connection -> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val jasperPrint = JasperFillManager.fillReport(jasperReport, paramReport, connection) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val unique = UUID.randomUUID().toString() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val tmpDir = "report/swap" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                File(tmpDir).mkdirs() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val vrt = JRSwapFile(tmpDir, 1024, 1024) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val reportVirT: JRVirtualizer = JRSwapFileVirtualizer(10, vrt, true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                paramReport[JRParameter.REPORT_VIRTUALIZER] = reportVirT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                val exporter = when (formatType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    FormatType.PDF, FormatType.SCREEN -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val exporter = JRPdfExporter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        exporter.exporterOutput = SimpleOutputStreamExporterOutput(os) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        exporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    FormatType.CSV -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val cs = SimpleCsvExporterConfiguration() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        cs.forceFieldEnclosure = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        cs.isWriteBOM = true // For UTF-8 BOM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        cs.fieldDelimiter = "," // Bisa juga pakai ; kalau regional 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val csvExporter = JRCsvExporter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        csvExporter.setConfiguration(cs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        csvExporter.exporterOutput = SimpleWriterExporterOutput(os) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        csvExporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    FormatType.XLSX -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val exporter = JRXlsxExporter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        exporter.exporterOutput = SimpleOutputStreamExporterOutput(os) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        exporter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    FormatType.HTML -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!File(".tmp/$unique").exists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            File(".tmp/$unique").mkdirs() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        //reportGenerateId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val file = File(".tmp/$unique/${paramReport["templateName"]}.html") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val htmlExp = HtmlExporter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val configuration = SimpleHtmlExporterConfiguration() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        htmlExp.setConfiguration(configuration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val exporterOutput = SimpleHtmlExporterOutput(file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val resourcesDir = File(file.parent, file.name.toString() + "_images") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        val pathPattern = resourcesDir.name + "/{0}" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        exporterOutput.imageHandler = FileHtmlResourceHandler(resourcesDir, pathPattern) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        htmlExp.exporterOutput = exporterOutput 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        htmlExp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                exporter.setExporterInput(SimpleExporterInput(jasperPrint)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                exporter.exportReport() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (formatType == FormatType.HTML) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    pack(".tmp/$unique", os) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return os.dataInputStream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (e: Exception) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                logger.error("failed to generate report", e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw (e) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } finally { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                os.flush() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                os.close() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private fun pack(sourceDirPath: String, os: OutputStream): OutputStream { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ZipOutputStream(os).use { zs -> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val pp: Path = Paths.get(sourceDirPath) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Files.walk(pp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter { path -> !Files.isDirectory(path) } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach { path -> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    val zipEntry = ZipEntry(pp.relativize(path).toString()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        zs.putNextEntry(zipEntry) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        Files.copy(path, zs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        zs.closeEntry() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } catch (e: IOException) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        logger.error("failed zip pack", e) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return os 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |