001: /*
002: * $Id: SAXiTextHandler.java 2917 2007-09-08 20:55:00Z psoares33 $
003: * $Name: $
004: *
005: * Copyright 2001, 2002 by Bruno Lowagie.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.xml;
052:
053: import java.lang.reflect.Field;
054: import java.util.ArrayList;
055: import java.util.Collections;
056: import java.util.EmptyStackException;
057: import java.util.HashMap;
058: import java.util.Iterator;
059: import java.util.Properties;
060: import java.util.Stack;
061:
062: import org.xml.sax.Attributes;
063: import org.xml.sax.helpers.DefaultHandler;
064:
065: import com.lowagie.text.Anchor;
066: import com.lowagie.text.Annotation;
067: import com.lowagie.text.BadElementException;
068: import com.lowagie.text.Cell;
069: import com.lowagie.text.Chapter;
070: import com.lowagie.text.Chunk;
071: import com.lowagie.text.DocListener;
072: import com.lowagie.text.DocumentException;
073: import com.lowagie.text.Element;
074: import com.lowagie.text.ElementTags;
075: import com.lowagie.text.ExceptionConverter;
076: import com.lowagie.text.Font;
077: import com.lowagie.text.Image;
078: import com.lowagie.text.List;
079: import com.lowagie.text.ListItem;
080: import com.lowagie.text.Meta;
081: import com.lowagie.text.PageSize;
082: import com.lowagie.text.Paragraph;
083: import com.lowagie.text.Rectangle;
084: import com.lowagie.text.Section;
085: import com.lowagie.text.Table;
086: import com.lowagie.text.TextElementArray;
087: import com.lowagie.text.factories.ElementFactory;
088: import com.lowagie.text.html.HtmlTagMap;
089: import com.lowagie.text.pdf.BaseFont;
090: import com.lowagie.text.xml.simpleparser.EntitiesToSymbol;
091:
092: /**
093: * This class is a Handler that controls the iText XML to PDF conversion.
094: * Subclass it, if you want to change the way iText translates XML to PDF.
095: */
096:
097: public class SAXiTextHandler extends DefaultHandler {
098:
099: /** This is the resulting document. */
100: protected DocListener document;
101:
102: /**
103: * This is a <CODE>Stack</CODE> of objects, waiting to be added to the
104: * document.
105: */
106: protected Stack stack;
107:
108: /** Counts the number of chapters in this document. */
109: protected int chapters = 0;
110:
111: /** This is the current chunk to which characters can be added. */
112: protected Chunk currentChunk = null;
113:
114: /** This is the current chunk to which characters can be added. */
115: protected boolean ignore = false;
116:
117: /**
118: * This is a flag that can be set, if you want to open and close the
119: * Document-object yourself.
120: */
121: protected boolean controlOpenClose = true;
122:
123: /** current margin of a page. */
124: float topMargin = 36;
125:
126: /** current margin of a page. */
127: float rightMargin = 36;
128:
129: /** current margin of a page. */
130: float leftMargin = 36;
131:
132: /** current margin of a page. */
133: float bottomMargin = 36;
134:
135: /**
136: * @param document
137: */
138: public SAXiTextHandler(DocListener document) {
139: super ();
140: this .document = document;
141: stack = new Stack();
142: }
143:
144: protected HashMap myTags;
145:
146: /**
147: * @param document
148: * @param myTags
149: */
150: public SAXiTextHandler(DocListener document, HtmlTagMap myTags) {
151: this (document);
152: this .myTags = myTags;
153: }
154:
155: /**
156: * @param document
157: * @param myTags
158: * @param bf
159: */
160: public SAXiTextHandler(DocListener document, HtmlTagMap myTags,
161: BaseFont bf) {
162: this (document, myTags);
163: this .bf = bf;
164: }
165:
166: /**
167: * @param document
168: * @param myTags
169: */
170: public SAXiTextHandler(DocListener document, HashMap myTags) {
171: this (document);
172: this .myTags = myTags;
173: }
174:
175: /**
176: * Sets the parameter that allows you to enable/disable the control over the
177: * Document.open() and Document.close() method.
178: * <P>
179: * If you set this parameter to true (= default), the parser will open the
180: * Document object when the start-root-tag is encounterd and close it when
181: * the end-root-tag is met. If you set it to false, you have to open and
182: * close the Document object yourself.
183: *
184: * @param controlOpenClose
185: * set this to false if you plan to open/close the Document
186: * yourself
187: */
188:
189: public void setControlOpenClose(boolean controlOpenClose) {
190: this .controlOpenClose = controlOpenClose;
191: }
192:
193: /**
194: * This method gets called when a start tag is encountered.
195: *
196: * @param uri
197: * the Uniform Resource Identifier
198: * @param lname
199: * the local name (without prefix), or the empty string if
200: * Namespace processing is not being performed.
201: * @param name
202: * the name of the tag that is encountered
203: * @param attrs
204: * the list of attributes
205: */
206:
207: public void startElement(String uri, String lname, String name,
208: Attributes attrs) {
209:
210: Properties attributes = new Properties();
211: if (attrs != null) {
212: for (int i = 0; i < attrs.getLength(); i++) {
213: String attribute = attrs.getQName(i);
214: attributes.setProperty(attribute, attrs.getValue(i));
215: }
216: }
217: handleStartingTags(name, attributes);
218: }
219:
220: /**
221: * This method deals with the starting tags.
222: *
223: * @param name
224: * the name of the tag
225: * @param attributes
226: * the list of attributes
227: */
228:
229: public void handleStartingTags(String name, Properties attributes) {
230: // System.err.println("Start: " + name);
231: if (ignore || ElementTags.IGNORE.equals(name)) {
232: ignore = true;
233: return;
234: }
235:
236: // maybe there is some meaningful data that wasn't between tags
237: if (currentChunk != null) {
238: TextElementArray current;
239: try {
240: current = (TextElementArray) stack.pop();
241: } catch (EmptyStackException ese) {
242: if (bf == null) {
243: current = new Paragraph("", new Font());
244: } else {
245: current = new Paragraph("", new Font(this .bf));
246: }
247: }
248: current.add(currentChunk);
249: stack.push(current);
250: currentChunk = null;
251: }
252:
253: // chunks
254: if (ElementTags.CHUNK.equals(name)) {
255: currentChunk = ElementFactory.getChunk(attributes);
256: if (bf != null) {
257: currentChunk.setFont(new Font(this .bf));
258: }
259: return;
260: }
261:
262: // symbols
263: if (ElementTags.ENTITY.equals(name)) {
264: Font f = new Font();
265: if (currentChunk != null) {
266: handleEndingTags(ElementTags.CHUNK);
267: f = currentChunk.getFont();
268: }
269: currentChunk = EntitiesToSymbol.get(attributes
270: .getProperty(ElementTags.ID), f);
271: return;
272: }
273:
274: // phrases
275: if (ElementTags.PHRASE.equals(name)) {
276: stack.push(ElementFactory.getPhrase(attributes));
277: return;
278: }
279:
280: // anchors
281: if (ElementTags.ANCHOR.equals(name)) {
282: stack.push(ElementFactory.getAnchor(attributes));
283: return;
284: }
285:
286: // paragraphs and titles
287: if (ElementTags.PARAGRAPH.equals(name)
288: || ElementTags.TITLE.equals(name)) {
289: stack.push(ElementFactory.getParagraph(attributes));
290: return;
291: }
292:
293: // lists
294: if (ElementTags.LIST.equals(name)) {
295: stack.push(ElementFactory.getList(attributes));
296: return;
297: }
298:
299: // listitems
300: if (ElementTags.LISTITEM.equals(name)) {
301: stack.push(ElementFactory.getListItem(attributes));
302: return;
303: }
304:
305: // cells
306: if (ElementTags.CELL.equals(name)) {
307: stack.push(ElementFactory.getCell(attributes));
308: return;
309: }
310:
311: // tables
312: if (ElementTags.TABLE.equals(name)) {
313: Table table = ElementFactory.getTable(attributes);
314: float widths[] = table.getProportionalWidths();
315: for (int i = 0; i < widths.length; i++) {
316: if (widths[i] == 0) {
317: widths[i] = 100.0f / (float) widths.length;
318: }
319: }
320: try {
321: table.setWidths(widths);
322: } catch (BadElementException bee) {
323: // this shouldn't happen
324: throw new ExceptionConverter(bee);
325: }
326: stack.push(table);
327: return;
328: }
329:
330: // sections
331: if (ElementTags.SECTION.equals(name)) {
332: Element previous = (Element) stack.pop();
333: Section section;
334: try {
335: section = ElementFactory.getSection((Section) previous,
336: attributes);
337: } catch (ClassCastException cce) {
338: throw new ExceptionConverter(cce);
339: }
340: stack.push(previous);
341: stack.push(section);
342: return;
343: }
344:
345: // chapters
346: if (ElementTags.CHAPTER.equals(name)) {
347: stack.push(ElementFactory.getChapter(attributes));
348: return;
349: }
350:
351: // images
352: if (ElementTags.IMAGE.equals(name)) {
353: try {
354: Image img = ElementFactory.getImage(attributes);
355: try {
356: addImage(img);
357: return;
358: } catch (EmptyStackException ese) {
359: // if there is no element on the stack, the Image is added
360: // to the document
361: try {
362: document.add(img);
363: } catch (DocumentException de) {
364: throw new ExceptionConverter(de);
365: }
366: return;
367: }
368: } catch (Exception e) {
369: throw new ExceptionConverter(e);
370: }
371: }
372:
373: // annotations
374: if (ElementTags.ANNOTATION.equals(name)) {
375: Annotation annotation = ElementFactory
376: .getAnnotation(attributes);
377: TextElementArray current;
378: try {
379: try {
380: current = (TextElementArray) stack.pop();
381: try {
382: current.add(annotation);
383: } catch (Exception e) {
384: document.add(annotation);
385: }
386: stack.push(current);
387: } catch (EmptyStackException ese) {
388: document.add(annotation);
389: }
390: return;
391: } catch (DocumentException de) {
392: throw new ExceptionConverter(de);
393: }
394: }
395:
396: // newlines
397: if (isNewline(name)) {
398: TextElementArray current;
399: try {
400: current = (TextElementArray) stack.pop();
401: current.add(Chunk.NEWLINE);
402: stack.push(current);
403: } catch (EmptyStackException ese) {
404: if (currentChunk == null) {
405: try {
406: document.add(Chunk.NEWLINE);
407: } catch (DocumentException de) {
408: throw new ExceptionConverter(de);
409: }
410: } else {
411: currentChunk.append("\n");
412: }
413: }
414: return;
415: }
416:
417: // newpage
418: if (isNewpage(name)) {
419: TextElementArray current;
420: try {
421: current = (TextElementArray) stack.pop();
422: Chunk newPage = new Chunk("");
423: newPage.setNewPage();
424: if (bf != null) {
425: newPage.setFont(new Font(this .bf));
426: }
427: current.add(newPage);
428: stack.push(current);
429: } catch (EmptyStackException ese) {
430: document.newPage();
431: }
432: return;
433: }
434:
435: // documentroot
436: if (isDocumentRoot(name)) {
437: String key;
438: String value;
439: // pagesize and orientation specific code suggested by Samuel Gabriel
440: // Updated by Ricardo Coutinho. Only use if set in html!
441: Rectangle pageSize = null;
442: String orientation = null;
443: for (Iterator i = attributes.keySet().iterator(); i
444: .hasNext();) {
445: key = (String) i.next();
446: value = attributes.getProperty(key);
447: try {
448: // margin specific code suggested by Reza Nasiri
449: if (ElementTags.LEFT.equalsIgnoreCase(key))
450: leftMargin = Float.parseFloat(value + "f");
451: if (ElementTags.RIGHT.equalsIgnoreCase(key))
452: rightMargin = Float.parseFloat(value + "f");
453: if (ElementTags.TOP.equalsIgnoreCase(key))
454: topMargin = Float.parseFloat(value + "f");
455: if (ElementTags.BOTTOM.equalsIgnoreCase(key))
456: bottomMargin = Float.parseFloat(value + "f");
457: } catch (Exception ex) {
458: throw new ExceptionConverter(ex);
459: }
460: if (ElementTags.PAGE_SIZE.equals(key)) {
461: try {
462: String pageSizeName = value;
463: Field pageSizeField = PageSize.class
464: .getField(pageSizeName);
465: pageSize = (Rectangle) pageSizeField.get(null);
466: } catch (Exception ex) {
467: throw new ExceptionConverter(ex);
468: }
469: } else if (ElementTags.ORIENTATION.equals(key)) {
470: try {
471: if ("landscape".equals(value)) {
472: orientation = "landscape";
473: }
474: } catch (Exception ex) {
475: throw new ExceptionConverter(ex);
476: }
477: } else {
478: try {
479: document.add(new Meta(key, value));
480: } catch (DocumentException de) {
481: throw new ExceptionConverter(de);
482: }
483: }
484: }
485: if (pageSize != null) {
486: if ("landscape".equals(orientation)) {
487: pageSize = pageSize.rotate();
488: }
489: document.setPageSize(pageSize);
490: }
491: document.setMargins(leftMargin, rightMargin, topMargin,
492: bottomMargin);
493:
494: if (controlOpenClose)
495: document.open();
496: }
497:
498: }
499:
500: protected void addImage(Image img) throws EmptyStackException {
501: // if there is an element on the stack...
502: Object current = stack.pop();
503: // ...and it's a Chapter or a Section, the Image can be
504: // added directly
505: if (current instanceof Chapter || current instanceof Section
506: || current instanceof Cell) {
507: ((TextElementArray) current).add(img);
508: stack.push(current);
509: return;
510: }
511: // ...if not, we need to to a lot of stuff
512: else {
513: Stack newStack = new Stack();
514: while (!(current instanceof Chapter
515: || current instanceof Section || current instanceof Cell)) {
516: newStack.push(current);
517: if (current instanceof Anchor) {
518: img.setAnnotation(new Annotation(0, 0, 0, 0,
519: ((Anchor) current).getReference()));
520: }
521: current = stack.pop();
522: }
523: ((TextElementArray) current).add(img);
524: stack.push(current);
525: while (!newStack.empty()) {
526: stack.push(newStack.pop());
527: }
528: return;
529: }
530: }
531:
532: /**
533: * This method gets called when ignorable white space encountered.
534: *
535: * @param ch
536: * an array of characters
537: * @param start
538: * the start position in the array
539: * @param length
540: * the number of characters to read from the array
541: */
542:
543: public void ignorableWhitespace(char[] ch, int start, int length) {
544: characters(ch, start, length);
545: }
546:
547: /**
548: * This method gets called when characters are encountered.
549: *
550: * @param ch
551: * an array of characters
552: * @param start
553: * the start position in the array
554: * @param length
555: * the number of characters to read from the array
556: */
557:
558: public void characters(char[] ch, int start, int length) {
559:
560: if (ignore)
561: return;
562:
563: String content = new String(ch, start, length);
564: // System.err.println("'" + content + "'");
565:
566: if (content.trim().length() == 0 && content.indexOf(' ') < 0) {
567: return;
568: }
569:
570: StringBuffer buf = new StringBuffer();
571: int len = content.length();
572: char character;
573: boolean newline = false;
574: for (int i = 0; i < len; i++) {
575: switch (character = content.charAt(i)) {
576: case ' ':
577: if (!newline) {
578: buf.append(character);
579: }
580: break;
581: case '\n':
582: if (i > 0) {
583: newline = true;
584: buf.append(' ');
585: }
586: break;
587: case '\r':
588: break;
589: case '\t':
590: break;
591: default:
592: newline = false;
593: buf.append(character);
594: }
595: }
596: if (currentChunk == null) {
597: if (bf == null) {
598: currentChunk = new Chunk(buf.toString());
599: } else {
600: currentChunk = new Chunk(buf.toString(), new Font(
601: this .bf));
602: }
603: } else {
604: currentChunk.append(buf.toString());
605: }
606: }
607:
608: private BaseFont bf = null;
609:
610: /**
611: * Sets the font that has to be used.
612: * @param bf
613: */
614: public void setBaseFont(BaseFont bf) {
615: this .bf = bf;
616: }
617:
618: /**
619: * This method gets called when an end tag is encountered.
620: *
621: * @param uri
622: * the Uniform Resource Identifier
623: * @param lname
624: * the local name (without prefix), or the empty string if
625: * Namespace processing is not being performed.
626: * @param name
627: * the name of the tag that ends
628: */
629:
630: public void endElement(String uri, String lname, String name) {
631: handleEndingTags(name);
632: }
633:
634: /**
635: * This method deals with the starting tags.
636: *
637: * @param name
638: * the name of the tag
639: */
640:
641: public void handleEndingTags(String name) {
642:
643: // System.err.println("Stop: " + name);
644:
645: if (ElementTags.IGNORE.equals(name)) {
646: ignore = false;
647: return;
648: }
649: if (ignore)
650: return;
651: // tags that don't have any content
652: if (isNewpage(name) || ElementTags.ANNOTATION.equals(name)
653: || ElementTags.IMAGE.equals(name) || isNewline(name)) {
654: return;
655: }
656:
657: try {
658: // titles of sections and chapters
659: if (ElementTags.TITLE.equals(name)) {
660: Paragraph current = (Paragraph) stack.pop();
661: if (currentChunk != null) {
662: current.add(currentChunk);
663: currentChunk = null;
664: }
665: Section previous = (Section) stack.pop();
666: previous.setTitle(current);
667: stack.push(previous);
668: return;
669: }
670:
671: // all other endtags
672: if (currentChunk != null) {
673: TextElementArray current;
674: try {
675: current = (TextElementArray) stack.pop();
676: } catch (EmptyStackException ese) {
677: current = new Paragraph();
678: }
679: current.add(currentChunk);
680: stack.push(current);
681: currentChunk = null;
682: }
683:
684: // chunks
685: if (ElementTags.CHUNK.equals(name)) {
686: return;
687: }
688:
689: // phrases, anchors, lists, tables
690: if (ElementTags.PHRASE.equals(name)
691: || ElementTags.ANCHOR.equals(name)
692: || ElementTags.LIST.equals(name)
693: || ElementTags.PARAGRAPH.equals(name)) {
694: Element current = (Element) stack.pop();
695: try {
696: TextElementArray previous = (TextElementArray) stack
697: .pop();
698: previous.add(current);
699: stack.push(previous);
700: } catch (EmptyStackException ese) {
701: document.add(current);
702: }
703: return;
704: }
705:
706: // listitems
707: if (ElementTags.LISTITEM.equals(name)) {
708: ListItem listItem = (ListItem) stack.pop();
709: List list = (List) stack.pop();
710: list.add(listItem);
711: stack.push(list);
712: }
713:
714: // tables
715: if (ElementTags.TABLE.equals(name)) {
716: Table table = (Table) stack.pop();
717: try {
718: TextElementArray previous = (TextElementArray) stack
719: .pop();
720: previous.add(table);
721: stack.push(previous);
722: } catch (EmptyStackException ese) {
723: document.add(table);
724: }
725: return;
726: }
727:
728: // rows
729: if (ElementTags.ROW.equals(name)) {
730: ArrayList cells = new ArrayList();
731: int columns = 0;
732: Table table;
733: Cell cell;
734: while (true) {
735: Element element = (Element) stack.pop();
736: if (element.type() == Element.CELL) {
737: cell = (Cell) element;
738: columns += cell.getColspan();
739: cells.add(cell);
740: } else {
741: table = (Table) element;
742: break;
743: }
744: }
745: if (table.getColumns() < columns) {
746: table.addColumns(columns - table.getColumns());
747: }
748: Collections.reverse(cells);
749: String width;
750: float[] cellWidths = new float[columns];
751: boolean[] cellNulls = new boolean[columns];
752: for (int i = 0; i < columns; i++) {
753: cellWidths[i] = 0;
754: cellNulls[i] = true;
755: }
756: float total = 0;
757: int j = 0;
758: for (Iterator i = cells.iterator(); i.hasNext();) {
759: cell = (Cell) i.next();
760: width = cell.getWidthAsString();
761: if (cell.getWidth() == 0) {
762: if (cell.getColspan() == 1
763: && cellWidths[j] == 0) {
764: try {
765: cellWidths[j] = 100f / columns;
766: total += cellWidths[j];
767: } catch (Exception e) {
768: // empty on purpose
769: }
770: } else if (cell.getColspan() == 1) {
771: cellNulls[j] = false;
772: }
773: } else if (cell.getColspan() == 1
774: && width.endsWith("%")) {
775: try {
776: cellWidths[j] = Float.parseFloat(width
777: .substring(0, width.length() - 1)
778: + "f");
779: total += cellWidths[j];
780: } catch (Exception e) {
781: // empty on purpose
782: }
783: }
784: j += cell.getColspan();
785: table.addCell(cell);
786: }
787: float widths[] = table.getProportionalWidths();
788: if (widths.length == columns) {
789: float left = 0.0f;
790: for (int i = 0; i < columns; i++) {
791: if (cellNulls[i] && widths[i] != 0) {
792: left += widths[i];
793: cellWidths[i] = widths[i];
794: }
795: }
796: if (100.0 >= total) {
797: for (int i = 0; i < widths.length; i++) {
798: if (cellWidths[i] == 0 && widths[i] != 0) {
799: cellWidths[i] = (widths[i] / left)
800: * (100.0f - total);
801: }
802: }
803: }
804: table.setWidths(cellWidths);
805: }
806: stack.push(table);
807: }
808:
809: // cells
810: if (ElementTags.CELL.equals(name)) {
811: return;
812: }
813:
814: // sections
815: if (ElementTags.SECTION.equals(name)) {
816: stack.pop();
817: return;
818: }
819:
820: // chapters
821: if (ElementTags.CHAPTER.equals(name)) {
822: document.add((Element) stack.pop());
823: return;
824: }
825:
826: // the documentroot
827: if (isDocumentRoot(name)) {
828: try {
829: while (true) {
830: Element element = (Element) stack.pop();
831: try {
832: TextElementArray previous = (TextElementArray) stack
833: .pop();
834: previous.add(element);
835: stack.push(previous);
836: } catch (EmptyStackException es) {
837: document.add(element);
838: }
839: }
840: } catch (EmptyStackException ese) {
841: // empty on purpose
842: }
843: if (controlOpenClose)
844: document.close();
845: return;
846: }
847: } catch (DocumentException de) {
848: throw new ExceptionConverter(de);
849: }
850: }
851:
852: /**
853: * Checks if a certain tag corresponds with the newpage-tag.
854: *
855: * @param tag
856: * a presumed tagname
857: * @return <CODE>true</CODE> or <CODE>false</CODE>
858: */
859:
860: private boolean isNewpage(String tag) {
861: return ElementTags.NEWPAGE.equals(tag);
862: }
863:
864: /**
865: * Checks if a certain tag corresponds with the newpage-tag.
866: *
867: * @param tag
868: * a presumed tagname
869: * @return <CODE>true</CODE> or <CODE>false</CODE>
870: */
871:
872: private boolean isNewline(String tag) {
873: return ElementTags.NEWLINE.equals(tag);
874: }
875:
876: /**
877: * Checks if a certain tag corresponds with the roottag.
878: *
879: * @param tag
880: * a presumed tagname
881: * @return <CODE>true</CODE> if <VAR>tag </VAR> equals <CODE>itext
882: * </CODE>,<CODE>false</CODE> otherwise.
883: */
884:
885: protected boolean isDocumentRoot(String tag) {
886: return ElementTags.ITEXT.equals(tag);
887: }
888: }
|