KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > design > JRAbstractCompiler


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.engine.design;
29
30 import java.io.File JavaDoc;
31 import java.io.Serializable JavaDoc;
32 import java.util.Collection JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.ListIterator JavaDoc;
36 import java.util.Random JavaDoc;
37
38 import net.sf.jasperreports.crosstabs.JRCrosstab;
39 import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab;
40 import net.sf.jasperreports.engine.JRDataset;
41 import net.sf.jasperreports.engine.JRException;
42 import net.sf.jasperreports.engine.JRExpressionCollector;
43 import net.sf.jasperreports.engine.JRReport;
44 import net.sf.jasperreports.engine.JRRuntimeException;
45 import net.sf.jasperreports.engine.JasperReport;
46 import net.sf.jasperreports.engine.fill.JREvaluator;
47 import net.sf.jasperreports.engine.util.JRProperties;
48 import net.sf.jasperreports.engine.util.JRSaver;
49 import net.sf.jasperreports.engine.util.JRStringUtil;
50
51 /**
52  * Base class for report compilers.
53  *
54  * @author Lucian Chirita (lucianc@users.sourceforge.net)
55  * @version $Id: JRAbstractCompiler.java 1346 2006-07-18 16:37:18 +0300 (Tue, 18 Jul 2006) teodord $
56  */

57 public abstract class JRAbstractCompiler implements JRCompiler
58 {
59     private static final int NAME_SUFFIX_RANDOM_MAX = 1000000;
60     private static final Random JavaDoc random = new Random JavaDoc();
61     
62     private final boolean needsSourceFiles;
63
64     /**
65      * Constructor.
66      *
67      * @param needsSourceFiles whether the compiler needs source files or is able to do in memory compilation
68      * <p>
69      * If true, the generated code is saved in source files to be used by the compiler.
70      */

71     protected JRAbstractCompiler(boolean needsSourceFiles)
72     {
73         this.needsSourceFiles = needsSourceFiles;
74     }
75
76     
77     /**
78      * Returns the name of the expression evaluator unit for a dataset of a report.
79      *
80      * @param report the report
81      * @param dataset the dataset
82      * @return the generated expression evaluator unit name
83      */

84     public static String JavaDoc getUnitName(JasperReport report, JRDataset dataset)
85     {
86         return getUnitName(report, dataset, report.getCompileNameSuffix());
87     }
88
89     protected static String JavaDoc getUnitName(JRReport report, JRDataset dataset, String JavaDoc nameSuffix)
90     {
91         String JavaDoc className;
92         if (dataset.isMainDataset())
93         {
94             className = report.getName();
95         }
96         else
97         {
98             className = report.getName() + "_" + dataset.getName();
99         }
100         
101         className = JRStringUtil.getLiteral(className) + nameSuffix;
102         
103         return className;
104     }
105     
106     /**
107      * Returns the name of the expression evaluator unit for a crosstab of a report.
108      *
109      * @param report the report
110      * @param crosstab the crosstab
111      * @return the generated expression evaluator unit name
112      */

113     public static String JavaDoc getUnitName(JasperReport report, JRCrosstab crosstab)
114     {
115         return getUnitName(report, crosstab.getId(), report.getCompileNameSuffix());
116     }
117
118     
119     protected static String JavaDoc getUnitName(JRReport report, JRCrosstab crosstab, JRExpressionCollector expressionCollector, String JavaDoc nameSuffix)
120     {
121         Integer JavaDoc crosstabId = expressionCollector.getCrosstabId(crosstab);
122         if (crosstabId == null)
123         {
124             throw new JRRuntimeException("Crosstab ID not found.");
125         }
126         
127         return getUnitName(report, crosstabId.intValue(), nameSuffix);
128     }
129
130     protected static String JavaDoc getUnitName(JRReport report, int crosstabId, String JavaDoc nameSuffix)
131     {
132         return JRStringUtil.getLiteral(report.getName()) + "_CROSSTAB" + crosstabId + nameSuffix;
133     }
134     
135     public final JasperReport compileReport(JasperDesign jasperDesign) throws JRException
136     {
137         // check if the language is supported by the compiler
138
checkLanguage(jasperDesign.getLanguage());
139         
140         // collect all report expressions
141
JRExpressionCollector expressionCollector = JRExpressionCollector.collector(jasperDesign);
142         
143         // verify the report design
144
verifyDesign(jasperDesign, expressionCollector);
145
146         String JavaDoc nameSuffix = createNameSuffix();
147         
148         // check if saving source files is required
149
boolean isKeepJavaFile = JRProperties.getBooleanProperty(JRProperties.COMPILER_KEEP_JAVA_FILE);
150         File JavaDoc tempDirFile = null;
151         if (isKeepJavaFile || needsSourceFiles)
152         {
153             String JavaDoc tempDirStr = JRProperties.getProperty(JRProperties.COMPILER_TEMP_DIR);
154
155             tempDirFile = new File JavaDoc(tempDirStr);
156             if (!tempDirFile.exists() || !tempDirFile.isDirectory())
157             {
158                 throw new JRException("Temporary directory not found : " + tempDirStr);
159             }
160         }
161
162         List JavaDoc datasets = jasperDesign.getDatasetsList();
163         List JavaDoc crosstabs = jasperDesign.getCrosstabs();
164         
165         JRCompilationUnit[] units = new JRCompilationUnit[datasets.size() + crosstabs.size() + 1];
166         
167         // generating source code for the main report dataset
168
units[0] = createCompileUnit(jasperDesign, jasperDesign.getMainDesignDataset(), expressionCollector, tempDirFile, nameSuffix);
169
170         int sourcesCount = 1;
171         for (Iterator JavaDoc it = datasets.iterator(); it.hasNext(); ++sourcesCount)
172         {
173             JRDesignDataset dataset = (JRDesignDataset) it.next();
174             // generating source code for a sub dataset
175
units[sourcesCount] = createCompileUnit(jasperDesign, dataset, expressionCollector, tempDirFile, nameSuffix);
176         }
177         
178         for (Iterator JavaDoc it = crosstabs.iterator(); it.hasNext(); ++sourcesCount)
179         {
180             JRDesignCrosstab crosstab = (JRDesignCrosstab) it.next();
181             // generating source code for a sub dataset
182
units[sourcesCount] = createCompileUnit(jasperDesign, crosstab, expressionCollector, tempDirFile, nameSuffix);
183         }
184         
185         String JavaDoc classpath = JRProperties.getProperty(JRProperties.COMPILER_CLASSPATH);
186         
187         try
188         {
189             // compiling generated sources
190
String JavaDoc compileErrors = compileUnits(units, classpath, tempDirFile);
191             if (compileErrors != null)
192             {
193                 throw new JRException("Errors were encountered when compiling report expressions class file:\n" + compileErrors);
194             }
195
196             // creating the report compile data
197
JRReportCompileData reportCompileData = new JRReportCompileData();
198             reportCompileData.setMainDatasetCompileData(units[0].getCompileData());
199             
200             for (ListIterator JavaDoc it = datasets.listIterator(); it.hasNext();)
201             {
202                 JRDesignDataset dataset = (JRDesignDataset) it.next();
203                 reportCompileData.setDatasetCompileData(dataset, units[it.nextIndex()].getCompileData());
204             }
205             
206             for (ListIterator JavaDoc it = crosstabs.listIterator(); it.hasNext();)
207             {
208                 JRDesignCrosstab crosstab = (JRDesignCrosstab) it.next();
209                 Integer JavaDoc crosstabId = expressionCollector.getCrosstabId(crosstab);
210                 reportCompileData.setCrosstabCompileData(crosstabId.intValue(), units[datasets.size() + it.nextIndex()].getCompileData());
211             }
212
213             // creating the report
214
JasperReport jasperReport =
215                 new JasperReport(
216                     jasperDesign,
217                     getCompilerClass(),
218                     reportCompileData,
219                     expressionCollector,
220                     nameSuffix
221                     );
222             
223             return jasperReport;
224         }
225         catch (JRException e)
226         {
227             throw e;
228         }
229         catch (Exception JavaDoc e)
230         {
231             throw new JRException("Error compiling report design.", e);
232         }
233         finally
234         {
235             if (needsSourceFiles && !isKeepJavaFile)
236             {
237                 deleteSourceFiles(units);
238             }
239         }
240     }
241
242
243     private static String JavaDoc createNameSuffix()
244     {
245         return "_" + System.currentTimeMillis() + "_" + random.nextInt(NAME_SUFFIX_RANDOM_MAX);
246     }
247
248
249     protected String JavaDoc getCompilerClass()
250     {
251         return getClass().getName();
252     }
253
254     
255     private void verifyDesign(JasperDesign jasperDesign, JRExpressionCollector expressionCollector) throws JRException
256     {
257         Collection JavaDoc brokenRules = JRVerifier.verifyDesign(jasperDesign, expressionCollector);
258         if (brokenRules != null && brokenRules.size() > 0)
259         {
260             StringBuffer JavaDoc sbuffer = new StringBuffer JavaDoc();
261             sbuffer.append("Report design not valid : ");
262             int i = 1;
263             for(Iterator JavaDoc it = brokenRules.iterator(); it.hasNext(); i++)
264             {
265                 sbuffer.append("\n\t " + i + ". " + (String JavaDoc)it.next());
266             }
267             throw new JRException(sbuffer.toString());
268         }
269     }
270     
271     private JRCompilationUnit createCompileUnit(JasperDesign jasperDesign, JRDesignDataset dataset, JRExpressionCollector expressionCollector, File JavaDoc saveSourceDir, String JavaDoc nameSuffix) throws JRException
272     {
273         String JavaDoc unitName = JRAbstractCompiler.getUnitName(jasperDesign, dataset, nameSuffix);
274         
275         JRSourceCompileTask sourceTask = new JRSourceCompileTask(jasperDesign, dataset, expressionCollector, unitName);
276         String JavaDoc sourceCode = generateSourceCode(sourceTask);
277         
278         File JavaDoc sourceFile = getSourceFile(saveSourceDir, unitName, sourceCode);
279
280         return new JRCompilationUnit(unitName, sourceCode, sourceFile, expressionCollector.getExpressions(dataset));
281     }
282     
283     private JRCompilationUnit createCompileUnit(JasperDesign jasperDesign, JRDesignCrosstab crosstab, JRExpressionCollector expressionCollector, File JavaDoc saveSourceDir, String JavaDoc nameSuffix) throws JRException
284     {
285         String JavaDoc unitName = JRAbstractCompiler.getUnitName(jasperDesign, crosstab, expressionCollector, nameSuffix);
286         
287         JRSourceCompileTask sourceTask = new JRSourceCompileTask(jasperDesign, crosstab, expressionCollector, unitName);
288         String JavaDoc sourceCode = generateSourceCode(sourceTask);
289         
290         File JavaDoc sourceFile = getSourceFile(saveSourceDir, unitName, sourceCode);
291
292         return new JRCompilationUnit(unitName, sourceCode, sourceFile, expressionCollector.getExpressions(crosstab));
293     }
294
295
296     private File JavaDoc getSourceFile(File JavaDoc saveSourceDir, String JavaDoc unitName, String JavaDoc sourceCode) throws JRException
297     {
298         File JavaDoc sourceFile = null;
299         if (saveSourceDir != null)
300         {
301             String JavaDoc fileName = getSourceFileName(unitName);
302             sourceFile = new File JavaDoc(saveSourceDir, fileName);
303
304             JRSaver.saveClassSource(sourceCode, sourceFile);
305         }
306         return sourceFile;
307     }
308
309     private void deleteSourceFiles(JRCompilationUnit[] units)
310     {
311         for (int i = 0; i < units.length; i++)
312         {
313             units[i].getSourceFile().delete();
314         }
315     }
316
317     public JREvaluator loadEvaluator(JasperReport jasperReport) throws JRException
318     {
319         return loadEvaluator(jasperReport, jasperReport.getMainDataset());
320     }
321
322     public JREvaluator loadEvaluator(JasperReport jasperReport, JRDataset dataset) throws JRException
323     {
324         String JavaDoc unitName = JRAbstractCompiler.getUnitName(jasperReport, dataset);
325         JRReportCompileData reportCompileData = (JRReportCompileData) jasperReport.getCompileData();
326         Serializable JavaDoc compileData = reportCompileData.getDatasetCompileData(dataset);
327         return loadEvaluator(compileData, unitName);
328     }
329
330     public JREvaluator loadEvaluator(JasperReport jasperReport, JRCrosstab crosstab) throws JRException
331     {
332         String JavaDoc unitName = JRAbstractCompiler.getUnitName(jasperReport, crosstab);
333         JRReportCompileData reportCompileData = (JRReportCompileData) jasperReport.getCompileData();
334         Serializable JavaDoc compileData = reportCompileData.getCrosstabCompileData(crosstab);
335         return loadEvaluator(compileData, unitName);
336     }
337
338     
339     /**
340      * Creates an expression evaluator instance from data saved when the report was compiled.
341      *
342      * @param compileData the data saved when the report was compiled
343      * @param unitName the evaluator unit name
344      * @return an expression evaluator instance
345      * @throws JRException
346      */

347     protected abstract JREvaluator loadEvaluator(Serializable JavaDoc compileData, String JavaDoc unitName) throws JRException;
348
349     
350     /**
351      * Checks that the report language is supported by the compiler.
352      *
353      * @param language the report language
354      * @throws JRException
355      */

356     protected abstract void checkLanguage(String JavaDoc language) throws JRException;
357
358     
359     /**
360      * Generates expression evaluator code.
361      *
362      * @param sourceTask the source code generation information
363      * @return generated expression evaluator code
364      * @throws JRException
365      */

366     protected abstract String JavaDoc generateSourceCode(JRSourceCompileTask sourceTask) throws JRException;
367
368     
369     /**
370      * Compiles several expression evaluator units.
371      * <p>
372      * The result of the compilation should be set by calling
373      * {@link JRCompilationUnit#setCompileData(Serializable) setCompileData} on all compile units.
374      *
375      * @param units the compilation units
376      * @param classpath the compilation classpath
377      * @param tempDirFile temporary directory
378      * @return a string containing compilation errors, or null if the compilation was successfull
379      * @throws JRException
380      */

381     protected abstract String JavaDoc compileUnits(JRCompilationUnit[] units, String JavaDoc classpath, File JavaDoc tempDirFile) throws JRException;
382
383     
384     /**
385      * Returns the name of the source file where generated source code for an unit is saved.
386      * <p>
387      * If the compiler needs source files for compilation
388      * or {@link JRProperties#COMPILER_KEEP_JAVA_FILE COMPILER_KEEP_JAVA_FILE} is set, the generated source
389      * will be saved in a file having the name returned by this method.
390      *
391      * @param unitName the unit name
392      * @return the source file name
393      */

394     protected abstract String JavaDoc getSourceFileName(String JavaDoc unitName);
395 }
396
Popular Tags