Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/htmlparser/tests/scannersTests/CompositeTagScannerTest.java


1   // $Header: /home/cvs/jakarta-jmeter/src/htmlparser/org/htmlparser/tests/scannersTests/CompositeTagScannerTest.java,v 1.2 2004/02/11 02:16:58 woolfel Exp $
2   /*
3    * ====================================================================
4    * Copyright 2002-2004 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   * 
18   */
19  
20  // The developers of JMeter and Apache are greatful to the developers
21  // of HTMLParser for giving Apache Software Foundation a non-exclusive
22  // license. The performance benefits of HTMLParser are clear and the
23  // users of JMeter will benefit from the hard work the HTMLParser
24  // team. For detailed information about HTMLParser, the project is
25  // hosted on sourceforge at http://htmlparser.sourceforge.net/.
26  //
27  // HTMLParser was originally created by Somik Raha in 2000. Since then
28  // a healthy community of users has formed and helped refine the
29  // design so that it is able to tackle the difficult task of parsing
30  // dirty HTML. Derrick Oswald is the current lead developer and was kind
31  // enough to assist JMeter.
32  
33  package org.htmlparser.tests.scannersTests;
34  
35  import org.htmlparser.Node;
36  import org.htmlparser.StringNode;
37  import org.htmlparser.scanners.CompositeTagScanner;
38  import org.htmlparser.tags.CompositeTag;
39  import org.htmlparser.tags.EndTag;
40  import org.htmlparser.tags.Tag;
41  import org.htmlparser.tags.data.CompositeTagData;
42  import org.htmlparser.tags.data.TagData;
43  import org.htmlparser.tests.ParserTestCase;
44  import org.htmlparser.util.ParserException;
45  
46  public class CompositeTagScannerTest extends ParserTestCase {
47    private CompositeTagScanner scanner;
48    private String url;
49    
50    public CompositeTagScannerTest(String name) {
51      super(name);
52    }
53  
54    protected void setUp() {
55      String [] arr = { 
56        "SOMETHING"
57      };
58      scanner = 
59        new CompositeTagScanner(arr) {
60          public Tag createTag(TagData tagData, CompositeTagData compositeTagData) throws ParserException {
61            return null;
62          }
63          public String[] getID() {
64            return null;
65          }
66  
67        };
68    }
69  
70    private CustomTag parseCustomTag(int expectedNodeCount) throws ParserException {
71      parser.addScanner(new CustomScanner());
72      parseAndAssertNodeCount(expectedNodeCount);
73      assertType("node",CustomTag.class,node[0]);
74      CustomTag customTag = (CustomTag)node[0];
75      return customTag;
76    }
77  
78    public void testEmptyCompositeTag() throws ParserException {
79      createParser(
80        "<Custom/>"
81      );
82      CustomTag customTag = parseCustomTag(1);
83      int x = customTag.getChildCount();
84      assertEquals("child count",0,customTag.getChildCount());
85      assertTrue("custom tag should be xml end tag",customTag.isEmptyXmlTag());
86      assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
87      assertEquals("ending loc",8,customTag.getStartTag().elementEnd());
88      assertEquals("starting line position",1,customTag.tagData.getStartLine());
89      assertEquals("ending line position",1,customTag.tagData.getEndLine());
90      assertStringEquals("html","<CUSTOM/>",customTag.toHtml());
91    }
92    
93    public void testEmptyCompositeTagAnotherStyle() throws ParserException {
94      createParser(
95        "<Custom></Custom>"
96      );
97      CustomTag customTag = parseCustomTag(1);
98      int x = customTag.getChildCount();
99      assertEquals("child count",0,customTag.getChildCount());
100     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
101     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
102     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
103     assertEquals("starting line position",1,customTag.tagData.getStartLine());
104     assertEquals("ending line position",1,customTag.tagData.getEndLine());
105     assertEquals("html","<CUSTOM></CUSTOM>",customTag.toHtml());
106   }
107 
108   public void testCompositeTagWithOneTextChild() throws ParserException {
109     createParser(
110       "<Custom>" +
111         "Hello" +
112       "</Custom>"
113     );
114     CustomTag customTag = parseCustomTag(1);
115     int x = customTag.getChildCount();
116     assertEquals("child count",1,customTag.getChildCount());
117     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
118     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
119     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
120     assertEquals("starting line position",1,customTag.tagData.getStartLine());
121     assertEquals("ending line position",1,customTag.tagData.getEndLine());
122     
123     Node child = customTag.childAt(0);
124     assertType("child",StringNode.class,child);
125     StringNode text = (StringNode)child;
126     assertStringEquals("child text","Hello",child.toPlainTextString());
127   }
128 
129   public void testCompositeTagWithTagChild() throws ParserException {
130     createParser(
131       "<Custom>" +
132         "<Hello>" +
133       "</Custom>"
134     );
135     CustomTag customTag = parseCustomTag(1);
136     int x = customTag.getChildCount();
137     assertEquals("child count",1,customTag.getChildCount());
138     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
139     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
140     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
141     assertEquals("custom tag starting loc",0,customTag.elementBegin());
142     assertEquals("custom tag ending loc",23,customTag.elementEnd());
143 
144     Node child = customTag.childAt(0);
145     assertType("child",Tag.class,child);
146     Tag tag = (Tag)child;
147     assertStringEquals("child html","<HELLO>",child.toHtml());
148   }
149 
150   public void testCompositeTagWithAnotherTagChild() throws ParserException {
151     createParser(
152       "<Custom>" +
153         "<Another/>" +
154       "</Custom>"
155     );
156     parser.addScanner(new AnotherScanner());
157     CustomTag customTag = parseCustomTag(1);
158     int x = customTag.getChildCount();
159     assertEquals("child count",1,customTag.getChildCount());
160     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
161     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
162     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
163     assertEquals("custom tag starting loc",0,customTag.elementBegin());
164     assertEquals("custom tag ending loc",26,customTag.elementEnd());
165 
166     Node child = customTag.childAt(0);
167     assertType("child",AnotherTag.class,child);
168     AnotherTag tag = (AnotherTag)child;
169     assertEquals("another tag start pos",8,tag.elementBegin());
170     assertEquals("another tag ending pos",17,tag.elementEnd());
171     
172     assertEquals("custom end tag start pos",18,customTag.getEndTag().elementBegin());
173     assertStringEquals("child html","<ANOTHER/>",child.toHtml());
174   }
175     
176   public void testParseTwoCompositeTags() throws ParserException {
177     createParser(
178       "<Custom>" +
179       "</Custom>" +
180       "<Custom/>"
181     );
182     parser.addScanner(new CustomScanner());
183     parseAndAssertNodeCount(2);
184     assertType("tag 1",CustomTag.class,node[0]);
185     assertType("tag 2",CustomTag.class,node[1]);
186   }
187   
188   public void testXmlTypeCompositeTags() throws ParserException {
189     createParser(
190       "<Custom>" +
191         "<Another name=\"subtag\"/>" +
192         "<Custom />" +
193       "</Custom>" +
194       "<Custom/>"
195     );
196     parser.addScanner(new CustomScanner());
197     parser.addScanner(new AnotherScanner());
198     parseAndAssertNodeCount(2);
199     assertType("first node",CustomTag.class,node[0]);
200     assertType("second node",CustomTag.class,node[1]);
201     CustomTag customTag = (CustomTag)node[0];
202     Node node = customTag.childAt(0);
203     assertType("first child",AnotherTag.class,node);
204     node = customTag.childAt(1);
205     assertType("second child",CustomTag.class,node);
206   }  
207   
208   public void testCompositeTagWithNestedTag() throws ParserException {
209     createParser(
210       "<Custom>" +
211         "<Another>" +
212           "Hello" +
213         "</Another>" +
214         "<Custom/>" +
215       "</Custom>" +
216       "<Custom/>"
217     );
218     parser.addScanner(new CustomScanner());
219     parser.addScanner(new AnotherScanner());
220     parseAndAssertNodeCount(2);
221     assertType("first node",CustomTag.class,node[0]);
222     assertType("second node",CustomTag.class,node[1]);
223     CustomTag customTag = (CustomTag)node[0];
224     Node node = customTag.childAt(0);
225     assertType("first child",AnotherTag.class,node);
226     AnotherTag anotherTag = (AnotherTag)node;
227     assertEquals("another tag children count",1,anotherTag.getChildCount());
228     node = anotherTag.childAt(0);
229     assertType("nested child",StringNode.class,node);
230     StringNode text = (StringNode)node;
231     assertEquals("text","Hello",text.toPlainTextString());
232   }
233 
234   public void testCompositeTagWithTwoNestedTags() throws ParserException {
235     createParser(
236       "<Custom>" +
237         "<Another>" +
238           "Hello" +
239         "</Another>" +
240         "<unknown>" +
241           "World" +
242         "</unknown>" +
243         "<Custom/>" +
244       "</Custom>" +
245       "<Custom/>"
246     );
247     parser.addScanner(new CustomScanner());
248     parser.addScanner(new AnotherScanner());
249     parseAndAssertNodeCount(2);
250     assertType("first node",CustomTag.class,node[0]);
251     assertType("second node",CustomTag.class,node[1]);
252     CustomTag customTag = (CustomTag)node[0];
253     assertEquals("first custom tag children count",5,customTag.getChildCount());
254     Node node = customTag.childAt(0);
255     assertType("first child",AnotherTag.class,node);
256     AnotherTag anotherTag = (AnotherTag)node;
257     assertEquals("another tag children count",1,anotherTag.getChildCount());
258     node = anotherTag.childAt(0);
259     assertType("nested child",StringNode.class,node);
260     StringNode text = (StringNode)node;
261     assertEquals("text","Hello",text.toPlainTextString());
262   }
263   
264   public void testErroneousCompositeTag() throws ParserException {
265     createParser("<custom>");
266     CustomTag customTag = parseCustomTag(1);
267     int x = customTag.getChildCount();
268     assertEquals("child count",0,customTag.getChildCount());
269     assertFalse("custom tag should be xml end tag",customTag.isEmptyXmlTag());
270     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
271     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
272     assertEquals("starting line position",1,customTag.tagData.getStartLine());
273     assertEquals("ending line position",1,customTag.tagData.getEndLine());
274     assertStringEquals("html","<CUSTOM></CUSTOM>",customTag.toHtml());    
275   }
276 
277   public void testErroneousCompositeTagWithChildren() throws ParserException {
278     createParser(
279       "<custom>" +
280         "<firstChild>" +
281         "<secondChild>"
282     );
283     CustomTag customTag = parseCustomTag(1);
284     int x = customTag.getChildCount();
285     assertEquals("child count",2,customTag.getChildCount());
286     assertFalse("custom tag should be xml end tag",customTag.isEmptyXmlTag());
287     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
288     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
289     assertEquals("starting line position",1,customTag.tagData.getStartLine());
290     assertEquals("ending line position",1,customTag.tagData.getEndLine());
291     assertStringEquals("html","<CUSTOM><FIRSTCHILD><SECONDCHILD></CUSTOM>",customTag.toHtml());    
292   }
293   
294   public void testErroneousCompositeTagWithChildrenAndLineBreak() throws ParserException {
295     createParser(
296       "<custom>" +
297         "<firstChild>\n" +
298         "<secondChild>"
299     );
300     CustomTag customTag = parseCustomTag(1);
301     int x = customTag.getChildCount();
302     assertEquals("child count",2,customTag.getChildCount());
303     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
304     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
305     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
306     assertEquals("starting line position",1,customTag.tagData.getStartLine());
307     assertEquals("ending line position",2,customTag.tagData.getEndLine());
308     assertStringEquals(
309       "html",
310       "<CUSTOM><FIRSTCHILD>\r\n" +
311       "<SECONDCHILD>" +
312       "</CUSTOM>",
313       customTag.toHtml()
314     );    
315   }
316   
317   public void testTwoConsecutiveErroneousCompositeTags() throws ParserException {
318     createParser(
319       "<custom>something" +
320       "<custom></endtag>"
321     );
322     parser.addScanner(new CustomScanner(false));
323     parseAndAssertNodeCount(2);
324     CustomTag customTag = (CustomTag)node[0];
325     int x = customTag.getChildCount();
326     assertEquals("child count",1,customTag.getChildCount());
327     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
328     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
329     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
330     assertEquals("ending loc of custom tag",25,customTag.elementEnd());
331     assertEquals("starting line position",1,customTag.tagData.getStartLine());
332     assertEquals("ending line position",1,customTag.tagData.getEndLine());
333     assertStringEquals(
334       "first custom tag",
335       "<CUSTOM>something</CUSTOM>",
336       customTag.toHtml()
337     );    
338     customTag = (CustomTag)node[1];
339     assertStringEquals(
340       "second custom tag",
341       "<CUSTOM></ENDTAG></CUSTOM>",
342       customTag.toHtml()
343     );
344   }
345     
346   public void testCompositeTagWithErroneousAnotherTagAndLineBreak() throws ParserException {
347     createParser(
348       "<another>" +
349       "<custom>\n" +
350       "</custom>"
351     );
352     parser.addScanner(new AnotherScanner());
353     parser.addScanner(new CustomScanner());
354     parseAndAssertNodeCount(2);
355     AnotherTag anotherTag = (AnotherTag)node[0];
356     assertEquals("another tag child count",0,anotherTag.getChildCount());
357     
358     CustomTag customTag = (CustomTag)node[1];
359     int x = customTag.getChildCount();
360     assertEquals("child count",0,customTag.getChildCount());
361     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
362     assertEquals("starting loc",9,customTag.getStartTag().elementBegin());
363     assertEquals("ending loc",16,customTag.getStartTag().elementEnd());
364     assertEquals("starting line position",1,customTag.tagData.getStartLine());
365     assertEquals("ending line position",2,customTag.tagData.getEndLine());
366     assertStringEquals("another tag html","<ANOTHER></ANOTHER>",anotherTag.toHtml());
367     assertStringEquals("custom tag html","<CUSTOM>\r\n</CUSTOM>",customTag.toHtml());    
368   }
369 
370   public void testCompositeTagWithErroneousAnotherTag() throws ParserException {
371     createParser(
372       "<custom>" +
373         "<another>" +
374       "</custom>"
375     );
376     parser.addScanner(new AnotherScanner(true));
377     CustomTag customTag = parseCustomTag(1);
378     int x = customTag.getChildCount();
379     assertEquals("child count",1,customTag.getChildCount());
380     assertFalse("custom tag should be xml end tag",customTag.isEmptyXmlTag());
381     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
382     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
383     AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
384     assertEquals("another tag ending loc",26,anotherTag.elementEnd());
385     assertEquals("starting line position",1,customTag.tagData.getStartLine());
386     assertEquals("ending line position",1,customTag.tagData.getEndLine());
387     assertStringEquals("html","<CUSTOM><ANOTHER></ANOTHER></CUSTOM>",customTag.toHtml());    
388   }
389 
390   public void testCompositeTagWithDeadlock() throws ParserException {
391     createParser(
392       "<custom>" +
393         "<another>something" +
394       "</custom>"+
395       "<custom>" +
396         "<another>else</another>" +
397       "</custom>"
398     );
399     parser.addScanner(new AnotherScanner(true));
400     CustomTag customTag = parseCustomTag(2);
401     int x = customTag.getChildCount();
402     assertEquals("child count",1,customTag.getChildCount());
403     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
404     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
405     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
406     assertEquals("starting line position",1,customTag.tagData.getStartLine());
407     assertEquals("ending line position",1,customTag.tagData.getEndLine());
408     AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
409     assertEquals("anotherTag child count",1,anotherTag.getChildCount());
410     StringNode stringNode = (StringNode)anotherTag.childAt(0);
411     assertStringEquals("anotherTag child text","something",stringNode.toPlainTextString());
412     assertStringEquals(
413       "first custom tag html",
414       "<CUSTOM><ANOTHER>something</ANOTHER></CUSTOM>",
415       customTag.toHtml()
416     );    
417     customTag = (CustomTag)node[1];
418     assertStringEquals(
419       "second custom tag html",
420       "<CUSTOM><ANOTHER>else</ANOTHER></CUSTOM>",
421       customTag.toHtml()
422     );
423   }
424 
425   public void testCompositeTagCorrectionWithSplitLines() throws ParserException {
426     createParser(
427       "<custom>" +
428         "<another><abcdefg>\n" +
429       "</custom>"
430     );
431     parser.addScanner(new AnotherScanner(true));
432     CustomTag customTag = parseCustomTag(1);
433     int x = customTag.getChildCount();
434     assertEquals("child count",1,customTag.getChildCount());
435     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
436     assertEquals("starting loc",0,customTag.getStartTag().elementBegin());
437     assertEquals("ending loc",7,customTag.getStartTag().elementEnd());
438     AnotherTag anotherTag = (AnotherTag)customTag.childAt(0);
439     assertEquals("anotherTag child count",1,anotherTag.getChildCount());
440     assertEquals("anotherTag end loc",9,anotherTag.elementEnd());
441     assertEquals("custom end tag begin loc",10,customTag.getEndTag().elementBegin());
442     assertEquals("custom end tag end loc",8,customTag.getEndTag().elementEnd());
443   }  
444   
445   public void testCompositeTagWithSelfChildren() throws ParserException {
446     createParser(
447       "<custom>" +
448       "<custom>something</custom>" +
449       "</custom>"
450     );
451     parser.addScanner(new CustomScanner(false));
452     parser.addScanner(new AnotherScanner());
453     parseAndAssertNodeCount(3);
454     
455     CustomTag customTag = (CustomTag)node[0];
456     int x = customTag.getChildCount();
457     assertEquals("child count",0,customTag.getChildCount());
458     assertFalse("custom tag should not be xml end tag",customTag.isEmptyXmlTag());
459     
460     assertStringEquals(
461       "first custom tag html",
462       "<CUSTOM></CUSTOM>",
463       customTag.toHtml()
464     );
465     customTag = (CustomTag)node[1];
466     assertStringEquals(
467       "first custom tag html",
468       "<CUSTOM>something</CUSTOM>",
469       customTag.toHtml()
470     );
471     EndTag endTag = (EndTag)node[2];
472     assertStringEquals(
473       "first custom tag html",
474       "</CUSTOM>",
475       endTag.toHtml()
476     );
477   }
478   
479   public void testParentConnections() throws ParserException {
480     createParser(
481       "<custom>" +
482       "<custom>something</custom>" +
483       "</custom>"
484     );
485     parser.addScanner(new CustomScanner(false));
486     parser.addScanner(new AnotherScanner());
487     parseAndAssertNodeCount(3);
488     
489     CustomTag customTag = (CustomTag)node[0];
490     
491     assertStringEquals(
492       "first custom tag html",
493       "<CUSTOM></CUSTOM>",
494       customTag.toHtml()
495     );
496     assertNull(
497       "first custom tag should have no parent",
498       customTag.getParent()
499     );
500     
501     customTag = (CustomTag)node[1];
502     assertStringEquals(
503       "first custom tag html",
504       "<CUSTOM>something</CUSTOM>",
505       customTag.toHtml()
506     );
507     assertNull(
508       "second custom tag should have no parent",
509       customTag.getParent()
510     );
511   
512     Node firstChild = customTag.childAt(0);
513     assertType("firstChild",StringNode.class,firstChild);
514     CompositeTag parent = firstChild.getParent();
515     assertNotNull("first child parent should not be null",parent);
516     assertSame("parent and custom tag should be the same",customTag,parent);
517     
518     EndTag endTag = (EndTag)node[2];
519     assertStringEquals(
520       "first custom tag html",
521       "</CUSTOM>",
522       endTag.toHtml()
523     );
524     assertNull(
525       "end tag should have no parent",
526       endTag.getParent()
527     );
528 
529   }
530   
531   public void testUrlBeingProvidedToCreateTag() throws ParserException {
532     createParser("<Custom/>","http://www.yahoo.com");
533     
534     parser.addScanner(new CustomScanner() {
535       public Tag createTag(
536         TagData tagData,
537         CompositeTagData compositeTagData) {
538         url = tagData.getUrlBeingParsed();
539         return super.createTag(
540           tagData,
541           compositeTagData
542         );
543       }
544     });
545     parseAndAssertNodeCount(1);
546     assertStringEquals("url","http://www.yahoo.com",url);    
547   }
548 
549   public void testComplexNesting() throws ParserException {
550     createParser(
551       "<custom>" +
552         "<custom>" +
553           "<another>" +
554         "</custom>" +
555         "<custom>" +
556           "<another>" +
557         "</custom>" +
558       "</custom>"
559     );
560     parser.addScanner(new CustomScanner());
561     parser.addScanner(new AnotherScanner(false));
562     parseAndAssertNodeCount(1);
563     assertType("root node",CustomTag.class, node[0]);
564     CustomTag root = (CustomTag)node[0];
565     assertNodeCount("child count",2,root.getChildrenAsNodeArray());
566     Node child = root.childAt(0);
567     assertType("child",CustomTag.class,child);
568     CustomTag customChild = (CustomTag)child;
569     assertNodeCount("grand child count",1,customChild.getChildrenAsNodeArray());
570     Node grandchild = customChild.childAt(0);
571     assertType("grandchild",AnotherTag.class,grandchild);
572   }
573 
574   public void testDisallowedChildren() throws ParserException {
575     createParser(
576       "<custom>\n" +
577       "Hello" +
578       "<custom>\n" +
579       "World" +
580       "<custom>\n" +
581       "Hey\n" +
582       "</custom>" 
583     );
584     parser.addScanner(new CustomScanner(false));
585     parseAndAssertNodeCount(3);
586     for (int i=0;i<nodeCount;i++) {
587       assertType("node "+i,CustomTag.class,node[i]);
588     }
589   }
590   
591   public static class CustomScanner extends CompositeTagScanner {
592     private static final String MATCH_NAME [] = { "CUSTOM" };
593     public CustomScanner() { 
594       this(true); 
595     }
596     
597     public CustomScanner(boolean selfChildrenAllowed) { 
598       super("", MATCH_NAME, new String[] {}, selfChildrenAllowed); 
599     }
600     
601     public String[] getID() { 
602       return MATCH_NAME; 
603     }
604     
605     public Tag createTag(TagData tagData, CompositeTagData compositeTagData) {
606       return new CustomTag(tagData, compositeTagData);
607     }
608   }
609   
610   public static class AnotherScanner extends CompositeTagScanner {
611     private static final String MATCH_NAME [] = { "ANOTHER" };
612     public AnotherScanner() { 
613       super("", MATCH_NAME, new String[] {"CUSTOM"}); 
614     }
615     
616     public AnotherScanner(boolean acceptCustomTagsButDontAcceptCustomEndTags) { 
617       super("", MATCH_NAME, new String[] {}, new String[] {"CUSTOM"}, true); 
618     }
619     
620     public String[] getID() { 
621       return MATCH_NAME; 
622     }
623     
624     public Tag createTag(TagData tagData, CompositeTagData compositeTagData) {
625       return new AnotherTag(tagData, compositeTagData);
626     }
627     protected boolean isBrokenTag() {
628       return false;
629     }
630     
631   }
632 
633   public static class CustomTag extends CompositeTag {
634     public TagData tagData;
635     public CustomTag(TagData tagData, CompositeTagData compositeTagData) {
636       super(tagData,compositeTagData);
637       this.tagData = tagData;
638     }
639   }
640   
641   public static class AnotherTag extends CompositeTag {
642     public AnotherTag(TagData tagData, CompositeTagData compositeTagData) {
643       super(tagData,compositeTagData);
644     }
645   }
646 
647 }