Author: ltheussl
Date: Mon Mar  2 10:54:56 2009
New Revision: 749267

URL: http://svn.apache.org/viewvc?rev=749267&view=rev
Log:
[DOXIA-241] Xdoc/XhtmlBaseParser doesn't close sections properly

Modified:
    
maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
    
maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java

Modified: 
maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java?rev=749267&r1=749266&r2=749267&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
 Mon Mar  2 10:54:56 2009
@@ -507,12 +507,48 @@
     }
 
     /**
-     * Close open sections. The current level is set to newLevel afterwards.
+     * Make sure sections are nested consecutively.
+     *
+     * <p>
+     * HTML doesn't have any sections, only sectionTitles (&lt;h2&gt, etc), 
that means we have to
+     * open close any sections that are missing in between.
+     * </p>
+     *
+     * <p>
+     * For instance, if the following sequence is parsed:
+     * <pre>
+     * <h3></h3>
+     * <h6></h6>
+     * </pre>
+     * we have to insert two section starts before we open the 
<code>&lt;h6&gt;</code>.
+     * In the following sequence
+     * <pre>
+     * <h6></h6>
+     * <h3></h3>
+     * </pre>
+     * we have to close two sections before we open the 
<code>&lt;h3&gt;</code>.
+     * </p>
+     *
+     * <p>The current level is set to newLevel afterwards.</p>
      *
      * @param newLevel the new section level, all upper levels have to be 
closed.
      * @param sink the sink to receive the events.
      */
-    protected void closeOpenSections( int newLevel, Sink sink )
+    protected void consecutiveSections( int newLevel, Sink sink )
+    {
+        closeOpenSections( newLevel, sink );
+        openMissingSections( newLevel, sink );
+
+        this.sectionLevel = newLevel;
+    }
+
+    /**
+     * Close open sections.
+     *
+     * @param newLevel the new section level, all upper levels have to be 
closed.
+     * @param sink the sink to receive the events.
+     */
+    private void closeOpenSections( int newLevel, Sink sink )
     {
         while ( this.sectionLevel >= newLevel )
         {
@@ -539,8 +575,41 @@
 
             this.sectionLevel--;
         }
+    }
 
-        this.sectionLevel = newLevel;
+    /**
+     * Open missing sections.
+     *
+     * @param newLevel the new section level, all lower levels have to be 
opened.
+     * @param sink the sink to receive the events.
+     */
+    private void openMissingSections( int newLevel, Sink sink )
+    {
+        while ( this.sectionLevel < newLevel - 1 )
+        {
+            this.sectionLevel++;
+
+            if ( sectionLevel == Sink.SECTION_LEVEL_5 )
+            {
+                sink.section5();
+            }
+            else if ( sectionLevel == Sink.SECTION_LEVEL_4 )
+            {
+                sink.section4();
+            }
+            else if ( sectionLevel == Sink.SECTION_LEVEL_3 )
+            {
+                sink.section3();
+            }
+            else if ( sectionLevel == Sink.SECTION_LEVEL_2 )
+            {
+                sink.section2();
+            }
+            else if ( sectionLevel == Sink.SECTION_LEVEL_1 )
+            {
+                sink.section1();
+            }
+        }
     }
 
     /**
@@ -793,7 +862,7 @@
 
     private void handleSectionStart( Sink sink, int sectionLevel, 
SinkEventAttributeSet attribs )
     {
-        closeOpenSections( sectionLevel, sink );
+        consecutiveSections( sectionLevel, sink );
         sink.section( sectionLevel, attribs );
         sink.sectionTitle( sectionLevel, attribs );
     }

Modified: 
maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java?rev=749267&r1=749266&r2=749267&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java
 Mon Mar  2 10:54:56 2009
@@ -88,6 +88,49 @@
         assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() );
         assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() 
).getName() );
         assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() 
).getName() );
+        // this one is missing because we enclose everything in <p> which is 
not valid xhtml,
+        // needs to be tested in overriding parser, eg XhtmlParser, XdocParser.
+        //assertEquals( "section1_", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "paragraph_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertFalse( it.hasNext() );
+    }
+
+    /** @throws Exception  */
+    public void testNestedHeadingEventsList()
+        throws Exception
+    {
+        // DOXIA-241
+        String text = "<p><h2></h2><h6></h6><h3></h3></p>";
+
+        parser.parse( text, sink );
+
+        Iterator it = sink.getEventList().iterator();
+
+        assertEquals( "paragraph", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() 
).getName() );
+
+        assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "section3", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "section4", ( (SinkEventElement) it.next() ).getName() );
+
+        assertEquals( "section5", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle5", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "sectionTitle5_", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "section5_", ( (SinkEventElement) it.next() ).getName() 
);
+
+        assertEquals( "section4_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section3_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() 
);
+
+        assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle2", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "sectionTitle2_", ( (SinkEventElement) it.next() 
).getName() );
+        // these two are missing because we enclose everything in <p> which is 
not valid xhtml,
+        // needs to be tested in overriding parser, eg XhtmlParser, XdocParser.
+        //assertEquals( "section2_", ( (SinkEventElement) it.next() 
).getName() );
+        //assertEquals( "section1_", ( (SinkEventElement) it.next() 
).getName() );
         assertEquals( "paragraph_", ( (SinkEventElement) it.next() ).getName() 
);
         assertFalse( it.hasNext() );
     }

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java?rev=749267&r1=749266&r2=749267&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java
 Mon Mar  2 10:54:56 2009
@@ -141,7 +141,7 @@
         }
         else if ( parser.getName().equals( SECTION_TAG.toString() ) )
         {
-            closeOpenSections( Sink.SECTION_LEVEL_1, sink );
+            consecutiveSections( Sink.SECTION_LEVEL_1, sink );
 
             Object id = attribs.getAttribute( Attribute.ID.toString() );
             if ( id != null )
@@ -160,7 +160,7 @@
         }
         else if ( parser.getName().equals( SUBSECTION_TAG.toString() ) )
         {
-            closeOpenSections( Sink.SECTION_LEVEL_2, sink );
+            consecutiveSections( Sink.SECTION_LEVEL_2, sink );
 
             Object id = attribs.getAttribute( Attribute.ID.toString() );
             if ( id != null )
@@ -300,7 +300,7 @@
         }
         else if ( parser.getName().equals( Tag.BODY.toString() ) )
         {
-            closeOpenSections( 0, sink );
+            consecutiveSections( 0, sink );
 
             sink.body_();
         }
@@ -370,15 +370,13 @@
         }
         else if ( parser.getName().equals( SECTION_TAG.toString() ) )
         {
-            closeOpenSections( 0, sink );
+            consecutiveSections( 0, sink );
 
             sink.section1_();
         }
         else if ( parser.getName().equals( SUBSECTION_TAG.toString() ) )
         {
-            closeOpenSections( Sink.SECTION_LEVEL_1, sink );
-
-            sink.section2_();
+            consecutiveSections( Sink.SECTION_LEVEL_1, sink );
         }
         else if ( parser.getName().equals( Tag.SCRIPT.toString() ) )
         {
@@ -413,12 +411,19 @@
         }
     }
 
+    /** {...@inheritdoc} */
+    protected void consecutiveSections( int newLevel, Sink sink )
+    {
+        closeOpenSections( newLevel, sink );
+        openMissingSections( newLevel, sink );
+
+        setSectionLevel( newLevel );
+    }
+
     /**
-     * {...@inheritdoc}
-     *
-     * Close open h4, h5, h6 sections. The current level is set to newLevel 
afterwards.
+     * Close open h4, h5, h6 sections.
      */
-    protected void closeOpenSections( int newLevel, Sink sink )
+    private void closeOpenSections( int newLevel, Sink sink )
     {
         while ( getSectionLevel() >= newLevel )
         {
@@ -434,10 +439,40 @@
             {
                 sink.section3_();
             }
+            else if ( getSectionLevel() == Sink.SECTION_LEVEL_2 )
+            {
+                sink.section2_();
+            }
 
             setSectionLevel( getSectionLevel() - 1 );
         }
+    }
 
-        setSectionLevel( newLevel );
+    /**
+     * Open missing h4, h5, h6 sections.
+     */
+    private void openMissingSections( int newLevel, Sink sink )
+    {
+        while ( getSectionLevel() < newLevel - 1 )
+        {
+            setSectionLevel( getSectionLevel() + 1 );
+
+            if ( getSectionLevel() == Sink.SECTION_LEVEL_5 )
+            {
+                sink.section5();
+            }
+            else if ( getSectionLevel() == Sink.SECTION_LEVEL_4 )
+            {
+                sink.section4();
+            }
+            else if ( getSectionLevel() == Sink.SECTION_LEVEL_3 )
+            {
+                sink.section3();
+            }
+            else if ( getSectionLevel() == Sink.SECTION_LEVEL_2 )
+            {
+                sink.section2();
+            }
+        }
     }
 }

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java?rev=749267&r1=749266&r2=749267&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
 Mon Mar  2 10:54:56 2009
@@ -213,6 +213,44 @@
     }
 
     /** @throws Exception  */
+    public void testNestedSectionsEventsList()
+        throws Exception
+    {
+        // DOXIA-241
+        String text = "<section name=\"section\"><h6>h6</h6><subsection 
name=\"subsection\"></subsection></section>";
+
+        SinkEventTestingSink sink = new SinkEventTestingSink();
+
+        parser.parse( text, sink );
+
+        Iterator it = sink.getEventList().iterator();
+
+        assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "text", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "section3", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "section4", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "section5", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle5", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "text", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle5_", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "section5_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section4_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section3_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() 
);
+
+        assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle2", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "text", ( (SinkEventElement) it.next() ).getName() );
+        assertEquals( "sectionTitle2_", ( (SinkEventElement) it.next() 
).getName() );
+        assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertEquals( "section1_", ( (SinkEventElement) it.next() ).getName() 
);
+        assertFalse( it.hasNext() );
+    }
+
+    /** @throws Exception  */
     public void testSourceEventsList()
         throws Exception
     {

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java?rev=749267&r1=749266&r2=749267&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
 Mon Mar  2 10:54:56 2009
@@ -210,7 +210,7 @@
         }
         else if ( parser.getName().equals( Tag.BODY.toString() ) )
         {
-            closeOpenSections( 0, sink );
+            consecutiveSections( 0, sink );
 
             sink.body_();
         }


Reply via email to