001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * AbstractRenderer.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.layout;
030:
031: import org.jfree.report.Band;
032: import org.jfree.report.InvalidReportStateException;
033: import org.jfree.report.PageDefinition;
034: import org.jfree.report.function.ExpressionRuntime;
035: import org.jfree.report.layout.model.BlockRenderBox;
036: import org.jfree.report.layout.model.BreakMarkerRenderBox;
037: import org.jfree.report.layout.model.LogicalPageBox;
038: import org.jfree.report.layout.model.RenderBox;
039: import org.jfree.report.layout.model.RenderLength;
040: import org.jfree.report.layout.model.RenderNode;
041: import org.jfree.report.layout.model.WatermarkAreaBox;
042: import org.jfree.report.layout.model.context.BoxDefinition;
043: import org.jfree.report.layout.output.ContentProcessingException;
044: import org.jfree.report.layout.output.LayoutPagebreakHandler;
045: import org.jfree.report.layout.output.OutputProcessor;
046: import org.jfree.report.layout.output.OutputProcessorFeature;
047: import org.jfree.report.layout.output.OutputProcessorMetaData;
048: import org.jfree.report.layout.process.ApplyAutoCommitStep;
049: import org.jfree.report.layout.process.ApplyCachedValuesStep;
050: import org.jfree.report.layout.process.ApplyCommitStep;
051: import org.jfree.report.layout.process.CanvasMajorAxisLayoutStep;
052: import org.jfree.report.layout.process.CommitStep;
053: import org.jfree.report.layout.process.ComputeStaticPropertiesProcessStep;
054: import org.jfree.report.layout.process.InfiniteMajorAxisLayoutStep;
055: import org.jfree.report.layout.process.InfiniteMinorAxisLayoutStep;
056: import org.jfree.report.layout.process.ParagraphLineBreakStep;
057: import org.jfree.report.layout.process.RevalidateAllAxisLayoutStep;
058: import org.jfree.report.layout.process.RollbackStep;
059: import org.jfree.report.layout.process.ValidateModelStep;
060: import org.jfree.report.layout.style.ManualBreakIndicatorStyleSheet;
061: import org.jfree.report.layout.style.SectionKeepTogetherStyleSheet;
062: import org.jfree.report.layout.style.SimpleStyleSheet;
063: import org.jfree.report.style.BandDefaultStyleSheet;
064: import org.jfree.report.style.StyleKey;
065: import org.jfree.report.style.StyleSheet;
066: import org.jfree.report.util.InstanceID;
067: import org.jfree.util.FastStack;
068:
069: /**
070: * The LayoutSystem is a simplified version of the LibLayout-rendering system.
071: *
072: * @author Thomas Morgner
073: */
074: public abstract class AbstractRenderer implements Renderer {
075: private static final boolean ENABLE_GROUP_SECTION = true;
076:
077: private static class Section {
078: private int type;
079: private RenderBox sectionBox;
080:
081: protected Section(final int type, final RenderBox sectionBox) {
082: this .type = type;
083: this .sectionBox = sectionBox;
084: }
085:
086: public int getType() {
087: return type;
088: }
089:
090: public RenderBox getSectionBox() {
091: return sectionBox;
092: }
093: }
094:
095: private static class GroupSection {
096: private static final double COMMON_GROWTH = 1.2;
097: private static final int INITIAL_COMMON_SIZE = 50;
098:
099: private RenderBox addBox;
100: private RenderBox groupBox;
101: private int childCount;
102: private int nextBoxStart;
103: private StyleSheet styleSheet;
104:
105: protected GroupSection(final RenderBox groupBox,
106: final StyleSheet styleSheet) {
107: if (groupBox == null) {
108: throw new NullPointerException();
109: }
110: this .styleSheet = styleSheet;
111: this .groupBox = groupBox;
112: this .childCount = 0;
113: this .nextBoxStart = INITIAL_COMMON_SIZE;
114: this .addBox = groupBox;
115: }
116:
117: protected GroupSection(final RenderBox groupBox,
118: final RenderBox addBox, final int childCount,
119: final int nextBoxStart, final StyleSheet styleSheet) {
120: if (groupBox == null) {
121: throw new NullPointerException();
122: }
123: this .groupBox = groupBox;
124: this .addBox = addBox;
125: this .childCount = childCount;
126: this .nextBoxStart = nextBoxStart;
127: this .styleSheet = styleSheet;
128: }
129:
130: public RenderBox getAddBox() {
131: return addBox;
132: }
133:
134: public RenderBox getGroupBox() {
135: return groupBox;
136: }
137:
138: public void addedSection(final RenderNode node,
139: final Object stateKey) {
140: childCount += 1;
141: if (childCount == nextBoxStart) {
142: if (addBox != groupBox) {
143: addBox.close();
144: }
145: final BlockRenderBox commonBox = new BlockRenderBox(
146: styleSheet, BoxDefinition.EMPTY, stateKey);
147: commonBox.setName("Common-Section");
148: groupBox.addChild(commonBox);
149: addBox = commonBox;
150:
151: nextBoxStart += nextBoxStart * COMMON_GROWTH;
152: }
153: addBox.addChild(node);
154: }
155:
156: public void close() {
157: if (addBox != groupBox) {
158: addBox.close();
159: }
160: groupBox.close();
161: }
162:
163: public int getChildCount() {
164: return childCount;
165: }
166:
167: public int getNextBoxStart() {
168: return nextBoxStart;
169: }
170:
171: public StyleSheet getStyleSheet() {
172: return styleSheet;
173: }
174: }
175:
176: private LogicalPageBox pageBox;
177: private LayoutBuilder layoutBuilder;
178:
179: private ValidateModelStep validateModelStep;
180: private ComputeStaticPropertiesProcessStep staticPropertiesStep;
181: private ParagraphLineBreakStep paragraphLineBreakStep;
182: private InfiniteMinorAxisLayoutStep minorAxisLayoutStep;
183: private InfiniteMajorAxisLayoutStep majorAxisLayoutStep;
184: private CanvasMajorAxisLayoutStep canvasMajorAxisLayoutStep;
185: private RevalidateAllAxisLayoutStep revalidateAllAxisLayoutStep;
186: private CommitStep commitStep;
187: private ApplyCommitStep applyCommitStep;
188: private RollbackStep rollbackStep;
189: private ApplyAutoCommitStep applyAutoCommitStep;
190:
191: private OutputProcessorMetaData metaData;
192: private OutputProcessor outputProcessor;
193: private Section section;
194: private int pagebreaks;
195: private boolean dirty;
196: private Object lastStateKey;
197: private ApplyCachedValuesStep applyCachedValuesStep;
198: private SimpleStyleSheet manualBreakBoxStyle;
199: private SimpleStyleSheet bandWithoutKeepTogetherStyle;
200: private SimpleStyleSheet bandWithKeepTogetherStyle;
201: private boolean readOnly;
202: private FastStack groupStack;
203: private Object stateKey;
204: private boolean paranoidChecks;
205:
206: protected AbstractRenderer(final OutputProcessor outputProcessor) {
207: this .outputProcessor = outputProcessor;
208: this .metaData = outputProcessor.getMetaData();
209: this .layoutBuilder = new LayoutBuilder(metaData);
210: this .paranoidChecks = "true".equals(metaData.getConfiguration()
211: .getConfigProperty(
212: "org.jfree.report.layout.ParanoidChecks"));
213: this .validateModelStep = new ValidateModelStep();
214: this .staticPropertiesStep = new ComputeStaticPropertiesProcessStep();
215: this .paragraphLineBreakStep = new ParagraphLineBreakStep();
216: this .minorAxisLayoutStep = new InfiniteMinorAxisLayoutStep();
217: this .majorAxisLayoutStep = new InfiniteMajorAxisLayoutStep();
218: this .canvasMajorAxisLayoutStep = new CanvasMajorAxisLayoutStep();
219: this .revalidateAllAxisLayoutStep = new RevalidateAllAxisLayoutStep();
220: this .applyCachedValuesStep = new ApplyCachedValuesStep();
221: this .commitStep = new CommitStep();
222: this .applyAutoCommitStep = new ApplyAutoCommitStep();
223: this .applyCommitStep = new ApplyCommitStep();
224: this .rollbackStep = new RollbackStep();
225:
226: this .groupStack = new FastStack();
227:
228: bandWithKeepTogetherStyle = new SimpleStyleSheet(
229: new SectionKeepTogetherStyleSheet(true), StyleKey
230: .getDefinedStyleKeys());
231: bandWithoutKeepTogetherStyle = new SimpleStyleSheet(
232: new SectionKeepTogetherStyleSheet(false), StyleKey
233: .getDefinedStyleKeys());
234:
235: }
236:
237: public Object getStateKey() {
238: return stateKey;
239: }
240:
241: public void setStateKey(final Object stateKey) {
242: this .stateKey = stateKey;
243: }
244:
245: public OutputProcessor getOutputProcessor() {
246: return outputProcessor;
247: }
248:
249: public void startReport(final PageDefinition pageDefinition) {
250: if (readOnly) {
251: throw new IllegalStateException();
252: }
253: this .pageBox = new LogicalPageBox(pageDefinition);
254: this .groupStack.push(new GroupSection(pageBox.getContentArea(),
255: bandWithoutKeepTogetherStyle));
256: this .dirty = true;
257: }
258:
259: public void startGroup(final boolean keepTogether) {
260: if (readOnly) {
261: throw new IllegalStateException();
262: }
263: if (ENABLE_GROUP_SECTION) {
264: final SimpleStyleSheet style;
265: if (keepTogether) {
266: style = bandWithKeepTogetherStyle;
267: } else {
268: style = bandWithoutKeepTogetherStyle;
269: }
270:
271: final BlockRenderBox groupBox = new BlockRenderBox(style,
272: BoxDefinition.EMPTY, null);
273: groupBox.setName("Group-Section-" + groupStack.size());
274: addBox(groupBox);
275: this .groupStack.push(new GroupSection(groupBox,
276: bandWithoutKeepTogetherStyle));
277: }
278: }
279:
280: private void addBox(final RenderNode node, final Object stateKey) {
281: final GroupSection groupSection = (GroupSection) groupStack
282: .peek();
283: groupSection.addedSection(node, stateKey);
284: }
285:
286: private void addBox(final RenderNode node) {
287: final GroupSection groupSection = (GroupSection) groupStack
288: .peek();
289: groupSection.addedSection(node, stateKey);
290: }
291:
292: public void startSection(final int type) {
293: if (readOnly) {
294: throw new IllegalStateException();
295: }
296: final BlockRenderBox sectionBox;
297:
298: if (type == Renderer.TYPE_WATERMARK) {
299: final BoxDefinition boxDefinition = new BoxDefinition();
300: boxDefinition.setPreferredHeight(new RenderLength(
301: this .pageBox.getPageHeight(), false));
302: sectionBox = new BlockRenderBox(
303: bandWithoutKeepTogetherStyle, boxDefinition, null);
304: } else {
305: sectionBox = new BlockRenderBox(
306: bandWithoutKeepTogetherStyle, BoxDefinition.EMPTY,
307: null);
308: }
309:
310: sectionBox.setName("Section-" + type);
311: this .section = new Section(type, sectionBox);
312: }
313:
314: public void endSection() {
315: if (readOnly) {
316: throw new IllegalStateException();
317: }
318: final Section section = this .section;
319: this .section = null;
320: final RenderBox sectionBox = section.getSectionBox();
321: sectionBox.close();
322:
323: if (sectionBox.getFirstChild() == null) {
324: // the whole section is empty; therefore we can ignore it.
325: return;
326: }
327:
328: switch (section.getType()) {
329: case TYPE_NORMALFLOW: {
330: addBox(sectionBox);
331: break;
332: }
333: case TYPE_FOOTER: {
334: final BlockRenderBox footerArea = pageBox.getFooterArea();
335: footerArea.clear();
336: footerArea.addChild(sectionBox);
337: break;
338: }
339: case TYPE_HEADER: {
340: final BlockRenderBox headerArea = pageBox.getHeaderArea();
341: headerArea.clear();
342: headerArea.addChild(sectionBox);
343: break;
344: }
345: case TYPE_WATERMARK: {
346: // ignore for now.
347: final WatermarkAreaBox watermarkArea = pageBox
348: .getWatermarkArea();
349: watermarkArea.clear();
350: watermarkArea.addChild(sectionBox);
351: break;
352: }
353: default:
354: throw new IllegalStateException("Type " + section.getType()
355: + " not recognized");
356: }
357: this .dirty = true;
358: }
359:
360: public void endGroup() {
361: if (readOnly) {
362: throw new IllegalStateException();
363: }
364: if (ENABLE_GROUP_SECTION) {
365: final GroupSection groupSection = (GroupSection) groupStack
366: .pop();
367: groupSection.close();
368: }
369: }
370:
371: protected LogicalPageBox getPageBox() {
372: return pageBox;
373: }
374:
375: public void endReport() {
376: if (readOnly) {
377: throw new IllegalStateException();
378: }
379: final GroupSection groupSection = (GroupSection) groupStack
380: .pop();
381: groupSection.close();
382:
383: pageBox.close();
384: this .dirty = true;
385: }
386:
387: public void add(final Band band, final ExpressionRuntime runtime,
388: final Object stateKey) {
389: if (readOnly) {
390: throw new IllegalStateException();
391: }
392: final RenderBox sectionBox = section.getSectionBox();
393: layoutBuilder.add(sectionBox, band, runtime, stateKey);
394: }
395:
396: public boolean validatePages() throws ContentProcessingException {
397: if (readOnly) {
398: throw new IllegalStateException();
399: }
400: // Pagination time without dirty-flag: 875067
401: if (pageBox == null) {
402: // StartReport has not been called yet ..
403: return false;
404: }
405:
406: if (dirty) {
407: setLastStateKey(null);
408: setPagebreaks(0);
409: if (validateModelStep.isLayoutable(pageBox) == false) {
410: return false;
411: }
412:
413: // These structural processors will skip old nodes. These beasts cannot be cached otherwise.
414: staticPropertiesStep.compute(pageBox, metaData);
415: paragraphLineBreakStep.compute(pageBox);
416:
417: minorAxisLayoutStep.compute(pageBox);
418: majorAxisLayoutStep.compute(pageBox);
419: canvasMajorAxisLayoutStep.compute(pageBox);
420: revalidateAllAxisLayoutStep.compute(pageBox, metaData);
421:
422: applyCachedValuesStep.compute(pageBox);
423: return isPageFinished();
424: }
425: return false;
426: }
427:
428: protected void clearDirty() {
429: dirty = false;
430: }
431:
432: protected abstract boolean isPageFinished();
433:
434: public void processIncrementalUpdate(final boolean performOutput)
435: throws ContentProcessingException {
436: dirty = false;
437: }
438:
439: public boolean processPage(final LayoutPagebreakHandler handler,
440: final Object commitMarker, final boolean performOutput)
441: throws ContentProcessingException {
442: if (readOnly) {
443: throw new IllegalStateException();
444: }
445: // Pagination time without dirty-flag: 875067
446: if (pageBox == null) {
447: // StartReport has not been called yet ..
448: // Log.debug ("PageBox null");
449: return false;
450: }
451:
452: if (dirty == false) {
453: // Log.debug ("Not dirty");
454: return false;
455: }
456:
457: setLastStateKey(null);
458: setPagebreaks(0);
459: if (validateModelStep.isLayoutable(pageBox) == false) {
460: // Log.debug ("Not layoutable");
461: return false;
462: }
463:
464: // processes the current page
465: boolean repeat = true;
466: while (repeat) {
467: if (handler != null) {
468: handler.pageFinished();
469: }
470:
471: if (outputProcessor.getMetaData().isFeatureSupported(
472: OutputProcessorFeature.PAGEBREAKS)) {
473: createRollbackInformation();
474: applyRollbackInformation();
475: performParanoidModelCheck();
476: }
477:
478: staticPropertiesStep.compute(pageBox, metaData);
479: paragraphLineBreakStep.compute(pageBox);
480:
481: minorAxisLayoutStep.compute(pageBox);
482: majorAxisLayoutStep.compute(pageBox);
483: canvasMajorAxisLayoutStep.compute(pageBox);
484: revalidateAllAxisLayoutStep.compute(pageBox, metaData);
485:
486: applyCachedValuesStep.compute(pageBox);
487:
488: repeat = performPagination(handler, performOutput);
489: }
490: dirty = false;
491: return (pagebreaks > 0);
492: }
493:
494: protected abstract boolean performPagination(
495: LayoutPagebreakHandler handler, final boolean performOutput)
496: throws ContentProcessingException;
497:
498: protected void debugPrint(final LogicalPageBox pageBox) {
499: }
500:
501: public Object getLastStateKey() {
502: return lastStateKey;
503: }
504:
505: public void setLastStateKey(final Object lastStateKey) {
506: this .lastStateKey = lastStateKey;
507: }
508:
509: protected void setPagebreaks(final int pagebreaks) {
510: this .pagebreaks = pagebreaks;
511: }
512:
513: public int getPagebreaks() {
514: return pagebreaks;
515: }
516:
517: public boolean isOpen() {
518: if (pageBox == null) {
519: return false;
520: }
521: return pageBox.isOpen();
522: }
523:
524: public boolean isValid() {
525: return readOnly == false;
526: }
527:
528: public Renderer deriveForStorage() {
529: try {
530: final AbstractRenderer renderer = (AbstractRenderer) clone();
531: renderer.readOnly = false;
532: if (pageBox != null) {
533: renderer.pageBox = (LogicalPageBox) pageBox
534: .derive(true);
535: if (section != null) {
536: final RenderNode nodeById = renderer.pageBox
537: .findNodeById(section.getSectionBox()
538: .getInstanceId());
539: renderer.section = new Section(section.getType(),
540: (RenderBox) nodeById);
541: }
542: }
543:
544: final int stackSize = groupStack.size();
545: final Object[] tempList = new Object[stackSize];
546:
547: renderer.groupStack = (FastStack) groupStack.clone();
548: final int tempListLength = tempList.length;
549: for (int i = 0; i < tempListLength; i++) {
550: tempList[i] = renderer.groupStack.pop();
551: }
552:
553: // the stack is empty now ..
554: // lets fill it again ..
555: for (int i = tempListLength - 1; i >= 0; i--) {
556: final GroupSection section = (GroupSection) tempList[i];
557:
558: final RenderBox groupBox = section.getGroupBox();
559: final InstanceID groupBoxInstanceId = groupBox
560: .getInstanceId();
561: final RenderBox groupBoxClone = (RenderBox) renderer.pageBox
562: .findNodeById(groupBoxInstanceId);
563: if (groupBoxClone == null) {
564: throw new IllegalStateException(
565: "The pagebox did no longer contain the stored node.");
566: }
567: if (groupBoxClone == groupBox) {
568: throw new IllegalStateException(
569: "Thought you wanted a groupBoxClone");
570: }
571:
572: final RenderBox addBox = section.getAddBox();
573: final RenderBox addBoxClone;
574: if (addBox == groupBox) {
575: addBoxClone = groupBoxClone;
576: } else {
577: final InstanceID addBoxInstanceId = addBox
578: .getInstanceId();
579: addBoxClone = (RenderBox) renderer.pageBox
580: .findNodeById(addBoxInstanceId);
581: if (addBoxClone == null) {
582: throw new IllegalStateException(
583: "The pagebox did no longer contain the stored node.");
584: }
585: if (addBoxClone == addBox) {
586: throw new IllegalStateException(
587: "Thought you wanted a groupBoxClone");
588: }
589: }
590: renderer.groupStack.push(new GroupSection(
591: groupBoxClone, addBoxClone, section
592: .getChildCount(), section
593: .getNextBoxStart(), section
594: .getStyleSheet()));
595: }
596: return renderer;
597: } catch (CloneNotSupportedException cne) {
598: throw new InvalidReportStateException(
599: "Failed to derive Renderer", cne);
600: }
601: }
602:
603: public Renderer deriveForPagebreak() {
604: try {
605: final AbstractRenderer renderer = (AbstractRenderer) clone();
606: renderer.readOnly = true;
607: if (pageBox != null) {
608: if (section != null) {
609: renderer.section = new Section(section.getType(),
610: section.getSectionBox());
611: }
612: }
613:
614: final int stackSize = groupStack.size();
615: final Object[] tempList = new Object[stackSize];
616: renderer.groupStack = (FastStack) groupStack.clone();
617: final int tempListLength = tempList.length;
618: for (int i = 0; i < tempListLength; i++) {
619: tempList[i] = renderer.groupStack.pop();
620: }
621:
622: // the stack is empty now ..
623: // lets fill it again ..
624: for (int i = tempListLength - 1; i >= 0; i--) {
625: final GroupSection section = (GroupSection) tempList[i];
626:
627: final RenderBox groupBox = section.getGroupBox();
628: final RenderBox addBox = section.getAddBox();
629:
630: // validate(addBox, groupBox);
631: renderer.groupStack.push(new GroupSection(groupBox,
632: addBox, section.getChildCount(), section
633: .getNextBoxStart(), section
634: .getStyleSheet()));
635: }
636: return renderer;
637: } catch (CloneNotSupportedException cne) {
638: throw new InvalidReportStateException(
639: "Failed to derive Renderer", cne);
640: }
641: }
642:
643: public void performParanoidModelCheck() {
644: if (paranoidChecks) {
645: final int stackSize = groupStack.size();
646:
647: // the stack is empty now ..
648: // lets fill it again ..
649: for (int i = 0; i < stackSize; i++) {
650: final GroupSection section = (GroupSection) groupStack
651: .get(i);
652:
653: final RenderBox groupBox = section.getGroupBox();
654: final RenderBox addBox = section.getAddBox();
655:
656: // step 1: Check whether addbox is a child of groupbox
657: RenderBox c = addBox;
658: while (c != groupBox) {
659: c = c.getParent();
660: if (c == null) {
661: throw new NullPointerException(
662: "Failed to locate parent");
663: }
664: }
665:
666: c = addBox;
667: while (c != null) {
668: if (c.isOpen() == false) {
669: throw new NullPointerException(
670: "Add-Box is not open: "
671: + c.isMarkedOpen() + ' '
672: + c.isMarkedSeen());
673: }
674: c = c.getParent();
675: }
676: }
677: }
678: }
679:
680: public Object clone() throws CloneNotSupportedException {
681: return super .clone();
682: }
683:
684: public void addPagebreak(final Object stateKey) {
685: if (readOnly) {
686: throw new IllegalStateException();
687: }
688: if (this .manualBreakBoxStyle == null) {
689: final ManualBreakIndicatorStyleSheet mbis = new ManualBreakIndicatorStyleSheet(
690: BandDefaultStyleSheet.getBandDefaultStyle());
691: this .manualBreakBoxStyle = new SimpleStyleSheet(mbis,
692: StyleKey.getDefinedStyleKeys());
693: }
694:
695: final RenderBox sectionBox = new BreakMarkerRenderBox(
696: manualBreakBoxStyle, BoxDefinition.EMPTY, stateKey);
697: sectionBox.setName("pagebreak");
698: sectionBox.close();
699: addBox(sectionBox, stateKey);
700: }
701:
702: public boolean clearPendingPageStart(
703: final LayoutPagebreakHandler layoutPagebreakHandler) {
704: // intentionally left empty.
705: return false;
706: }
707:
708: public boolean isPageStartPending() {
709: return false;
710: }
711:
712: public boolean isDirty() {
713: return dirty;
714: }
715:
716: public void createRollbackInformation() {
717: if (pageBox != null) {
718: commitStep.compute(pageBox);
719: validateAfterCommit();
720: }
721: }
722:
723: public void applyRollbackInformation() {
724: if (pageBox != null) {
725: applyCommitStep.compute(pageBox);
726: }
727: }
728:
729: public void validateAfterCommit() {
730: if (paranoidChecks) {
731: final int stackSize = groupStack.size();
732: for (int i = 0; i < stackSize; i++) {
733: final GroupSection section = (GroupSection) groupStack
734: .get(i);
735:
736: final RenderBox groupBox = section.getGroupBox();
737: final RenderBox addBox = section.getAddBox();
738:
739: if (groupBox.isMarkedSeen() == false) {
740: throw new IllegalStateException();
741: }
742: if (addBox.isMarkedOpen() == false) {
743: throw new IllegalStateException();
744: }
745: }
746: }
747: }
748:
749: public void rollback() {
750: readOnly = false;
751: if (pageBox != null) {
752: rollbackStep.compute(pageBox);
753: }
754: }
755:
756: public void applyAutoCommit() {
757: if (pageBox != null) {
758: applyAutoCommitStep.compute(pageBox);
759: }
760: }
761: }
|