1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.kuali.kfs.sys.service.impl;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.text.MessageFormat;
28 import java.util.Arrays;
29 import java.util.Date;
30 import java.util.List;
31 import java.util.Map;
32
33 import net.sf.jasperreports.engine.JRDataSource;
34 import net.sf.jasperreports.engine.JRException;
35 import net.sf.jasperreports.engine.JasperCompileManager;
36 import net.sf.jasperreports.engine.JasperRunManager;
37 import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
38
39 import org.apache.commons.lang.StringUtils;
40 import org.kuali.kfs.sys.KFSConstants;
41 import org.kuali.kfs.sys.KFSConstants.ReportGeneration;
42 import org.kuali.kfs.sys.service.ReportGenerationService;
43 import org.kuali.rice.core.api.datetime.DateTimeService;
44 import org.springframework.core.io.ClassPathResource;
45 import org.springframework.ui.jasperreports.JasperReportsUtils;
46
47
48
49
50 public class ReportGenerationServiceImpl implements ReportGenerationService {
51 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ReportGenerationServiceImpl.class);
52
53 protected DateTimeService dateTimeService;
54
55 public final static String PARAMETER_NAME_SUBREPORT_DIR = ReportGeneration.PARAMETER_NAME_SUBREPORT_DIR;
56 public final static String PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME = ReportGeneration.PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME;
57
58 public final static String DESIGN_FILE_EXTENSION = ReportGeneration.DESIGN_FILE_EXTENSION;
59 public final static String JASPER_REPORT_EXTENSION = ReportGeneration.JASPER_REPORT_EXTENSION;
60 public final static String PDF_FILE_EXTENSION = ReportGeneration.PDF_FILE_EXTENSION;
61
62 public final static String SEPARATOR = "/";
63
64
65
66
67 public void generateReportToPdfFile(Map<String, Object> reportData, String template, String reportFileName) {
68 List<String> data = Arrays.asList(KFSConstants.EMPTY_STRING);
69 JRDataSource dataSource = new JRBeanCollectionDataSource(data);
70
71 generateReportToPdfFile(reportData, dataSource, template, reportFileName);
72 }
73
74
75
76
77
78
79
80 public void generateReportToPdfFile(Map<String, Object> reportData, Object dataSource, String template, String reportFileName) {
81 ClassPathResource resource = getReportTemplateClassPathResource(template);
82 if (resource == null || !resource.exists()) {
83 throw new IllegalArgumentException("Cannot find the template file: " + template);
84 }
85
86 try {
87 if (reportData != null && reportData.containsKey(PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME)) {
88 Map<String, String> subReports = (Map<String, String>) reportData.get(PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME);
89 String subReportDirectory = (String) reportData.get(PARAMETER_NAME_SUBREPORT_DIR);
90 compileSubReports(subReports, subReportDirectory);
91 }
92
93 String realTemplateNameWithoutExtension = removeTemplateExtension(resource);
94 String designTemplateName = realTemplateNameWithoutExtension.concat(DESIGN_FILE_EXTENSION);
95 String jasperReportName = realTemplateNameWithoutExtension.concat(JASPER_REPORT_EXTENSION);
96 compileReportTemplate(designTemplateName, jasperReportName);
97
98 JRDataSource jrDataSource = JasperReportsUtils.convertReportData(dataSource);
99
100 reportFileName = reportFileName + PDF_FILE_EXTENSION;
101 File reportDirectory = new File(StringUtils.substringBeforeLast(reportFileName, SEPARATOR));
102 if(!reportDirectory.exists()) {
103 reportDirectory.mkdir();
104 }
105
106 JasperRunManager.runReportToPdfFile(jasperReportName, reportFileName, reportData, jrDataSource);
107 }
108 catch (Exception e) {
109 LOG.error(e);
110 throw new RuntimeException("Fail to generate report.", e);
111 }
112 }
113
114
115
116
117
118 public void generateReportToOutputStream(Map<String, Object> reportData, Object dataSource, String template, ByteArrayOutputStream baos) {
119 ClassPathResource resource = getReportTemplateClassPathResource(template);
120 if (resource == null || !resource.exists()) {
121 throw new IllegalArgumentException("Cannot find the template file: " + template);
122 }
123
124 try {
125 if (reportData != null && reportData.containsKey(PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME)) {
126 Map<String, String> subReports = (Map<String, String>) reportData.get(PARAMETER_NAME_SUBREPORT_TEMPLATE_NAME);
127 String subReportDirectory = (String) reportData.get(PARAMETER_NAME_SUBREPORT_DIR);
128 compileSubReports(subReports, subReportDirectory);
129 }
130
131 String realTemplateNameWithoutExtension = removeTemplateExtension(resource);
132 String designTemplateName = realTemplateNameWithoutExtension.concat(DESIGN_FILE_EXTENSION);
133 String jasperReportName = realTemplateNameWithoutExtension.concat(JASPER_REPORT_EXTENSION);
134 compileReportTemplate(designTemplateName, jasperReportName);
135
136 JRDataSource jrDataSource = JasperReportsUtils.convertReportData(dataSource);
137
138 InputStream inputStream = new FileInputStream(jasperReportName);
139
140 JasperRunManager.runReportToPdfStream(inputStream, (OutputStream) baos, reportData, jrDataSource);
141 }
142 catch (Exception e) {
143 LOG.error(e);
144 throw new RuntimeException("Fail to generate report.", e);
145 }
146 }
147
148
149
150
151
152 public String buildFullFileName(Date runDate, String directory, String fileName, String extension) {
153 String runtimeStamp = dateTimeService.toDateTimeStringForFilename(runDate);
154 String fileNamePattern = "{0}" + SEPARATOR + "{1}_{2}{3}";
155
156 return MessageFormat.format(fileNamePattern, directory, fileName, runtimeStamp, extension);
157 }
158
159
160
161
162
163
164
165
166 protected ClassPathResource getReportTemplateClassPathResource(String reportTemplateName) {
167 if (reportTemplateName.endsWith(DESIGN_FILE_EXTENSION) || reportTemplateName.endsWith(JASPER_REPORT_EXTENSION)) {
168 return new ClassPathResource(reportTemplateName);
169 }
170
171 String jasperReport = reportTemplateName.concat(JASPER_REPORT_EXTENSION);
172 ClassPathResource resource = new ClassPathResource(jasperReport);
173 if (resource.exists()) {
174 return resource;
175 }
176
177 String designTemplate = reportTemplateName.concat(DESIGN_FILE_EXTENSION);
178 resource = new ClassPathResource(designTemplate);
179 return resource;
180 }
181
182
183
184
185
186
187
188 protected void compileReportTemplate(String designTemplate, String jasperReport) throws JRException {
189 File jasperFile = new File(jasperReport);
190 File designFile = new File(designTemplate);
191
192 if (!jasperFile.exists() && !designFile.exists()) {
193 throw new RuntimeException("Both the design template file and jasper report file don't exist: (" + designTemplate + ", " + jasperReport + ")");
194 }
195
196 if (!jasperFile.exists() && designFile.exists()) {
197 JasperCompileManager.compileReportToFile(designTemplate, jasperReport);
198 }
199 else if (jasperFile.exists() && designFile.exists()) {
200 if (jasperFile.lastModified() < designFile.lastModified()) {
201 JasperCompileManager.compileReportToFile(designTemplate, jasperReport);
202 }
203 }
204 }
205
206
207
208
209
210
211
212 protected void compileSubReports(Map<String, String> subReports, String subReportDirectory) throws Exception {
213 for (Map.Entry<String, String> entry: subReports.entrySet()) {
214 ClassPathResource resource = getReportTemplateClassPathResource(subReportDirectory + entry.getValue());
215 String realTemplateNameWithoutExtension = removeTemplateExtension(resource);
216
217 String designTemplateName = realTemplateNameWithoutExtension.concat(DESIGN_FILE_EXTENSION);
218 String jasperReportName = realTemplateNameWithoutExtension.concat(JASPER_REPORT_EXTENSION);
219
220 compileReportTemplate(designTemplateName, jasperReportName);
221 }
222 }
223
224
225
226
227
228
229
230 protected String removeTemplateExtension(ClassPathResource template) throws IOException {
231 String realTemplateName = template.getFile().getAbsolutePath();
232
233 int lastIndex = realTemplateName.lastIndexOf(".");
234 String realTemplateNameWithoutExtension = lastIndex > 0 ? realTemplateName.substring(0, lastIndex) : realTemplateName;
235
236 return realTemplateNameWithoutExtension;
237 }
238
239
240
241
242
243
244 public void setDateTimeService(DateTimeService dateTimeService) {
245 this.dateTimeService = dateTimeService;
246 }
247 }