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

com.xlrit.gears.plugin.jasper.JasperDocumentProcessor Maven / Gradle / Ivy

package com.xlrit.gears.plugin.jasper;

import java.io.*;
import java.nio.file.Files;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import com.xlrit.gears.engine.meta.PrintOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xlrit.gears.base.content.ContentRef;
import com.xlrit.gears.base.model.Document;
import com.xlrit.gears.base.content.ContentStore;
import com.xlrit.gears.engine.document.DocumentProcessor;
import com.xlrit.gears.engine.meta.MetaManager;

import lombok.RequiredArgsConstructor;
import net.sf.jasperreports.engine.*;

@Component
@Order(200)
@RequiredArgsConstructor
public class JasperDocumentProcessor implements DocumentProcessor {
	private static final Logger LOG = LoggerFactory.getLogger(JasperDocumentProcessor.class);

	private final JasperProperties properties;
	private final MetaManager metaManager;
	private final ContentStore contentStore;
	private final ObjectMapper objectMapper;
	private final JasperExportManager exportManager = JasperExportManager.getInstance(DefaultJasperReportsContext.getInstance());

	@Override
	public boolean supports(Document doc) {
		return "pdf".equals(doc.getType())
		    && doc.getTemplate() != null
		    && doc.getTemplate().endsWith(".jrxml");
	}

	@Override
	public ContentRef process(Document doc) {
		if (properties.isDebug()) {
			properties.getDir().mkdirs();
			writeParametersAsJson(doc);
			writeExampleTemplate(doc);
		}

		try {
			JasperReport report = getReportTemplate(doc.getTemplate());

			JRDataSource dataSource = createDataSource(doc.getParameters());
			Map params = new HashMap<>();

			JasperPrint print = JasperFillManager.fillReport(report, params, dataSource);

			byte[] data = exportReport(print, doc.getType());
			if (properties.isDebug()) {
				writeToFile(doc, data);
			}
			return contentStore.putContent(doc.getFilename(), getContentType(doc.getType()), data);
		}
		catch (JRException e) {
			throw new RuntimeException("Unable to create report document", e);
		}
	}

	private String getContentType(String documentType) {
        return switch (documentType) {
            case "pdf" -> "application/pdf";
            case "xml" -> "application/xml";
            default    -> throw new RuntimeException("Unsupported document type: " + documentType);
        };
	}

	private byte[] exportReport(JasperPrint print, String type) throws JRException {
		try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
			exportReport(print, type, os);
			os.flush();
			return os.toByteArray();
		}
		catch (IOException e) {
			throw new RuntimeException("Unable to export to byte array output stream", e);
		}
	}

	private void exportReport(JasperPrint print, String type, OutputStream outputStream) throws JRException {
		switch (type) {
			case "pdf" -> exportManager.exportToPdfStream(print, outputStream);
			case "xml" -> exportManager.exportToXmlStream(print, outputStream);
			default    -> throw new RuntimeException("Unsupported document type: " + type);
		}
	}

	private JasperReport getReportTemplate(String resourceName) {
		Resource template = new ClassPathResource(resourceName);
		try (InputStream is = template.getInputStream()) {
			return JasperCompileManager.compileReport(is);
		}
		catch (IOException | JRException e) {
			throw new RuntimeException("Unable to load report template '" + resourceName + "'", e);
		}
	}

	private JRDataSource createDataSource(Object parameters) {
        return switch (properties.getDatasource()) {
            case DEFAULT -> createDefaultDataSource(parameters);
            case JSON    -> createJsonDataSource(parameters);
            default      -> throw new UnsupportedOperationException("Unknown datasource mode: " + properties.getDatasource());
        };
	}

	private CustomCollectionDataSource createDefaultDataSource(Object parameters) {
		Collection collection =
			parameters instanceof Collection
				? (Collection) parameters
				: Collections.singletonList(parameters);

		return new CustomCollectionDataSource(metaManager, collection);
	}

	private CustomJsonQLDataSource createJsonDataSource(Object parameters) {
		try {
			JsonNode json = toJson(parameters);
			return new CustomJsonQLDataSource(json, null);
		}
		catch (JRException e) {
			throw new RuntimeException(e);
		}
	}

	private void writeParametersAsJson(Document doc) {
		try {
			JsonNode json = toJson(doc.getParameters());

			File file = new File(properties.getDir(), doc.getFilename() + ".json");
			LOG.info("Writing document parameters as JSON to {}", file);
			objectMapper.writeValue(file, json);
		}
		catch (JsonProcessingException e) {
			throw new RuntimeException(e);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private void writeExampleTemplate(Document doc) {
		ExampleTemplateWriter exampleTemplateWriter = new ExampleTemplateWriter(metaManager);
		exampleTemplateWriter.processParameters(doc.getParameters());
		exampleTemplateWriter.print();
	}

	private void writeToFile(Document doc, byte[] data) {
		try {
			File file = new File(properties.getDir(), doc.getFilename());
			LOG.info("Writing result to {}", file.getAbsolutePath());
			Files.write(file.toPath(), data);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private JsonNode toJson(Object params) {
		return metaManager.requireTypeInfo(params).serialize(params, objectMapper, PrintOptions.NONE);
	}
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy