Source Code Cross Referenced for AbstractReportProcessor.java in  » Report » pentaho-report » org » jfree » report » layout » output » 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 » pentaho report » org.jfree.report.layout.output 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * ===========================================
0003:         * JFreeReport : a free Java reporting library
0004:         * ===========================================
0005:         *
0006:         * Project Info:  http://reporting.pentaho.org/
0007:         *
0008:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
0009:         *
0010:         * This library is free software; you can redistribute it and/or modify it under the terms
0011:         * of the GNU Lesser General Public License as published by the Free Software Foundation;
0012:         * either version 2.1 of the License, or (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
0015:         * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0016:         * See the GNU Lesser General Public License for more details.
0017:         *
0018:         * You should have received a copy of the GNU Lesser General Public License along with this
0019:         * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
0020:         * Boston, MA 02111-1307, USA.
0021:         *
0022:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
0023:         * in the United States and other countries.]
0024:         *
0025:         * ------------
0026:         * AbstractReportProcessor.java
0027:         * ------------
0028:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
0029:         */package org.jfree.report.layout.output;
0030:
0031:        import java.util.ArrayList;
0032:        import java.util.Arrays;
0033:        import java.util.Date;
0034:        import java.util.List;
0035:
0036:        import org.jfree.base.config.ModifiableConfiguration;
0037:        import org.jfree.base.log.MemoryUsageMessage;
0038:        import org.jfree.report.DataFactory;
0039:        import org.jfree.report.EmptyReportException;
0040:        import org.jfree.report.JFreeReport;
0041:        import org.jfree.report.ReportDataFactoryException;
0042:        import org.jfree.report.ReportEventException;
0043:        import org.jfree.report.ReportInterruptedException;
0044:        import org.jfree.report.ReportProcessingException;
0045:        import org.jfree.report.event.ReportProgressEvent;
0046:        import org.jfree.report.event.ReportProgressListener;
0047:        import org.jfree.report.function.OutputFunction;
0048:        import org.jfree.report.layout.AbstractRenderer;
0049:        import org.jfree.report.layout.DefaultLayoutSupport;
0050:        import org.jfree.report.layout.Renderer;
0051:        import org.jfree.report.states.CollectingReportErrorHandler;
0052:        import org.jfree.report.states.IgnoreEverythingReportErrorHandler;
0053:        import org.jfree.report.states.LayoutProcess;
0054:        import org.jfree.report.states.ReportProcessingErrorHandler;
0055:        import org.jfree.report.states.ReportState;
0056:        import org.jfree.report.states.ReportStateKey;
0057:        import org.jfree.report.states.StateUtilities;
0058:        import org.jfree.report.states.process.ProcessState;
0059:        import org.jfree.report.util.IntList;
0060:        import org.jfree.report.util.ReportConfigurationUtil;
0061:        import org.jfree.report.util.StringUtil;
0062:        import org.jfree.util.Log;
0063:
0064:        /**
0065:         * Creation-Date: 08.04.2007, 14:52:52
0066:         *
0067:         * @author Thomas Morgner
0068:         */
0069:        public abstract class AbstractReportProcessor implements 
0070:                ReportProcessor {
0071:            private static final boolean SHOW_ROLLBACKS = false;
0072:
0073:            protected static final int MAX_EVENTS_PER_RUN = 200;
0074:            protected static final int MIN_ROWS_PER_EVENT = 100;
0075:            protected static final int PAGE_EVENT_RATE = 20;
0076:
0077:            /**
0078:             * A flag defining whether to check for Thread-Interrupts.
0079:             */
0080:            private boolean handleInterruptedState;
0081:
0082:            /**
0083:             * Storage for listener references.
0084:             */
0085:            private ArrayList listeners;
0086:
0087:            /**
0088:             * The listeners as object array for faster access.
0089:             */
0090:            private transient Object[] listenersCache;
0091:
0092:            private JFreeReport report;
0093:
0094:            private OutputProcessor outputProcessor;
0095:
0096:            private PageStateList stateList;
0097:            private transient DataFactory activeDataFactory;
0098:
0099:            private IntList physicalMapping;
0100:            private IntList logicalMapping;
0101:            private boolean pagebreaksSupported;
0102:            private boolean paranoidChecks;
0103:
0104:            protected AbstractReportProcessor(final JFreeReport report,
0105:                    final OutputProcessor outputProcessor)
0106:                    throws ReportProcessingException {
0107:                if (report == null) {
0108:                    throw new NullPointerException("Report cannot be null.");
0109:                }
0110:
0111:                if (outputProcessor == null) {
0112:                    throw new NullPointerException(
0113:                            "OutputProcessor cannot be null");
0114:                }
0115:
0116:                try {
0117:                    // first cloning ... protect the page layouter function ...
0118:                    // and any changes we may do to the report instance.
0119:
0120:                    // a second cloning is done in the start state, to protect the
0121:                    // processed data.
0122:                    this .report = (JFreeReport) report.clone();
0123:                } catch (CloneNotSupportedException cne) {
0124:                    throw new ReportProcessingException(
0125:                            "Initial Clone of Report failed");
0126:                }
0127:
0128:                this .handleInterruptedState = true;
0129:                this .outputProcessor = outputProcessor;
0130:                this .paranoidChecks = "true".equals(outputProcessor
0131:                        .getMetaData().getConfiguration().getConfigProperty(
0132:                                "org.jfree.report.layout.ParanoidChecks"));
0133:                this .pagebreaksSupported = outputProcessor.getMetaData()
0134:                        .isFeatureSupported(OutputProcessorFeature.PAGEBREAKS);
0135:                final ModifiableConfiguration configuration = report
0136:                        .getReportConfiguration();
0137:                final String yieldRateText = configuration
0138:                        .getConfigProperty("org.jfree.report.YieldRate");
0139:                final int yieldRate = StringUtil.parseInt(yieldRateText, 0);
0140:                if (yieldRate > 0) {
0141:                    addReportProgressListener(new YieldReportListener(yieldRate));
0142:                }
0143:            }
0144:
0145:            protected JFreeReport getReport() {
0146:                return report;
0147:            }
0148:
0149:            public OutputProcessor getOutputProcessor() {
0150:                return outputProcessor;
0151:            }
0152:
0153:            protected OutputProcessorMetaData getOutputProcessorMetaData() {
0154:                return outputProcessor.getMetaData();
0155:            }
0156:
0157:            /**
0158:             * Adds a repagination listener. This listener will be informed of pagination events.
0159:             *
0160:             * @param l the listener.
0161:             */
0162:            public synchronized void addReportProgressListener(
0163:                    final ReportProgressListener l) {
0164:                if (l == null) {
0165:                    throw new NullPointerException("Listener == null");
0166:                }
0167:                if (listeners == null) {
0168:                    listeners = new ArrayList(5);
0169:                }
0170:                listenersCache = null;
0171:                listeners.add(l);
0172:            }
0173:
0174:            /**
0175:             * Removes a repagination listener.
0176:             *
0177:             * @param l the listener.
0178:             */
0179:            public synchronized void removeReportProgressListener(
0180:                    final ReportProgressListener l) {
0181:                if (l == null) {
0182:                    throw new NullPointerException("Listener == null");
0183:                }
0184:                if (listeners == null) {
0185:                    return;
0186:                }
0187:                listenersCache = null;
0188:                listeners.remove(l);
0189:            }
0190:
0191:            /**
0192:             * Sends a repagination update to all registered listeners.
0193:             *
0194:             * @param state the state.
0195:             */
0196:            protected synchronized void fireStateUpdate(
0197:                    final ReportProgressEvent state) {
0198:                if (listeners == null) {
0199:                    return;
0200:                }
0201:                if (listenersCache == null) {
0202:                    listenersCache = listeners.toArray();
0203:                }
0204:                final int length = listenersCache.length;
0205:                for (int i = 0; i < length; i++) {
0206:                    final ReportProgressListener l = (ReportProgressListener) listenersCache[i];
0207:                    l.reportProcessingUpdate(state);
0208:                }
0209:            }
0210:
0211:            /**
0212:             * Returns whether the processor should check the threads interrupted state. If this is set to true and the thread was
0213:             * interrupted, then the report processing is aborted.
0214:             *
0215:             * @return true, if the processor should check the current thread state, false otherwise.
0216:             */
0217:            public boolean isHandleInterruptedState() {
0218:                return handleInterruptedState;
0219:            }
0220:
0221:            /**
0222:             * Defines, whether the processor should check the threads interrupted state. If this is set to true and the thread
0223:             * was interrupted, then the report processing is aborted.
0224:             *
0225:             * @param handleInterruptedState true, if the processor should check the current thread state, false otherwise.
0226:             */
0227:            public void setHandleInterruptedState(
0228:                    final boolean handleInterruptedState) {
0229:                this .handleInterruptedState = handleInterruptedState;
0230:            }
0231:
0232:            /**
0233:             * Checks, whether the current thread is interrupted.
0234:             *
0235:             * @throws org.jfree.report.ReportInterruptedException
0236:             *          if the thread is interrupted to abort the report processing.
0237:             */
0238:            protected final void checkInterrupted()
0239:                    throws ReportInterruptedException {
0240:                if (isHandleInterruptedState() && Thread.interrupted()) {
0241:                    throw new ReportInterruptedException(
0242:                            "Current thread signaled interrupt; Aborting report processing.");
0243:                }
0244:            }
0245:
0246:            public synchronized void close() {
0247:                if (activeDataFactory != null) {
0248:                    this .activeDataFactory.close();
0249:                    this .activeDataFactory = null;
0250:                    this .stateList = null;
0251:                    this .physicalMapping = null;
0252:                    this .logicalMapping = null;
0253:                }
0254:            }
0255:
0256:            protected DefaultProcessingContext createProcessingContext() {
0257:                final OutputProcessorMetaData metaData = getOutputProcessorMetaData();
0258:                final boolean maxLineHeightUsed = metaData
0259:                        .isFeatureSupported(OutputProcessorFeature.LEGACY_LINEHEIGHT_CALC) == false;
0260:                final boolean imageResolutionMapping = metaData
0261:                        .isFeatureSupported(OutputProcessorFeature.IMAGE_RESOLUTION_MAPPING) == false;
0262:                final JFreeReport report = getReport();
0263:                return new DefaultProcessingContext(metaData
0264:                        .getExportDescriptor(), new DefaultLayoutSupport(
0265:                        maxLineHeightUsed, imageResolutionMapping), report
0266:                        .getResourceBundleFactory(), report.getConfiguration(),
0267:                        report.getResourceManager(), report.getContentBase());
0268:            }
0269:
0270:            /**
0271:             * Processes all prepare levels to compute the function values.
0272:             *
0273:             * @param state   the state state with which we beginn the processing.
0274:             * @param level   the current processing level.
0275:             * @param maxRows the number of rows in the table model.
0276:             * @return the finish state for the current level.
0277:             * @throws ReportProcessingException if processing failed or if there are exceptions during the function execution.
0278:             */
0279:            protected ProcessState processPrepareLevels(ProcessState state,
0280:                    final int level, final int maxRows)
0281:                    throws ReportProcessingException {
0282:                final boolean failOnError = ReportConfigurationUtil
0283:                        .isStrictErrorHandling(getReport()
0284:                                .getReportConfiguration());
0285:                final ReportProcessingErrorHandler errorHandler = new CollectingReportErrorHandler();
0286:                state.setErrorHandler(errorHandler);
0287:
0288:                int lastRow = -1;
0289:                int eventCount = 0;
0290:                final int eventTrigger = Math.min(maxRows / MAX_EVENTS_PER_RUN,
0291:                        MIN_ROWS_PER_EVENT);
0292:                final ReportProgressEvent repaginationState = new ReportProgressEvent(
0293:                        this );
0294:                // Function processing does not use the PageLayouter, so we don't need
0295:                // the expensive cloning ...
0296:                while (!state.isFinish()) {
0297:                    checkInterrupted();
0298:                    if (lastRow != state.getCurrentDataItem()) {
0299:                        lastRow = state.getCurrentDataItem();
0300:                        if (eventCount == 0) {
0301:                            repaginationState.reuse(level, state
0302:                                    .getCurrentDataItem(), state
0303:                                    .getNumberOfRows(), state.getCurrentPage(),
0304:                                    state.getProgressLevel(), state
0305:                                            .getProgressLevelCount());
0306:                            fireStateUpdate(repaginationState);
0307:                            eventCount += 1;
0308:                        } else {
0309:                            if (eventCount == eventTrigger) {
0310:                                eventCount = 0;
0311:                            } else {
0312:                                eventCount += 1;
0313:                            }
0314:                        }
0315:                    }
0316:
0317:                    //progress = state.createStateProgress(progress);
0318:                    final ProcessState nextState = state.advance();
0319:                    state
0320:                            .setErrorHandler(IgnoreEverythingReportErrorHandler.INSTANCE);
0321:                    state = nextState.commit();
0322:
0323:                    if (errorHandler.isErrorOccured() == true) {
0324:                        final List childExceptions = Arrays.asList(errorHandler
0325:                                .getErrors());
0326:                        errorHandler.clearErrors();
0327:                        if (failOnError) {
0328:                            throw new ReportEventException(
0329:                                    "Failed to dispatch an event.",
0330:                                    childExceptions);
0331:                        } else {
0332:                            final ReportEventException exception = new ReportEventException(
0333:                                    "Failed to dispatch an event.",
0334:                                    childExceptions);
0335:                            Log
0336:                                    .error("Failed to dispatch an event.",
0337:                                            exception);
0338:                        }
0339:                    }
0340:                }
0341:                return state;
0342:            }
0343:
0344:            protected abstract DefaultOutputFunction createLayoutManager();
0345:
0346:            protected void prepareReportProcessing()
0347:                    throws ReportProcessingException {
0348:                if (stateList != null) {
0349:                    // is already paginated.
0350:                    return;
0351:                }
0352:
0353:                final long start = System.currentTimeMillis();
0354:
0355:                try {
0356:                    // every report processing starts with an StartState.
0357:                    final DefaultProcessingContext processingContext = createProcessingContext();
0358:                    final JFreeReport report = getReport();
0359:                    report.setProperty(JFreeReport.REPORT_DATE_PROPERTY,
0360:                            new Date());
0361:                    report.setProperty(JFreeReport.REPORT_LAYOUT_SUPPORT,
0362:                            processingContext.getLayoutSupport());
0363:
0364:                    final OutputFunction lm = createLayoutManager();
0365:
0366:                    final LayoutProcess lp = new LayoutProcess(
0367:                            (OutputFunction) lm.getInstance(), report
0368:                                    .getStructureFunctions());
0369:
0370:                    final ProcessState startState = new ProcessState(report,
0371:                            processingContext, lp);
0372:                    activeDataFactory = startState.getDataFactory();
0373:                    ProcessState state = startState;
0374:                    final int maxRows = startState.getNumberOfRows();
0375:
0376:                    report.getDataFactory().open();
0377:
0378:                    // the report processing can be splitted into 2 separate processes.
0379:                    // The first is the ReportPreparation; all function values are resolved and
0380:                    // a dummy run is done to calculate the final layout. This dummy run is
0381:                    // also necessary to resolve functions which use or depend on the PageCount.
0382:
0383:                    // the second process is the printing of the report, this is done in the
0384:                    // processReport() method.
0385:                    processingContext.setPrepareRun(true);
0386:
0387:                    // now process all function levels.
0388:                    // there is at least one level defined, as we added the PageLayouter
0389:                    // to the report.
0390:                    // the levels are defined from +inf to 0
0391:                    // we don't draw and we do not collect states in a StateList yet
0392:                    final int[] levels = StateUtilities.computeLevels(report,
0393:                            lp);
0394:                    if (levels.length == 0) {
0395:                        throw new IllegalStateException(
0396:                                "Assertation Failed: No functions defined, invalid implementation.");
0397:                    }
0398:                    processingContext.setProgressLevelCount(levels.length);
0399:                    int index = 0;
0400:                    int level = levels[index];
0401:                    // outer loop: process all function levels
0402:                    boolean hasNext;
0403:                    do {
0404:                        processingContext.setProcessingLevel(level);
0405:                        processingContext.setProgressLevel(index);
0406:
0407:                        // if the current level is the output-level, then save the report state.
0408:                        // The state is used later to restart the report processing.
0409:                        if (level == LayoutProcess.LEVEL_PAGINATE) {
0410:                            stateList = new PageStateList(this );
0411:                            physicalMapping = new IntList(40);
0412:                            logicalMapping = new IntList(20);
0413:                            Log.debug("Pagination started ..");
0414:                            state = processPaginationLevel(state, stateList,
0415:                                    maxRows);
0416:                        } else {
0417:                            state = processPrepareLevels(state, level, maxRows);
0418:                        }
0419:
0420:                        // if there is an other level to process, then use the finish state to
0421:                        // create a new start state, which will continue the report processing on
0422:                        // the next higher level.
0423:                        hasNext = (index < (levels.length - 1));
0424:                        if (hasNext) {
0425:                            index += 1;
0426:                            level = levels[index];
0427:                            processingContext.setProcessingLevel(level);
0428:                            processingContext.setProgressLevel(index);
0429:                            if (state.isFinish()) {
0430:                                state = state.restart();
0431:                                // this is a paranoid check ...
0432:                                if (state.getCurrentPage() != ReportState.BEFORE_FIRST_PAGE) {
0433:                                    throw new IllegalStateException(
0434:                                            "State was not set up properly");
0435:                                }
0436:                            } else {
0437:                                throw new IllegalStateException(
0438:                                        "Repaginate did not produce an finish state");
0439:                            }
0440:                        }
0441:                    } while (hasNext == true);
0442:
0443:                    // finally return the saved page states.
0444:                    processingContext.setPrepareRun(false);
0445:                } catch (ReportDataFactoryException e) {
0446:                    throw new ReportProcessingException(
0447:                            "Unable to initialize the report", e);
0448:                }
0449:
0450:                final long end = System.currentTimeMillis();
0451:                Log.debug("Pagination-Time: " + (end - start));
0452:
0453:            }
0454:
0455:            /**
0456:             * Processes the print level for the current report. This function will fill the report state list while performing
0457:             * the repagination.
0458:             *
0459:             * @param startState the start state for the print level.
0460:             * @param pageStates the list of report states that should receive the created page states.
0461:             * @param maxRows    the number of rows in the report (used to estaminate the current progress).
0462:             * @return the finish state for the report.
0463:             * @throws ReportProcessingException if there was a problem processing the report.
0464:             */
0465:            private ProcessState processPaginationLevel(
0466:                    final ProcessState startState,
0467:                    final PageStateList pageStates, final int maxRows)
0468:                    throws ReportProcessingException {
0469:                try {
0470:                    final boolean failOnError = ReportConfigurationUtil
0471:                            .isStrictErrorHandling(getReport()
0472:                                    .getReportConfiguration());
0473:                    final ReportProcessingErrorHandler errorHandler = new CollectingReportErrorHandler();
0474:                    final DefaultLayoutPagebreakHandler pagebreakHandler = new DefaultLayoutPagebreakHandler();
0475:
0476:                    final ProcessState initialReportState = startState
0477:                            .deriveForStorage();
0478:                    final PageState initialPageState = new PageState(
0479:                            initialReportState, outputProcessor.getPageCursor());
0480:                    pageStates.add(initialPageState);
0481:
0482:                    final ReportProgressEvent repaginationState = new ReportProgressEvent(
0483:                            this );
0484:
0485:                    // inner loop: process the complete report, calculate the function values
0486:                    // for the current level. Higher level functions are not available in the
0487:                    // dataRow.
0488:                    final int eventTrigger = Math.min(maxRows
0489:                            / MAX_EVENTS_PER_RUN, MIN_ROWS_PER_EVENT);
0490:
0491:                    ProcessState state = startState.deriveForStorage();
0492:                    state.setErrorHandler(errorHandler);
0493:                    validate(state);
0494:
0495:                    int pageEventCount = 0;
0496:                    // First and last derive of a page must be a storage derivate - this clones everything and does
0497:                    // not rely on the more complicated transactional layouting ..
0498:                    ProcessState fallBackState = startState
0499:                            .deriveForPagebreak();
0500:                    //      ProcessState debugState = startState.deriveForStorage();
0501:                    //      ProcessState lastCommitedState = null;
0502:
0503:                    Object rollbackPageState = null;
0504:                    int rollBackCount = 0;
0505:                    boolean isInRollBackMode = false;
0506:
0507:                    int eventCount = 0;
0508:                    int lastRow = -1;
0509:                    while (!state.isFinish()) {
0510:                        int logPageCount = outputProcessor
0511:                                .getLogicalPageCount();
0512:                        int physPageCount = outputProcessor
0513:                                .getPhysicalPageCount();
0514:
0515:                        checkInterrupted();
0516:                        if (lastRow != state.getCurrentDataItem()) {
0517:                            lastRow = state.getCurrentDataItem();
0518:                            if (eventCount == 0) {
0519:                                if (isPagebreaksSupported()
0520:                                        && fallBackState != null) {
0521:                                    repaginationState.reuse(
0522:                                            ReportProgressEvent.PAGINATING,
0523:                                            fallBackState.getCurrentDataItem(),
0524:                                            fallBackState.getNumberOfRows(),
0525:                                            fallBackState.getCurrentPage(),
0526:                                            fallBackState.getProgressLevel(),
0527:                                            fallBackState
0528:                                                    .getProgressLevelCount());
0529:                                } else {
0530:                                    repaginationState.reuse(
0531:                                            ReportProgressEvent.PAGINATING,
0532:                                            state.getCurrentDataItem(), state
0533:                                                    .getNumberOfRows(), state
0534:                                                    .getCurrentPage(), state
0535:                                                    .getProgressLevel(), state
0536:                                                    .getProgressLevelCount());
0537:                                }
0538:                                fireStateUpdate(repaginationState);
0539:                                eventCount += 1;
0540:                            } else {
0541:                                if (eventCount == eventTrigger) {
0542:                                    eventCount = 0;
0543:                                } else {
0544:                                    eventCount += 1;
0545:                                }
0546:                            }
0547:                        }
0548:
0549:                        final ProcessState restoreState = fallBackState;
0550:                        if (isPagebreaksSupported()) {
0551:                            if (isInRollBackMode == false) {
0552:                                if (pageEventCount == PAGE_EVENT_RATE) {
0553:
0554:                                    //              lastCommitedState = fallBackState.deriveForStorage();
0555:                                    //
0556:                                    final DefaultOutputFunction commitableOutputFunction = (DefaultOutputFunction) state
0557:                                            .getLayoutProcess()
0558:                                            .getOutputFunction();
0559:                                    final Renderer commitableRenderer = commitableOutputFunction
0560:                                            .getRenderer();
0561:                                    commitableRenderer
0562:                                            .createRollbackInformation();
0563:
0564:                                    //              Log.debug ("Deriving " + fallBackState.getProcessKey());
0565:                                    fallBackState = state.deriveForPagebreak();
0566:                                    //              debugState = state.deriveForStorage();
0567:                                    validate(state);
0568:                                    pageEventCount = 0;
0569:                                } else {
0570:                                    pageEventCount += 1;
0571:                                }
0572:                            } else {
0573:                                // on rollback, increase the count, but never create new fallback states.
0574:                                rollBackCount += 1;
0575:                            }
0576:                        }
0577:
0578:                        final ProcessState nextState = state.advance();
0579:                        state
0580:                                .setErrorHandler(IgnoreEverythingReportErrorHandler.INSTANCE);
0581:                        state = nextState;
0582:                        validate(state);
0583:
0584:                        final ReportStateKey nextStateKey = state
0585:                                .getProcessKey();
0586:
0587:                        if (errorHandler.isErrorOccured() == true) {
0588:                            final List childExceptions = Arrays
0589:                                    .asList(errorHandler.getErrors());
0590:                            errorHandler.clearErrors();
0591:                            if (failOnError) {
0592:                                throw new ReportEventException(
0593:                                        "Failed to dispatch an event.",
0594:                                        childExceptions);
0595:                            } else {
0596:                                final ReportEventException exception = new ReportEventException(
0597:                                        "Failed to dispatch an event.",
0598:                                        childExceptions);
0599:                                Log.error("Failed to dispatch an event.",
0600:                                        exception);
0601:                            }
0602:                        }
0603:
0604:                        final DefaultOutputFunction lm = (DefaultOutputFunction) state
0605:                                .getLayoutProcess().getOutputFunction();
0606:                        final Renderer renderer = lm.getRenderer();
0607:                        pagebreakHandler.setReportState(state);
0608:
0609:                        if (isInRollBackMode) {
0610:                            if (rollBackCount > PAGE_EVENT_RATE) {
0611:                                // we missed the state that caused the pagebreak. This means, that the report behaved
0612:                                // non-deterministic - which is bad.
0613:                                //throw new ReportProcessingException ("Failed to rollback during the page processing: " + rollBackCount);
0614:                            }
0615:
0616:                            // todo: Could be that we have to use the other key here..
0617:                            // was: state.getProcessKey()
0618:                            if (nextStateKey.equals(rollbackPageState)) {
0619:                                // reached the border case. We have to insert a manual pagebreak here or at least
0620:                                // we have to force the renderer to end the page right now.
0621:                                //Log.debug ("HERE: Found real pagebreak position. This might be the last state we process.");
0622:                                renderer.addPagebreak(state.getProcessKey());
0623:                            }
0624:                        }
0625:
0626:                        final boolean pagebreakEncountered = renderer
0627:                                .validatePages();
0628:                        if (pagebreakEncountered) {
0629:                            final Object lastVisibleStateKey = renderer
0630:                                    .getLastStateKey();
0631:                            if (isPagebreaksSupported()
0632:                                    && isInRollBackMode == false
0633:                                    && lastVisibleStateKey != null
0634:                                    && renderer.isOpen()) {
0635:                                if (lastVisibleStateKey.equals(nextStateKey) == false) {
0636:                                    // Roll back to the last known to be good position and process the states up to, but not
0637:                                    // including the current state. This way, we can fire the page-events *before* this band
0638:                                    // gets printed.
0639:                                    rollbackPageState = lastVisibleStateKey;
0640:                                    rollBackCount = 0;
0641:                                    state = restoreState.deriveForPagebreak();
0642:
0643:                                    final DefaultOutputFunction rollbackOutputFunction = (DefaultOutputFunction) state
0644:                                            .getLayoutProcess()
0645:                                            .getOutputFunction();
0646:                                    final Renderer rollbackRenderer = rollbackOutputFunction
0647:                                            .getRenderer();
0648:                                    rollbackRenderer.rollback();
0649:                                    if (SHOW_ROLLBACKS) {
0650:                                        Log
0651:                                                .debug("HERE: Encountered bad break, need to roll-back: "
0652:                                                        + rollbackPageState);
0653:                                        Log
0654:                                                .debug("HERE:                                         : "
0655:                                                        + state.getProcessKey());
0656:                                        Log
0657:                                                .debug("HERE:                                         : "
0658:                                                        + restoreState
0659:                                                                .getProcessKey());
0660:                                    }
0661:
0662:                                    validate(state);
0663:
0664:                                    isInRollBackMode = true;
0665:                                    fallBackState = null; // there is no way we can fall-back inside a roll-back ..
0666:                                    continue;
0667:                                } else {
0668:                                    // The current state printed content partially on the now finished page and there is more
0669:                                    // content on the currently open page. This is a in-between pagebreak, we invoke a pagebreak
0670:                                    // after this state has been processed.
0671:                                    if (SHOW_ROLLBACKS) {
0672:                                        Log
0673:                                                .debug("HERE: Encountered on-going break "
0674:                                                        + lastVisibleStateKey);
0675:                                    }
0676:                                }
0677:                            } else {
0678:                                if (SHOW_ROLLBACKS) {
0679:                                    Log
0680:                                            .debug("HERE: Encountered a good break or a roll-back break: "
0681:                                                    + isInRollBackMode);
0682:                                    Log
0683:                                            .debug("HERE:                                              : "
0684:                                                    + state.getProcessKey());
0685:                                }
0686:                                isInRollBackMode = false;
0687:                                rollbackPageState = null;
0688:                                rollBackCount = 0;
0689:                            }
0690:
0691:                            if (isPagebreaksSupported() == false) {
0692:                                // The commit causes all closed-nodes to become finishable. This allows the process-page
0693:                                // and the incremental-update methods to remove the nodes. For non-streaming targets (where
0694:                                // pagebreaks are possible) the commit state is managed manually
0695:                                renderer.applyAutoCommit();
0696:                            }
0697:
0698:                            if (renderer.processPage(pagebreakHandler, state
0699:                                    .getProcessKey(), true) == false) {
0700:                                throw new IllegalStateException(
0701:                                        "This cannot be. If the validation said we get a new page, how can we now get lost here");
0702:                            }
0703:
0704:                            state = state.commit();
0705:
0706:                            // can continue safely ..
0707:                            final int newLogPageCount = outputProcessor
0708:                                    .getLogicalPageCount();
0709:                            final int newPhysPageCount = outputProcessor
0710:                                    .getPhysicalPageCount();
0711:
0712:                            final int result = stateList.size() - 1;
0713:                            for (; physPageCount < newPhysPageCount; physPageCount++) {
0714:                                physicalMapping.add(result);
0715:                            }
0716:
0717:                            for (; logPageCount < newLogPageCount; logPageCount++) {
0718:                                logicalMapping.add(result);
0719:                            }
0720:
0721:                            if (state.isFinish() == false) {
0722:                                // A pagebreak has occured ...
0723:                                // We add all but the last state ..
0724:                                final PageState pageState = new PageState(state
0725:                                        .deriveForStorage(), outputProcessor
0726:                                        .getPageCursor());
0727:                                stateList.add(pageState);
0728:                            }
0729:
0730:                            if (isPagebreaksSupported()) {
0731:                                fallBackState = state.deriveForPagebreak();
0732:                                pageEventCount = 0;
0733:                                eventCount = 0;
0734:                            }
0735:                        } else {
0736:                            if (isPagebreaksSupported() == false) {
0737:                                renderer.applyAutoCommit();
0738:                            }
0739:
0740:                            // PageEventCount is zero on streaming exports and zero after a new rollback event is created.
0741:                            if (pageEventCount == 0
0742:                                    && isInRollBackMode == false) {
0743:                                renderer.processIncrementalUpdate(true);
0744:                            }
0745:                            state = state.commit();
0746:
0747:                            // Expected a pagebreak now, but did not encounter one.
0748:                            // todo: Could be that we have to use the other key here ..
0749:                            //          if (nextStateKey.equals(rollbackPageState))
0750:                            //          {
0751:                            //            // reached the border case. We have to insert a manual pagebreak here or at least
0752:                            //            // we have to force the renderer to end the page right now.
0753:                            //            // todo
0754:                            //            Log.debug("HERE: Ups, Found real pagebreak position. but where is my break?");
0755:                            //            renderer.addPagebreak(state.getProcessKey());
0756:                            //          }
0757:
0758:                            if (fallBackState != restoreState) {
0759:                                final DefaultOutputFunction commitableOutputFunction = (DefaultOutputFunction) state
0760:                                        .getLayoutProcess().getOutputFunction();
0761:                                final Renderer commitableRenderer = commitableOutputFunction
0762:                                        .getRenderer();
0763:                                commitableRenderer.applyRollbackInformation();
0764:                            }
0765:                        }
0766:
0767:                    }
0768:                    return initialReportState;
0769:                } catch (ContentProcessingException e) {
0770:                    throw new ReportProcessingException(
0771:                            "Content-Processing failed.", e);
0772:                }
0773:            }
0774:
0775:            private void validate(final ProcessState state) {
0776:                if (paranoidChecks) {
0777:                    final DefaultOutputFunction of = (DefaultOutputFunction) state
0778:                            .getLayoutProcess().getOutputFunction();
0779:                    final AbstractRenderer r = (AbstractRenderer) of
0780:                            .getRenderer();
0781:                    r.performParanoidModelCheck();
0782:                }
0783:            }
0784:
0785:            public boolean isPaginated() {
0786:                return stateList != null;
0787:            }
0788:
0789:            protected PageState getLogicalPageState(final int page) {
0790:                final int index = logicalMapping.get(page);
0791:                final PageState pageState = stateList.get(index);
0792:                if (pageState == null) {
0793:                    throw new IndexOutOfBoundsException(
0794:                            "The logical mapping between page " + page
0795:                                    + " and index " + index + " is invalid.");
0796:                }
0797:                return pageState;
0798:            }
0799:
0800:            protected PageState getPhysicalPageState(final int page) {
0801:                final int index = physicalMapping.get(page);
0802:                final PageState pageState = stateList.get(index);
0803:                if (pageState == null) {
0804:                    throw new IndexOutOfBoundsException(
0805:                            "The physical mapping between page " + page
0806:                                    + " and index " + index + " is invalid.");
0807:                }
0808:                return pageState;
0809:            }
0810:
0811:            public PageState processPage(final PageState pageState,
0812:                    final boolean performOutput)
0813:                    throws ReportProcessingException {
0814:                if (pageState == null) {
0815:                    throw new NullPointerException(
0816:                            "PageState must not be null.");
0817:                }
0818:                final boolean failOnError = ReportConfigurationUtil
0819:                        .isStrictErrorHandling(getReport()
0820:                                .getReportConfiguration());
0821:                final ReportProcessingErrorHandler errorHandler = new CollectingReportErrorHandler();
0822:                //todo
0823:
0824:                try {
0825:                    final ProcessState startState = pageState.getReportState();
0826:                    outputProcessor.setPageCursor(pageState.getPageCursor());
0827:                    final int maxRows = startState.getNumberOfRows();
0828:                    final ReportProgressEvent repaginationState = new ReportProgressEvent(
0829:                            this );
0830:                    final DefaultLayoutPagebreakHandler pagebreakHandler = new DefaultLayoutPagebreakHandler();
0831:                    // inner loop: process the complete report, calculate the function values
0832:                    // for the current level. Higher level functions are not available in the
0833:                    // dataRow.
0834:                    final int eventTrigger = Math.min(maxRows
0835:                            / MAX_EVENTS_PER_RUN, MIN_ROWS_PER_EVENT);
0836:
0837:                    Object rollbackPageState = null;
0838:
0839:                    ProcessState state = startState.deriveForStorage();
0840:                    ProcessState fallBackState = state.deriveForPagebreak();
0841:                    state.setErrorHandler(errorHandler);
0842:
0843:                    int rollBackCount = 0;
0844:                    boolean isInRollBackMode = false;
0845:                    int lastRow = -1;
0846:                    int eventCount = 0;
0847:                    int pageEventCount = 0;
0848:                    while (!state.isFinish()) {
0849:                        checkInterrupted();
0850:                        if (lastRow != state.getCurrentDataItem()) {
0851:                            lastRow = state.getCurrentDataItem();
0852:                            if (eventCount == 0) {
0853:                                repaginationState.reuse(
0854:                                        ReportProgressEvent.GENERATING_CONTENT,
0855:                                        state.getCurrentDataItem(), maxRows,
0856:                                        state.getCurrentPage(), state
0857:                                                .getProgressLevel(), state
0858:                                                .getProgressLevelCount());
0859:                                fireStateUpdate(repaginationState);
0860:                                eventCount += 1;
0861:                            } else {
0862:                                if (eventCount == eventTrigger) {
0863:                                    eventCount = 0;
0864:                                } else {
0865:                                    eventCount += 1;
0866:                                }
0867:                            }
0868:                        }
0869:
0870:                        final ProcessState restoreState = fallBackState;
0871:                        if (isPagebreaksSupported()) {
0872:                            if (isInRollBackMode == false) {
0873:                                if (pageEventCount == PAGE_EVENT_RATE) {
0874:                                    final DefaultOutputFunction commitableOutputFunction = (DefaultOutputFunction) state
0875:                                            .getLayoutProcess()
0876:                                            .getOutputFunction();
0877:                                    final Renderer commitableRenderer = commitableOutputFunction
0878:                                            .getRenderer();
0879:                                    commitableRenderer
0880:                                            .createRollbackInformation();
0881:
0882:                                    fallBackState = state.deriveForPagebreak();
0883:                                    pageEventCount = 0;
0884:                                } else {
0885:                                    pageEventCount += 1;
0886:                                }
0887:                            } else {
0888:                                // on rollback, increase the count, but never create new fallback states.
0889:                                rollBackCount += 1;
0890:                            }
0891:                        }
0892:
0893:                        final ProcessState nextState = state.advance();
0894:                        state
0895:                                .setErrorHandler(IgnoreEverythingReportErrorHandler.INSTANCE);
0896:                        state = nextState;
0897:
0898:                        final ReportStateKey nextStateKey = state
0899:                                .getProcessKey();
0900:
0901:                        if (errorHandler.isErrorOccured() == true) {
0902:                            final List childExceptions = Arrays
0903:                                    .asList(errorHandler.getErrors());
0904:                            errorHandler.clearErrors();
0905:                            if (failOnError) {
0906:                                throw new ReportEventException(
0907:                                        "Failed to dispatch an event.",
0908:                                        childExceptions);
0909:                            } else {
0910:                                final ReportEventException exception = new ReportEventException(
0911:                                        "Failed to dispatch an event.",
0912:                                        childExceptions);
0913:                                Log.error("Failed to dispatch an event.",
0914:                                        exception);
0915:                            }
0916:                        }
0917:
0918:                        final DefaultOutputFunction lm = (DefaultOutputFunction) state
0919:                                .getLayoutProcess().getOutputFunction();
0920:                        final Renderer renderer = lm.getRenderer();
0921:                        pagebreakHandler.setReportState(state);
0922:
0923:                        if (isInRollBackMode) {
0924:                            if (rollBackCount > PAGE_EVENT_RATE) {
0925:                                // we missed the state that caused the pagebreak. This means, that the report behaved
0926:                                // non-deterministic - which is bad.
0927:                                //throw new ReportProcessingException ("Failed to rollback during the page processing: " + rollBackCount);
0928:                            }
0929:
0930:                            if (nextStateKey.equals(rollbackPageState)) {
0931:                                // reached the border case. We have to insert a manual pagebreak here or at least
0932:                                // we have to force the renderer to end the page right now.
0933:                                //            Log.debug ("HERE: Found real pagebreak position. This might be the last state we process.");
0934:                                renderer.addPagebreak(state.getProcessKey());
0935:                            }
0936:                        }
0937:
0938:                        final boolean pagebreakEncountered = (renderer
0939:                                .validatePages());
0940:                        if (pagebreakEncountered) {
0941:                            final Object lastStateKey = renderer
0942:                                    .getLastStateKey();
0943:                            if (isPagebreaksSupported()
0944:                                    && isInRollBackMode == false
0945:                                    && renderer.isOpen()
0946:                                    && lastStateKey != null) {
0947:                                if (lastStateKey.equals(nextStateKey) == false) {
0948:                                    //              Log.debug ("HERE: Encountered bad break, need to roll-back");
0949:
0950:                                    // Roll back to the last known to be good position and process the states up to, but not
0951:                                    // including the current state. This way, we can fire the page-events *before* this band
0952:                                    // gets printed.
0953:                                    rollbackPageState = lastStateKey;
0954:                                    rollBackCount = 0;
0955:                                    state = restoreState.deriveForPagebreak();
0956:
0957:                                    final DefaultOutputFunction rollbackOutputFunction = (DefaultOutputFunction) state
0958:                                            .getLayoutProcess()
0959:                                            .getOutputFunction();
0960:                                    final Renderer rollbackRenderer = rollbackOutputFunction
0961:                                            .getRenderer();
0962:                                    rollbackRenderer.rollback();
0963:                                    if (SHOW_ROLLBACKS) {
0964:                                        Log
0965:                                                .debug("HERE: Encountered bad break, need to roll-back: "
0966:                                                        + rollbackPageState);
0967:                                        Log
0968:                                                .debug("HERE:                                         : "
0969:                                                        + state.getProcessKey());
0970:                                        Log
0971:                                                .debug("HERE:                                         : "
0972:                                                        + restoreState
0973:                                                                .getProcessKey());
0974:                                    }
0975:
0976:                                    validate(state);
0977:
0978:                                    isInRollBackMode = true;
0979:                                    continue;
0980:                                }
0981:                                //            else
0982:                                //            {
0983:                                //              // The current state printed content partially on the now finished page and there is more
0984:                                //              // content on the currently open page. This is a in-between pagebreak, we invoke a pagebreak
0985:                                //              // after this state has been processed.
0986:                                //              Log.debug ("HERE: Encountered on-going break " + lastStateKey);
0987:                                //            }
0988:                            }
0989:                            //          else
0990:                            //          {
0991:                            //            Log.debug ("HERE: Encountered a good break or a roll-back break: " + isInRollBackMode);
0992:                            //            Log.debug ("HERE:                                              : " + state.getProcessKey());
0993:                            //          }
0994:                            if (isPagebreaksSupported() == false) {
0995:                                // The commit causes all closed-nodes to become finishable. This allows the process-page
0996:                                // and the incremental-update methods to remove the nodes. For non-streaming targets (where
0997:                                // pagebreaks are possible) the commit state is managed manually
0998:                                renderer.applyAutoCommit();
0999:                            }
1000:
1001:                            if (renderer.processPage(pagebreakHandler, state
1002:                                    .getProcessKey(), performOutput) == false) {
1003:                                throw new IllegalStateException(
1004:                                        "This must not be.");
1005:                            }
1006:
1007:                            state = state.commit();
1008:                            if (renderer.isOpen()) {
1009:                                // No need to create a copy here. It is part of the contract that the resulting page state must be
1010:                                // cloned before it can be used again. The only place where it is used is this method, so we can
1011:                                // be pretty sure that this contract is valid.
1012:                                return new PageState(state, outputProcessor
1013:                                        .getPageCursor());
1014:                            }
1015:                        } else {
1016:                            if (isPagebreaksSupported() == false) {
1017:                                // The commit causes all closed-nodes to become finishable. This allows the process-page
1018:                                // and the incremental-update methods to remove the nodes. For non-streaming targets (where
1019:                                // pagebreaks are possible) the commit state is managed manually
1020:                                renderer.applyAutoCommit();
1021:                            }
1022:
1023:                            if (pageEventCount == 0
1024:                                    && isInRollBackMode == false) {
1025:                                renderer
1026:                                        .processIncrementalUpdate(performOutput);
1027:                            }
1028:                            state = state.commit();
1029:
1030:                            // Expected a pagebreak now, but did not encounter one.
1031:                            //          if (nextStateKey.equals(rollbackPageState))
1032:                            //          {
1033:                            //            // reached the border case. We have to insert a manual pagebreak here or at least
1034:                            //            // we have to force the renderer to end the page right now.
1035:                            //            Log.debug ("HERE: Ups, Found real pagebreak position. but where is my break?");
1036:                            //            //renderer.addPagebreak(state.getProcessKey());
1037:                            //          }
1038:                            if (fallBackState != restoreState) {
1039:                                final DefaultOutputFunction commitableOutputFunction = (DefaultOutputFunction) state
1040:                                        .getLayoutProcess().getOutputFunction();
1041:                                final Renderer commitableRenderer = commitableOutputFunction
1042:                                        .getRenderer();
1043:                                commitableRenderer.applyRollbackInformation();
1044:                            }
1045:                        }
1046:                    }
1047:
1048:                    // We should never reach this point, if this function has been called by the PageStateList.
1049:                    return null;
1050:                }
1051:                //    catch (CloneNotSupportedException e)
1052:                //    {
1053:                //      throw new ReportProcessingException("Clone failed. This cannot be.");
1054:                //    }
1055:                catch (ContentProcessingException e) {
1056:                    throw new ReportProcessingException(
1057:                            "Content-Processing failed.", e);
1058:                }
1059:            }
1060:
1061:            public void processReport() throws ReportProcessingException {
1062:                if (Log.isDebugEnabled()) {
1063:                    Log.debug(new MemoryUsageMessage(System
1064:                            .identityHashCode(Thread.currentThread())
1065:                            + ": Report processing time: Starting: "));
1066:                }
1067:                try {
1068:                    final long startTime = System.currentTimeMillis();
1069:                    if (isPaginated() == false) {
1070:                        // Processes the whole report ..
1071:                        prepareReportProcessing();
1072:                    }
1073:
1074:                    final long paginateTime = System.currentTimeMillis();
1075:                    if (Log.isDebugEnabled()) {
1076:                        Log.debug(new MemoryUsageMessage(System
1077:                                .identityHashCode(Thread.currentThread())
1078:                                + ": Report processing time: Pagination time: "
1079:                                + ((paginateTime - startTime) / 1000.0)));
1080:                    }
1081:                    if (getLogicalPageCount() == 0) {
1082:                        throw new EmptyReportException(
1083:                                "Report did not generate any content.");
1084:                    }
1085:
1086:                    // Start from scratch ...
1087:                    PageState state = getLogicalPageState(0);
1088:                    while (state != null) {
1089:                        state = processPage(state, true);
1090:                    }
1091:                    final long endTime = System.currentTimeMillis();
1092:                    if (Log.isDebugEnabled()) {
1093:                        Log.debug(new MemoryUsageMessage(System
1094:                                .identityHashCode(Thread.currentThread())
1095:                                + ": Report processing time: "
1096:                                + ((endTime - startTime) / 1000.0)));
1097:                    }
1098:                } catch (EmptyReportException re) {
1099:                    throw re;
1100:                } catch (ReportProcessingException re) {
1101:                    Log.error(System.identityHashCode(Thread.currentThread())
1102:                            + ": Report processing failed.");
1103:                    throw re;
1104:                } catch (Exception e) {
1105:                    Log.error(System.identityHashCode(Thread.currentThread())
1106:                            + ": Report processing failed.");
1107:                    throw new ReportProcessingException(
1108:                            "Failed to process the report", e);
1109:                }
1110:                if (Log.isDebugEnabled()) {
1111:                    Log.debug(System.identityHashCode(Thread.currentThread())
1112:                            + ": Report processing finished.");
1113:                }
1114:            }
1115:
1116:            public int getLogicalPageCount() {
1117:                return logicalMapping.size();
1118:            }
1119:
1120:            /**
1121:             * Checks, whether the output mode may generate pagebreaks. If we have to deal with pagebreaks, we may have to perform
1122:             * roll-backs and commits to keep the pagebreaks in sync with the state-processing. This is ugly, expensive and you
1123:             * better dont try this at home.
1124:             * <p/>
1125:             * The roll-back is done for paginated and flow-report outputs, but if we have no autmoatic and manual pagebreaks,
1126:             * there is no need to even consider to roll-back to a state before the pagebreak (which will never occur).
1127:             *
1128:             * @return a flag indicating whether the output target supports pagebreaks.
1129:             */
1130:            protected boolean isPagebreaksSupported() {
1131:                return pagebreaksSupported;
1132:            }
1133:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.