Source Code Cross Referenced for LayoutEngine.java in  » Report » datavision-1.1.0 » jimm » datavision » layout » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Report » datavision 1.1.0 » jimm.datavision.layout 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package jimm.datavision.layout;
002:
003:        import jimm.datavision.*;
004:        import jimm.datavision.field.Field;
005:        import jimm.datavision.field.ImageField;
006:        import java.io.PrintWriter;
007:        import java.util.*;
008:
009:        /**
010:         * A layout engine is responsible for formatting and outputting report data.
011:         * <code>LayoutEngine</code> is an abstract class. The Template design
012:         * pattern is heavily used to provide a framework for concrete layout
013:         * engine subclasses.
014:         *
015:         * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
016:         */
017:        public abstract class LayoutEngine {
018:
019:            /** The number of points per inch. */
020:            public static final int POINTS_PER_INCH = 72;
021:
022:            protected static final int SECT_REPORT_HEADER = 0;
023:            protected static final int SECT_REPORT_FOOTER = 1;
024:            protected static final int SECT_PAGE_HEADER = 2;
025:            protected static final int SECT_PAGE_FOOTER = 3;
026:            protected static final int SECT_GROUP_HEADER = 4;
027:            protected static final int SECT_GROUP_FOOTER = 5;
028:            protected static final int SECT_DETAIL = 6;
029:
030:            /** Set by report in <code>Report.setLayoutEngine</code>. */
031:            protected Report report;
032:            protected int pageNumber;
033:            protected PrintWriter out;
034:            protected boolean newPage;
035:            protected double pageHeight;
036:            protected double pageWidth;
037:            protected double pageHeightUsed;
038:            protected Section currentSection;
039:            protected boolean wantsMoreData;
040:            protected int previousSectionArea;
041:
042:            /**
043:             * Constructor.
044:             */
045:            public LayoutEngine() {
046:                this (null);
047:            }
048:
049:            /**
050:             * Constructor.
051:             *
052:             * @param out output print writer
053:             */
054:            public LayoutEngine(PrintWriter out) {
055:                report = null;
056:                this .out = out;
057:                wantsMoreData = true;
058:                previousSectionArea = -1;
059:            }
060:
061:            public void setReport(Report r) {
062:                report = r;
063:            }
064:
065:            /**
066:             * Returns the page width in points. This value is only valid after
067:             * {@link #start} has been called.
068:             *
069:             * @return the page width in points
070:             */
071:            public double pageWidth() {
072:                return pageWidth;
073:            }
074:
075:            /**
076:             * Returns the page height in points. This value is only valid after
077:             * {@link #start} has been called.
078:             *
079:             * @return the page height in points
080:             */
081:            public double pageHeight() {
082:                return pageHeight;
083:            }
084:
085:            /**
086:             * Called by a report before retrieving each row of data, this method returns
087:             * <code>true</code> if this layout engine wants more data. Concrete
088:             * subclasses can set the <code>wantsMoreData</code> instance variable
089:             * to <code>false</code> if the user cancells a report run, for example.
090:             *
091:             * @return <code>true</code> if this layout engine would like more data
092:             */
093:            public boolean wantsMoreData() {
094:                return wantsMoreData;
095:            }
096:
097:            /**
098:             * Called by someone else running the report to cancel all the hard work
099:             * this layout engine has performed.
100:             */
101:            public void cancel() {
102:                closeOutput();
103:            }
104:
105:            /**
106:             * Called by the report at the beginning of a report run.
107:             * <p>
108:             * By this time, <code>report</code> will be non-<code>null</code>
109:             * because we have been added to a report (which in turn sets our
110:             * <code>report</code> instance variable).
111:             */
112:            public void start() {
113:                newPage = true;
114:                pageHeightUsed = 0;
115:                pageNumber = 0;
116:                pageHeight = report.getPaperFormat().getHeight();
117:                pageWidth = report.getPaperFormat().getWidth();
118:                if (wantsMoreData) {
119:                    doStart();
120:                    startPage();
121:                }
122:            }
123:
124:            /**
125:             * Called by <code>start</code> as a chance to insert behavior when the
126:             * report starts.
127:             */
128:            protected void doStart() {
129:            }
130:
131:            /**
132:             * Called by the report at the end of a report run.
133:             */
134:            public void end() {
135:                if (wantsMoreData) {
136:                    for (Iterator iter = report.footers().iterator(); iter
137:                            .hasNext();)
138:                        outputSection((Section) iter.next(), SECT_REPORT_FOOTER);
139:                    endPage(true);
140:                    doEnd();
141:                }
142:                closeOutput();
143:            }
144:
145:            /**
146:             * Called by <code>end</code> as a chance to insert behavior when the
147:             * report ends.
148:             */
149:            protected void doEnd() {
150:            }
151:
152:            /**
153:             * Called by <code>end</code> to let this layout engine clean up a bit.
154:             */
155:            protected void closeOutput() {
156:                if (out != null) {
157:                    out.flush();
158:                    out.close();
159:                    out = null;
160:                }
161:            }
162:
163:            /**
164:             * Called by the report when group headers need to be output. Once one
165:             * group header is output, we output all remaining group headers.
166:             * <p>
167:             * We need to explicitly evaluate all formulas in the headers that will be
168:             * output because {@link #checkRemainingPageLength} causes formulas in
169:             * detail and footers to be evaluated. Those formulas may depend upon
170:             * values in these headers.
171:             *
172:             * @param isLastRow if <code>true</code>, this is the last row of the report
173:             */
174:            public void groupHeaders(boolean isLastRow) {
175:                if (!wantsMoreData)
176:                    return;
177:
178:                boolean headerWasOutput = false;
179:                for (Iterator iter = report.groups(); iter.hasNext();) {
180:                    Group g = (Group) iter.next();
181:                    if (headerWasOutput || g.isNewValue()) {
182:                        for (Iterator i2 = g.headers().iterator(); i2.hasNext();)
183:                            ((Section) i2.next()).evaluateFormulas();
184:                        headerWasOutput = true;
185:                    }
186:                }
187:                //     boolean headerWasOutput;
188:
189:                checkRemainingPageLength(isLastRow, true);
190:
191:                headerWasOutput = false;
192:                for (Iterator iter = report.groups(); iter.hasNext();) {
193:                    Group g = (Group) iter.next();
194:                    if (headerWasOutput || g.isNewValue()) {
195:                        for (Iterator i2 = g.headers().iterator(); i2.hasNext();)
196:                            outputSection((Section) i2.next(),
197:                                    SECT_GROUP_HEADER);
198:                        headerWasOutput = true;
199:                    }
200:                }
201:            }
202:
203:            /**
204:             * Called by the report when a single detail row needs to be output.
205:             *
206:             * @param isLastRow if <code>true</code>, this is the last row of the report
207:             */
208:            public void detail(boolean isLastRow) {
209:                if (!wantsMoreData)
210:                    return;
211:
212:                checkRemainingPageLength(isLastRow, true);
213:                for (Iterator iter = report.details().iterator(); iter
214:                        .hasNext();)
215:                    outputSection((Section) iter.next(), SECT_DETAIL);
216:            }
217:
218:            /**
219:             * Called by the report when group footers need to be output. When one
220:             * group footer is output, we make sure all of the footers before (above)
221:             * it are also output.
222:             *
223:             * @param isLastRow if <code>true</code>, this is the last row of the report
224:             */
225:            public void groupFooters(boolean isLastRow) {
226:                if (!wantsMoreData)
227:                    return;
228:
229:                checkRemainingPageLength(isLastRow, false);
230:
231:                // We need to output group footers backwards (Group n ... Group 1).
232:                // When a group footer is output, make sure all of the footers before
233:                // (above) it are also output. First, we walk the group list forwards
234:                // so we can see which group changed first and grab all groups
235:                // after that one.
236:                boolean footerWasOutput = false;
237:                ArrayList groupsToOutput = new ArrayList();
238:                for (Iterator iter = report.groups(); iter.hasNext();) {
239:                    Group g = (Group) iter.next();
240:                    if (footerWasOutput || g.isNewValue() || isLastRow) {
241:                        if (footerWasOutput)
242:                            g.forceFooterOutput();
243:                        groupsToOutput.add(g);
244:                        footerWasOutput = true;
245:                    }
246:                }
247:
248:                // Now we reverse the list of groups and output them.
249:                Collections.reverse(groupsToOutput);
250:                for (Iterator iter = groupsToOutput.iterator(); iter.hasNext();) {
251:                    Group g = (Group) iter.next();
252:                    for (Iterator i2 = g.footers().iterator(); i2.hasNext();)
253:                        outputSection((Section) i2.next(), SECT_GROUP_FOOTER);
254:                }
255:            }
256:
257:            /**
258:             * Checks remaining page length and outputs a new page if we are at the
259:             * bottom of the page.
260:             *
261:             * @param isLastRow if <code>true</code>, this is the last row of the report
262:             * @param includeDetail if <code>true</code>, include height of detail
263:             * sections
264:             */
265:            protected void checkRemainingPageLength(boolean isLastRow,
266:                    boolean includeDetail) {
267:                // NOTE: need to do this dynamically each row because each one
268:                // of the multiple detail sections may or may not be active for
269:                // this row.
270:                double detailHeight = includeDetail ? calcDetailHeight() : 0;
271:                double footerHeight = calcPageFooterHeight();
272:                if (isLastRow)
273:                    footerHeight += calcReportFooterHeight();
274:
275:                if ((pageHeightUsed + footerHeight + detailHeight) > pageHeight())
276:                    endPage(isLastRow);
277:
278:                if (newPage)
279:                    startPage();
280:            }
281:
282:            /**
283:             * Returns the current page number.
284:             *
285:             * @return the current page number
286:             */
287:            public int pageNumber() {
288:                return pageNumber;
289:            }
290:
291:            /**
292:             * Starts a new page.
293:             */
294:            protected void startPage() {
295:                if (!wantsMoreData)
296:                    return;
297:
298:                pageNumber += 1;
299:                pageHeightUsed = 0;
300:                newPage = false;
301:
302:                doStartPage();
303:                if (pageNumber == 1) {
304:                    for (Iterator iter = report.headers().iterator(); iter
305:                            .hasNext();)
306:                        outputSection((Section) iter.next(), SECT_REPORT_HEADER);
307:                }
308:                for (Iterator iter = report.pageHeaders().iterator(); iter
309:                        .hasNext();)
310:                    outputSection((Section) iter.next(), SECT_PAGE_HEADER);
311:            }
312:
313:            /**
314:             * Called by <code>startPage</code> as a chance to insert behavior when a
315:             * new page starts.
316:             */
317:            protected void doStartPage() {
318:            }
319:
320:            /**
321:             * Ends a new page.
322:             *
323:             * @param isLastPage if <code>true</code>, this is the last page of the report
324:             */
325:            protected void endPage(boolean isLastPage) {
326:                if (!wantsMoreData)
327:                    return;
328:
329:                for (Iterator iter = report.pageFooters().iterator(); iter
330:                        .hasNext();)
331:                    outputSection((Section) iter.next(), SECT_PAGE_FOOTER);
332:
333:                newPage = true;
334:                doEndPage();
335:            }
336:
337:            /**
338:             * Called by <code>endPage</code> as a chance to insert behavior when a
339:             * new page ends.
340:             */
341:            protected void doEndPage() {
342:            }
343:
344:            /**
345:             * Outputs a section.
346:             *
347:             * @param sect the section to output
348:             * @param which the type of section (for example,
349:             * <code>SECT_PAGE_FOOTER</code>)
350:             */
351:            protected void outputSection(Section sect, int which) {
352:                if (!wantsMoreData)
353:                    return;
354:
355:                if (sect.isVisibleForCurrentRow()) {
356:                    // Insert a page break if requested.
357:                    if (sect.hasPageBreak()
358:                            && previousSectionArea != SECT_PAGE_HEADER) {
359:                        endPage(false);
360:                        startPage();
361:                    }
362:
363:                    // This must be after page break because calling endPage() and
364:                    // startPage() changes the currentSection.
365:                    currentSection = sect;
366:                    // Insert a page break if section will get overwritten by the page footer.
367:                    if (sect.getArea().getArea() != SECT_PAGE_FOOTER
368:                            && pageHeight - pageHeightUsed
369:                                    - calcPageFooterHeight() < currentSection
370:                                    .getOutputHeight()) {
371:                        endPage(false);
372:                        startPage();
373:                        currentSection = sect;
374:                    }
375:                    report.evaluateFormulasIn(currentSection);
376:                    doOutputSection(currentSection);
377:
378:                    pageHeightUsed += sect.getOutputHeight();
379:                    previousSectionArea = which;
380:                } else {
381:                    // Always eval formulas, even if the section is hidden
382:                    report.evaluateFormulasIn(sect);
383:                }
384:            }
385:
386:            /**
387:             * Called by <code>outputSection</code> as a chance to insert behavior
388:             * when a section is output.
389:             *
390:             * @param sect a section
391:             */
392:            protected void doOutputSection(Section sect) {
393:                // Output the fields in the section
394:                for (Iterator iter = sect.fields(); iter.hasNext();) {
395:                    Field f = (Field) iter.next();
396:                    if (f.isVisible()) {
397:                        if (f instanceof  ImageField)
398:                            outputImage((ImageField) f);
399:                        else
400:                            outputField(f);
401:                    }
402:                }
403:                // Output the lines
404:                for (Iterator iter = sect.lines(); iter.hasNext();) {
405:                    Line l = (Line) iter.next();
406:                    if (l.isVisible())
407:                        outputLine(l);
408:                }
409:            }
410:
411:            /**
412:             * Outputs a field.
413:             *
414:             * @param field the field to output
415:             */
416:            protected void outputField(Field field) {
417:                if (wantsMoreData) // Do nothing if we have cancelled
418:                    doOutputField(field);
419:            }
420:
421:            /**
422:             * Called by <code>outputField</code> as a chance to insert behavior
423:             * when a field is output.
424:             *
425:             * @param field a field
426:             */
427:            protected abstract void doOutputField(Field field);
428:
429:            /**
430:             * Outputs a image.
431:             *
432:             * @param image the image field to output
433:             */
434:            protected void outputImage(ImageField image) {
435:                if (wantsMoreData) // Do nothing if we have cancelled
436:                    doOutputImage(image);
437:            }
438:
439:            /**
440:             * Called by <code>outputImage</code> as a chance to insert behavior
441:             * when a image is output.
442:             *
443:             * @param image an image field
444:             */
445:            protected abstract void doOutputImage(ImageField image);
446:
447:            /**
448:             * Outputs a line.
449:             *
450:             * @param line the line to output
451:             */
452:            protected void outputLine(Line line) {
453:                if (wantsMoreData)
454:                    doOutputLine(line);
455:            }
456:
457:            /**
458:             * Called by <code>outputLine</code> as a chance to insert behavior
459:             * when a line is output.
460:             *
461:             * @param line a line
462:             */
463:            protected abstract void doOutputLine(Line line);
464:
465:            /**
466:             * Returns the current section type (header, footer, detail) as a string.
467:             *
468:             * @return a string representation of the current section type
469:             */
470:            protected String currentSectionTypeAsString() {
471:                switch (currentSection.getArea().getArea()) {
472:                case SectionArea.REPORT_HEADER:
473:                    return "report header";
474:                case SectionArea.REPORT_FOOTER:
475:                    return "report footer";
476:                case SectionArea.PAGE_HEADER:
477:                    return "page header";
478:                case SectionArea.PAGE_FOOTER:
479:                    return "page footer";
480:                case SectionArea.GROUP_HEADER:
481:                    return "group header";
482:                case SectionArea.GROUP_FOOTER:
483:                    return "group footer";
484:                case SectionArea.DETAIL:
485:                    return "detail";
486:                default:
487:                    return "unknown"; // Should never happen
488:                }
489:            }
490:
491:            /**
492:             * Returns the total height of all sections in the specified list.
493:             *
494:             * @param area a section area
495:             * @return the total height of all sections in the list
496:             */
497:            protected double calcSectionHeights(SectionArea area) {
498:                double sum = 0;
499:                for (Iterator iter = area.iterator(); iter.hasNext();) {
500:                    Section s = (Section) iter.next();
501:                    if (s.isVisibleForCurrentRow())
502:                        sum += s.getOutputHeight();
503:                }
504:                return sum;
505:            }
506:
507:            /**
508:             * Returns the total height of all detail sections.
509:             *
510:             * @return the total height of all detail sections
511:             */
512:            protected double calcDetailHeight() {
513:                return calcSectionHeights(report.details());
514:            }
515:
516:            /**
517:             * Returns the total height of all page footer sections.
518:             *
519:             * @return the total height of all page footer sections
520:             */
521:            protected double calcPageFooterHeight() {
522:                return calcSectionHeights(report.pageFooters());
523:            }
524:
525:            /**
526:             * Returns the total height of all report footer sections.
527:             *
528:             * @return the total height of all report footer sections
529:             */
530:            protected double calcReportFooterHeight() {
531:                return calcSectionHeights(report.footers());
532:            }
533:
534:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.