KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > htmlparser > tests > scannersTests > CompositeTagScannerTest


1 // HTMLParser Library $Name: v1_5_20050313 $ - A java-based parser for HTML
2
// http://sourceforge.org/projects/htmlparser
3
// Copyright (C) 2004 Somik Raha
4
//
5
// Revision Control Information
6
//
7
// $Source: /cvsroot/htmlparser/htmlparser/src/org/htmlparser/tests/scannersTests/CompositeTagScannerTest.java,v $
8
// $Author: derrickoswald $
9
// $Date: 2004/07/31 16:42:32 $
10
// $Revision: 1.62 $
11
//
12
// This library is free software; you can redistribute it and/or
13
// modify it under the terms of the GNU Lesser General Public
14
// License as published by the Free Software Foundation; either
15
// version 2.1 of the License, or (at your option) any later version.
16
//
17
// This library is distributed in the hope that it will be useful,
18
// but WITHOUT ANY WARRANTY; without even the implied warranty of
19
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
// Lesser General Public License for more details.
21
//
22
// You should have received a copy of the GNU Lesser General Public
23
// License along with this library; if not, write to the Free Software
24
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
//
26

27 package org.htmlparser.tests.scannersTests;
28
29 import org.htmlparser.Node;
30 import org.htmlparser.PrototypicalNodeFactory;
31 import org.htmlparser.Tag;
32 import org.htmlparser.Text;
33 import org.htmlparser.nodes.AbstractNode;
34 import org.htmlparser.scanners.CompositeTagScanner;
35 import org.htmlparser.tags.CompositeTag;
36 import org.htmlparser.tags.Div;
37 import org.htmlparser.tags.LinkTag;
38 import org.htmlparser.tags.TableColumn;
39 import org.htmlparser.tags.TableRow;
40 import org.htmlparser.tags.TableTag;
41 import org.htmlparser.tests.ParserTestCase;
42 import org.htmlparser.util.ParserException;
43
44 public class CompositeTagScannerTest extends ParserTestCase {
45     static
46     {
47         System.setProperty ("org.htmlparser.tests.scannersTests.CompositeTagScannerTest", "CompositeTagScannerTest");
48     }
49
50     public CompositeTagScannerTest(String JavaDoc name) {
51         super(name);
52     }
53
54     private CustomTag parseCustomTag(int expectedNodeCount) throws ParserException {
55         parser.setNodeFactory (new PrototypicalNodeFactory (new CustomTag ()));
56         parseAndAssertNodeCount(expectedNodeCount);
57         assertType("node",CustomTag.class,node[0]);
58         CustomTag customTag = (CustomTag)node[0];
59         return customTag;
60     }
61
62     public void testEmptyCompositeTag() throws ParserException {
63         String JavaDoc html = "<Custom/>";
64         createParser(html);
65         CustomTag customTag = parseCustomTag(1);
66         assertEquals("child count",0,customTag.getChildCount());
67         assertTrue("custom tag should be xml end tag",customTag.isEmptyXmlTag());
68         assertEquals("starting loc",0,customTag.getStartPosition ());
69         assertEquals("ending loc",9,customTag.getEndPosition ());
70         assertEquals("starting line position",0,customTag.getStartingLineNumber());
71         assertEquals("ending line position",0,customTag.getEndingLineNumber());
72         assertStringEquals("html",html,customTag.toHtml());
73     }
74
75     public void testEmptyCompositeTagAnotherStyle() throws ParserException {
76         String JavaDoc html = "<Custom></Custom>";
77         createParser(html);
78         CustomTag customTag = parseCustomTag(1);
79         assertEquals("child count",0,customTag.getChildCount());
80         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
81         assertEquals("starting loc",0,customTag.getStartPosition ());
82         assertEquals("ending loc",8,customTag.getEndPosition ());
83         assertEquals("starting line position",0,customTag.getStartingLineNumber());
84         assertEquals("ending line position",0,customTag.getEndingLineNumber());
85         assertEquals("html",html,customTag.toHtml());
86     }
87
88     public void testCompositeTagWithOneTextChild() throws ParserException {
89         String JavaDoc html =
90             "<Custom>" +
91                 "Hello" +
92             "</Custom>";
93         createParser(html);
94         CustomTag customTag = parseCustomTag(1);
95         assertEquals("child count",1,customTag.getChildCount());
96         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
97         assertEquals("starting loc",0,customTag.getStartPosition ());
98         assertEquals("ending loc",8,customTag.getEndPosition ());
99         assertEquals("starting line position",0,customTag.getStartingLineNumber());
100         assertEquals("ending line position",0,customTag.getEndingLineNumber());
101         Node child = customTag.childAt(0);
102         assertType("child",Text.class,child);
103         assertStringEquals("child text","Hello",child.toPlainTextString());
104     }
105
106     public void testCompositeTagWithTagChild() throws ParserException {
107         String JavaDoc childtag = "<Hello>";
108         createParser(
109             "<Custom>" +
110                 childtag +
111             "</Custom>"
112         );
113         CustomTag customTag = parseCustomTag(1);
114         assertEquals("child count",1,customTag.getChildCount());
115         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
116         assertEquals("starting loc",0,customTag.getStartPosition ());
117         assertEquals("ending loc",8,customTag.getEndPosition ());
118         assertEquals("custom tag starting loc",0,customTag.getStartPosition ());
119         assertEquals("custom tag ending loc",24,customTag.getEndTag ().getEndPosition ());
120
121         Node child = customTag.childAt(0);
122         assertType("child",Tag.class,child);
123         assertStringEquals("child html",childtag,child.toHtml());
124     }
125
126     public void testCompositeTagWithAnotherTagChild() throws ParserException {
127         String JavaDoc childtag = "<Another/>";
128         createParser(
129             "<Custom>" +
130                  childtag +
131             "</Custom>"
132         );
133         parser.setNodeFactory (
134             new PrototypicalNodeFactory (
135                 new Tag[]
136                 {
137                     new CustomTag (),
138                     new AnotherTag (true),
139                 }));
140         parseAndAssertNodeCount(1);
141         assertType("node",CustomTag.class,node[0]);
142         CustomTag customTag = (CustomTag)node[0];
143         assertEquals("child count",1,customTag.getChildCount());
144         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
145         assertEquals("starting loc",0,customTag.getStartPosition ());
146         assertEquals("ending loc",8,customTag.getEndPosition ());
147         assertEquals("custom tag starting loc",0,customTag.getStartPosition ());
148         assertEquals("custom tag ending loc",27,customTag.getEndTag ().getEndPosition ());
149
150         Node child = customTag.childAt(0);
151         assertType("child",AnotherTag.class,child);
152         AnotherTag tag = (AnotherTag)child;
153         assertEquals("another tag start pos",8,tag.getStartPosition ());
154         assertEquals("another tag ending pos",18,tag.getEndPosition ());
155
156         assertEquals("custom end tag start pos",18,customTag.getEndTag().getStartPosition ());
157         assertStringEquals("child html",childtag,child.toHtml());
158     }
159
160     public void testParseTwoCompositeTags() throws ParserException {
161         createParser(
162             "<Custom>" +
163             "</Custom>" +
164             "<Custom/>"
165         );
166         parser.setNodeFactory (new PrototypicalNodeFactory (new CustomTag ()));
167         parseAndAssertNodeCount(2);
168         assertType("tag 1",CustomTag.class,node[0]);
169         assertType("tag 2",CustomTag.class,node[1]);
170     }
171
172     public void testXmlTypeCompositeTags() throws ParserException {
173         createParser(
174             "<Custom>" +
175                 "<Another name=\"subtag\"/>" +
176                 "<Custom />" +
177             "</Custom>" +
178             "<Custom/>"
179         );
180         parser.setNodeFactory (
181             new PrototypicalNodeFactory (
182                 new Tag[] {
183                     new CustomTag (),
184                     new AnotherTag (false),
185                 }));
186         parseAndAssertNodeCount(2);
187         assertType("first node",CustomTag.class,node[0]);
188         assertType("second node",CustomTag.class,node[1]);
189         CustomTag customTag = (CustomTag)node[0];
190         Node node = customTag.childAt(0);
191         assertType("first child",AnotherTag.class,node);
192         node = customTag.childAt(1);
193         assertType("second child",CustomTag.class,node);
194     }
195
196     public void testCompositeTagWithNestedTag() throws ParserException {
197         createParser(
198             "<Custom>" +
199                 "<Another>" +
200                     "Hello" +
201                 "</Another>" +
202                 "<Custom/>" +
203             "</Custom>" +
204             "<Custom/>"
205         );
206         parser.setNodeFactory (
207             new PrototypicalNodeFactory (
208                 new Tag[] {
209                     new CustomTag (),
210                     new AnotherTag (false),
211                 }));
212         parseAndAssertNodeCount(2);
213         assertType("first node",CustomTag.class,node[0]);
214         assertType("second node",CustomTag.class,node[1]);
215         CustomTag customTag = (CustomTag)node[0];
216         Node node = customTag.childAt(0);
217         assertType("first child",AnotherTag.class,node);
218         AnotherTag anotherTag = (AnotherTag)node;
219         assertEquals("another tag children count",1,anotherTag.getChildCount());
220         node = anotherTag.childAt(0);
221         assertType("nested child",Text.class,node);
222         Text text = (Text)node;
223         assertEquals("text","Hello",text.toPlainTextString());
224     }
225
226     public void testCompositeTagWithTwoNestedTags() throws ParserException {
227         createParser(
228             "<Custom>" +
229                 "<Another>" +
230                     "Hello" +
231                 "</Another>" +
232                 "<unknown>" +
233                     "World" +
234                 "</unknown>" +
235                 "<Custom/>" +
236             "</Custom>" +
237             "<Custom/>"
238         );
239         parser.setNodeFactory (
240             new PrototypicalNodeFactory (
241                 new Tag[] {
242                     new CustomTag (),
243                     new AnotherTag (false),
244                 }));
245         parseAndAssertNodeCount(2);
246         assertType("first node",CustomTag.class,node[0]);
247         assertType("second node",CustomTag.class,node[1]);
248         CustomTag customTag = (CustomTag)node[0];
249         assertEquals("first custom tag children count",5,customTag.getChildCount());
250         Node node = customTag.childAt(0);
251         assertType("first child",AnotherTag.class,node);
252         AnotherTag anotherTag = (AnotherTag)node;
253         assertEquals("another tag children count",1,anotherTag.getChildCount());
254         node = anotherTag.childAt(0);
255         assertType("nested child",Text.class,node);
256         Text text = (Text)node;
257         assertEquals("text","Hello",text.toPlainTextString());
258     }
259
260     public void testErroneousCompositeTag() throws ParserException {
261         String JavaDoc html = "<custom>";
262         createParser(html);
263         CustomTag customTag = parseCustomTag(1);
264         assertEquals("child count",0,customTag.getChildCount());
265         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
266         assertEquals("starting loc",0,customTag.getStartPosition ());
267         assertEquals("ending loc",8,customTag.getEndPosition ());
268         assertEquals("starting line position",0,customTag.getStartingLineNumber());
269         assertEquals("ending line position",0,customTag.getEndingLineNumber());
270         assertStringEquals("html",html + "</custom>",customTag.toHtml());
271     }
272
273     public void testErroneousCompositeTagWithChildren() throws ParserException {
274         String JavaDoc html = "<custom>" + "<firstChild>" + "<secondChild>";
275         createParser(html);
276         CustomTag customTag = parseCustomTag(1);
277         assertEquals("child count",2,customTag.getChildCount());
278         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
279         assertEquals("starting loc",0,customTag.getStartPosition ());
280         assertEquals("ending loc",8,customTag.getEndPosition ());
281         assertEquals("starting line position",0,customTag.getStartingLineNumber());
282         assertEquals("ending line position",0,customTag.getEndingLineNumber());
283         assertStringEquals("html",html + "</custom>",customTag.toHtml());
284     }
285
286     public void testErroneousCompositeTagWithChildrenAndLineBreak() throws ParserException {
287         String JavaDoc html = "<custom>" + "<firstChild>" + "\n" + "<secondChild>";
288         createParser(html);
289         CustomTag customTag = parseCustomTag(1);
290         assertEquals("child count",3,customTag.getChildCount());
291         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
292         assertEquals("starting loc",0,customTag.getStartPosition ());
293         assertEquals("ending loc",8,customTag.getEndPosition ());
294         assertEquals("starting line position",0,customTag.getStartingLineNumber());
295         assertEquals("ending line position",1,customTag.getEndTag ().getEndingLineNumber());
296         assertStringEquals("html", html + "</custom>", customTag.toHtml()
297         );
298     }
299
300     public void testTwoConsecutiveErroneousCompositeTags() throws ParserException {
301         String JavaDoc tag1 = "<custom>something";
302         String JavaDoc tag2 = "<custom></endtag>";
303         createParser(tag1 + tag2);
304         parser.setNodeFactory (new PrototypicalNodeFactory (new CustomTag (false)));
305         parseAndAssertNodeCount(2);
306         CustomTag customTag = (CustomTag)node[0];
307         assertEquals("child count",1,customTag.getChildCount());
308         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
309         assertEquals("starting loc",0,customTag.getStartPosition ());
310         assertEquals("ending loc",8,customTag.getEndPosition ());
311         assertEquals("ending loc of custom tag",17,customTag.getEndTag ().getEndPosition ());
312         assertEquals("starting line position",0,customTag.getStartingLineNumber());
313         assertEquals("ending line position",0,customTag.getEndTag ().getEndingLineNumber());
314         assertStringEquals("1st custom tag", tag1 + "</custom>", customTag.toHtml());
315         customTag = (CustomTag)node[1];
316         assertStringEquals("2nd custom tag", tag2 + "</custom>", customTag.toHtml());
317     }
318
319     public void testCompositeTagWithErroneousAnotherTagAndLineBreak() throws ParserException {
320         String JavaDoc another = "<another>";
321         String JavaDoc custom = "<custom>\n</custom>";
322         createParser(
323             another +
324             custom
325         );
326         parser.setNodeFactory (
327             new PrototypicalNodeFactory (
328                 new Tag[] {
329                     new CustomTag (),
330                     new AnotherTag (false),
331                 }));
332         parseAndAssertNodeCount(2);
333         AnotherTag anotherTag = (AnotherTag)node[0];
334         assertEquals("another tag child count",0,anotherTag.getChildCount());
335
336         CustomTag customTag = (CustomTag)node[1];
337         assertEquals("child count",1,customTag.getChildCount());
338         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
339         assertEquals("starting loc",9,customTag.getStartPosition ());
340         assertEquals("ending loc",17,customTag.getEndPosition ());
341         assertEquals("starting line position",0,customTag.getStartingLineNumber());
342         assertEquals("ending line position",1,customTag.getEndTag ().getEndingLineNumber());
343         assertStringEquals("another tag html",another + "</another>",anotherTag.toHtml());
344         assertStringEquals("custom tag html",custom,customTag.toHtml());
345     }
346
347     public void testCompositeTagWithErroneousAnotherTag() throws ParserException {
348         createParser(
349             "<custom>" +
350                 "<another>" +
351             "</custom>"
352         );
353         parser.setNodeFactory (
354             new PrototypicalNodeFactory (
355                 new Tag[]
356                 {
357                     new CustomTag (),
358                     new AnotherTag (true),
359                 }));
360         parseAndAssertNodeCount(1);
361         assertType("node",CustomTag.class,node[0]);
362         CustomTag customTag = (CustomTag)node[0];
363         assertEquals("child count",1,customTag.getChildCount());
364         assertFalse("custom tag should be xml end tag",customTag.isEmptyXmlTag());
365         assertEquals("starting loc",0,customTag.getStartPosition ());
366         assertEquals("ending loc",8,customTag.getEndPosition ());
367         AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
368         assertEquals("another tag ending loc",17,anotherTag.getEndPosition ());
369         assertEquals("starting line position",0,customTag.getStartingLineNumber());
370         assertEquals("ending line position",0,customTag.getEndingLineNumber());
371         assertStringEquals("html","<custom><another></another></custom>",customTag.toHtml());
372     }
373
374     public void testCompositeTagWithDeadlock() throws ParserException {
375         createParser(
376             "<custom>" +
377                 "<another>something" +
378             "</custom>"+
379             "<custom>" +
380                 "<another>else</another>" +
381             "</custom>"
382         );
383         parser.setNodeFactory (
384             new PrototypicalNodeFactory (
385                 new Tag[]
386                 {
387                     new CustomTag (),
388                     new AnotherTag (true),
389                 }));
390         parseAndAssertNodeCount(2);
391         assertType("node",CustomTag.class,node[0]);
392         CustomTag customTag = (CustomTag)node[0];
393
394         assertEquals("child count",1,customTag.getChildCount());
395         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
396         assertEquals("starting loc",0,customTag.getStartPosition ());
397         assertEquals("ending loc",8,customTag.getEndPosition ());
398         assertEquals("starting line position",0,customTag.getStartingLineNumber());
399         assertEquals("ending line position",0,customTag.getEndingLineNumber());
400         AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
401         assertEquals("anotherTag child count",1,anotherTag.getChildCount());
402         Text stringNode = (Text)anotherTag.childAt(0);
403         assertStringEquals("anotherTag child text","something",stringNode.toPlainTextString());
404         assertStringEquals(
405             "first custom tag html",
406             "<custom><another>something</another></custom>",
407             customTag.toHtml()
408         );
409         customTag = (CustomTag)node[1];
410         assertStringEquals(
411             "second custom tag html",
412             "<custom><another>else</another></custom>",
413             customTag.toHtml()
414         );
415     }
416
417     public void testCompositeTagCorrectionWithSplitLines() throws ParserException {
418         createParser(
419             "<custom>" +
420                 "<another><abcdefg>\n" +
421             "</custom>"
422         );
423         parser.setNodeFactory (
424             new PrototypicalNodeFactory (
425                 new Tag[]
426                 {
427                     new CustomTag (),
428                     new AnotherTag (true),
429                 }));
430         parseAndAssertNodeCount(1);
431         assertType("node",CustomTag.class,node[0]);
432         CustomTag customTag = (CustomTag)node[0];
433         assertEquals("child count",1,customTag.getChildCount());
434         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
435         assertEquals("starting loc",0,customTag.getStartPosition ());
436         assertEquals("ending loc",8,customTag.getEndPosition ());
437         AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
438         assertEquals("anotherTag child count",2,anotherTag.getChildCount());
439         assertEquals("anotherTag end loc",27,anotherTag.getEndTag ().getEndPosition ());
440         assertEquals("custom end tag begin loc",27,customTag.getEndTag().getStartPosition ());
441         assertEquals("custom end tag end loc",36,customTag.getEndTag().getEndPosition ());
442     }
443
444     public void testCompositeTagWithSelfChildren() throws ParserException
445     {
446         String JavaDoc tag1 = "<custom>";
447         String JavaDoc tag2 = "<custom>something</custom>";
448         String JavaDoc tag3 = "</custom>";
449         createParser(tag1 + tag2 + tag3);
450         parser.setNodeFactory (
451             new PrototypicalNodeFactory (
452                 new Tag[] {
453                     new CustomTag (false),
454                     new AnotherTag (false),
455                 }));
456         parseAndAssertNodeCount(3);
457
458         CustomTag customTag = (CustomTag)node[0];
459         assertEquals("child count",0,customTag.getChildCount());
460         assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
461
462         assertStringEquals(
463             "first custom tag html",
464             tag1 + "</custom>",
465             customTag.toHtml()
466         );
467         customTag = (CustomTag)node[1];
468         assertStringEquals(
469             "second custom tag html",
470             tag2,
471             customTag.toHtml()
472         );
473         Tag endTag = (Tag)node[2];
474         assertStringEquals(
475             "third custom tag html",
476             tag3,
477             endTag.toHtml()
478         );
479     }
480
481     public void testParentConnections() throws ParserException {
482         String JavaDoc tag1 = "<custom>";
483         String JavaDoc tag2 = "<custom>something</custom>";
484         String JavaDoc tag3 = "</custom>";
485         createParser(tag1 + tag2 + tag3);
486         parser.setNodeFactory (
487             new PrototypicalNodeFactory (
488                 new Tag[] {
489                     new CustomTag (false),
490                     new AnotherTag (false),
491                 }));
492         parseAndAssertNodeCount(3);
493
494         CustomTag customTag = (CustomTag)node[0];
495
496         assertStringEquals(
497             "first custom tag html",
498             tag1 + "</custom>",
499             customTag.toHtml()
500         );
501         assertNull(
502             "first custom tag should have no parent",
503             customTag.getParent()
504         );
505
506         customTag = (CustomTag)node[1];
507         assertStringEquals(
508             "second custom tag html",
509             tag2,
510             customTag.toHtml()
511         );
512         assertNull(
513             "second custom tag should have no parent",
514             customTag.getParent()
515         );
516
517         Node firstChild = customTag.childAt(0);
518         assertType("firstChild",Text.class,firstChild);
519         Node parent = firstChild.getParent();
520         assertNotNull("first child parent should not be null",parent);
521         assertSame("parent and custom tag should be the same",customTag,parent);
522
523         Tag endTag = (Tag)node[2];
524         assertStringEquals(
525             "third custom tag html",
526             tag3,
527             endTag.toHtml()
528         );
529         assertNull(
530             "end tag should have no parent",
531             endTag.getParent()
532         );
533
534     }
535
536     public void testUrlBeingProvidedToCreateTag() throws ParserException {
537         createParser("<Custom/>","http://www.yahoo.com");
538
539         parser.setNodeFactory (new PrototypicalNodeFactory (new CustomTag ()));
540         parseAndAssertNodeCount(1);
541         assertStringEquals("url","http://www.yahoo.com",((AbstractNode)node[0]).getPage ().getUrl ());
542     }
543
544     public void testComplexNesting() throws ParserException {
545         createParser(
546             "<custom>" +
547                 "<custom>" +
548                     "<another>" +
549                 "</custom>" +
550                 "<custom>" +
551                     "<another>" +
552                 "</custom>" +
553             "</custom>"
554         );
555         parser.setNodeFactory (
556             new PrototypicalNodeFactory (
557                 new Tag[] {
558                     new CustomTag (),
559                     new AnotherTag (false),
560                 }));
561         parseAndAssertNodeCount(1);
562         assertType("root node",CustomTag.class, node[0]);
563         CustomTag root = (CustomTag)node[0];
564         assertNodeCount("child count",2,root.getChildrenAsNodeArray());
565         Node child = root.childAt(0);
566         assertType("child",CustomTag.class,child);
567         CustomTag customChild = (CustomTag)child;
568         assertNodeCount("grand child count",1,customChild.getChildrenAsNodeArray());
569         Node grandchild = customChild.childAt(0);
570         assertType("grandchild",AnotherTag.class,grandchild);
571     }
572
573     public void testDisallowedChildren() throws ParserException {
574         createParser(
575             "<custom>\n" +
576             "Hello" +
577             "<custom>\n" +
578             "World" +
579             "<custom>\n" +
580             "Hey\n" +
581             "</custom>"
582         );
583         parser.setNodeFactory (new PrototypicalNodeFactory (new CustomTag (false)));
584         parseAndAssertNodeCount(3);
585         for (int i=0;i<nodeCount;i++) {
586             assertType("node "+i,CustomTag.class,node[i]);
587         }
588     }
589
590     public static class CustomScanner extends CompositeTagScanner {
591         private static final String JavaDoc MATCH_NAME [] = { "CUSTOM" };
592         public CustomScanner() {
593         }
594
595         public String JavaDoc[] getID() {
596             return MATCH_NAME;
597         }
598     }
599
600     public static class AnotherScanner extends CompositeTagScanner {
601         private static final String JavaDoc MATCH_NAME [] = { "ANOTHER" };
602         public AnotherScanner() {
603         }
604
605         public String JavaDoc[] getID() {
606             return MATCH_NAME;
607         }
608
609         protected boolean isBrokenTag() {
610             return false;
611         }
612
613     }
614
615     public static class CustomTag extends CompositeTag
616     {
617         /**
618          * The set of names handled by this tag.
619          */

620         private static final String JavaDoc[] mIds = new String JavaDoc[] {"CUSTOM"};
621
622         protected String JavaDoc[] mEnders;
623
624         /**
625          * The default scanner for custom tags.
626          */

627         protected final static CustomScanner mCustomScanner = new CustomScanner ();
628
629         public CustomTag ()
630         {
631             this (true);
632         }
633
634         public CustomTag (boolean selfChildrenAllowed)
635         {
636             if (selfChildrenAllowed)
637                 mEnders = new String JavaDoc[0];
638             else
639                 mEnders = mIds;
640             setThisScanner (mCustomScanner);
641         }
642
643         /**
644          * Return the set of names handled by this tag.
645          * @return The names to be matched that create tags of this type.
646          */

647         public String JavaDoc[] getIds ()
648         {
649             return (mIds);
650         }
651
652         /**
653          * Return the set of tag names that cause this tag to finish.
654          * @return The names of following tags that stop further scanning.
655          */

656         public String JavaDoc[] getEnders ()
657         {
658             return (mEnders);
659         }
660
661         
662     }
663
664     public static class AnotherTag extends CompositeTag
665     {
666         /**
667          * The set of names handled by this tag.
668          */

669         private static final String JavaDoc[] mIds = new String JavaDoc[] {"ANOTHER"};
670
671         /**
672          * The set of tag names that indicate the end of this tag.
673          */

674         private final String JavaDoc[] mEnders;
675
676         /**
677          * The set of end tag names that indicate the end of this tag.
678          */

679         private final String JavaDoc[] mEndTagEnders;
680
681         /**
682          * The default scanner for custom tags.
683          */

684         protected final static AnotherScanner mAnotherScanner = new AnotherScanner ();
685
686         public AnotherTag (boolean acceptCustomTagsButDontAcceptCustomEndTags)
687         {
688             if (acceptCustomTagsButDontAcceptCustomEndTags)
689             {
690                 mEnders = new String JavaDoc[0];
691                 mEndTagEnders = new String JavaDoc[] {"CUSTOM"};
692             }
693             else
694             {
695                 mEnders = new String JavaDoc[] {"CUSTOM"};
696                 mEndTagEnders = new String JavaDoc[] {"CUSTOM"};
697             }
698             setThisScanner (mAnotherScanner);
699         }
700
701         /**
702          * Return the set of names handled by this tag.
703          * @return The names to be matched that create tags of this type.
704          */

705         public String JavaDoc[] getIds ()
706         {
707             return (mIds);
708         }
709
710         /**
711          * Return the set of tag names that cause this tag to finish.
712          * @return The names of following tags that stop further scanning.
713          */

714         public String JavaDoc[] getEnders ()
715         {
716             return (mEnders);
717         }
718
719         /**
720          * Return the set of end tag names that cause this tag to finish.
721          * @return The names of following end tags that stop further scanning.
722          */

723         public String JavaDoc[] getEndTagEnders ()
724         {
725             return (mEndTagEnders);
726         }
727     }
728
729     /**
730      * Extracted from "http://scores.nba.com/games/20031029/scoreboard.html"
731      * which has a lot of table columns with unclosed DIV tags because the
732      * closing DIV doesn't have a slash.
733      * This caused java.lang.StackOverflowError on Windows.
734      * Tests the new non-recursive CompositeTagScanner with the walk back
735      * through the parse stack.
736      * See also Bug #750117 StackOverFlow while Node-Iteration and
737      * others.
738      */

739     public void testInvalidNesting () throws ParserException
740     {
741         String JavaDoc html = "<table cellspacing=\"2\" cellpadding=\"0\" border=\"0\" width=\"600\">\n"
742             + "<tr>\n"
743             + "<td><div class=\"ScoreBoardSec\">&nbsp;<a target=\"_parent\" class=\"ScoreBoardSec\" HREF=\"http://www.nba.com/heat/\">Heat</a><div></td>\n"
744             + "</tr>\n"
745             + "</table>";
746         createParser (html);
747         parseAndAssertNodeCount (1);
748         assertType ("table", TableTag.class, node[0]);
749         TableTag table = (TableTag)node[0];
750         assertTrue ("table should have 3 nodes", 3 == table.getChildCount ());
751         assertType ("row", TableRow.class, table.childAt (1));
752         TableRow row = (TableRow)table.childAt (1);
753         assertTrue ("row should have 3 nodes", 3 == row.getChildCount ());
754         assertType ("column", TableColumn.class, row.childAt (1));
755         TableColumn column = (TableColumn)row.childAt (1);
756         assertTrue ("column should have 1 node", 1 == column.getChildCount ());
757         assertType ("element", Div.class, column.childAt (0));
758         Div div = (Div)column.childAt (0);
759         assertTrue ("div should have 3 nodes", 3 == div.getChildCount ());
760         assertType ("link", LinkTag.class, div.childAt (1));
761         LinkTag link = (LinkTag)div.childAt (1);
762         assertTrue ("link contents", link.getLink ().equals ("http://www.nba.com/heat/"));
763         assertType ("bogus div", Div.class, div.childAt (2));
764         assertTrue ("bogus div should have no children", 0 == ((Div)div.childAt (2)).getChildCount ());
765     }
766 }
767
Popular Tags