View Javadoc

1   package org.apache.maven.doxia.module.xhtml;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import javax.swing.text.html.HTML.Attribute;
23  
24  import org.apache.maven.doxia.macro.MacroExecutionException;
25  import org.apache.maven.doxia.parser.XhtmlBaseParser;
26  import org.apache.maven.doxia.sink.Sink;
27  import org.apache.maven.doxia.sink.SinkEventAttributeSet;
28  
29  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
30  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
31  
32  /**
33   * Parse an xhtml model and emit events into a Doxia Sink.
34   *
35   * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
36   * @version $Id: XhtmlParser.java 807186 2009-08-24 12:29:12Z vsiveton $
37   * @since 1.0
38   * @plexus.component role="org.apache.maven.doxia.parser.Parser" role-hint="xhtml"
39   */
40  public class XhtmlParser
41      extends XhtmlBaseParser
42      implements XhtmlMarkup
43  {
44      /** For boxed verbatim. */
45      private boolean boxed;
46  
47      /** Empty elements don't write a closing tag. */
48      private boolean isEmptyElement;
49  
50      /** {@inheritDoc} */
51      protected void handleStartTag( XmlPullParser parser, Sink sink )
52          throws XmlPullParserException, MacroExecutionException
53      {
54          isEmptyElement = parser.isEmptyElementTag();
55  
56          SinkEventAttributeSet attribs = getAttributesFromParser( parser );
57  
58          if ( parser.getName().equals( HTML.toString() ) )
59          {
60              //Do nothing
61              return;
62          }
63          else if ( parser.getName().equals( HEAD.toString() ) )
64          {
65              sink.head( attribs );
66          }
67          else if ( parser.getName().equals( TITLE.toString() ) )
68          {
69              sink.title( attribs );
70          }
71          else if ( parser.getName().equals( META.toString() ) )
72          {
73              String name = parser.getAttributeValue( null, Attribute.NAME.toString() );
74              String content = parser.getAttributeValue( null, Attribute.CONTENT.toString() );
75  
76              if ( "author".equals( name ) )
77              {
78                  sink.author( null );
79  
80                  sink.text( content );
81  
82                  sink.author_();
83              }
84              else if ( "date".equals( name ) )
85              {
86                  sink.date( null );
87  
88                  sink.text( content );
89  
90                  sink.date_();
91              }
92              else
93              {
94                  sink.unknown( "meta", new Object[] {new Integer( TAG_TYPE_SIMPLE )}, attribs );
95              }
96          }
97          /*
98           * The ADDRESS element may be used by authors to supply contact information
99           * for a model or a major part of a model such as a form. This element
100          *  often appears at the beginning or end of a model.
101          */
102         else if ( parser.getName().equals( ADDRESS.toString() ) )
103         {
104             sink.author( attribs );
105         }
106         else if ( parser.getName().equals( BODY.toString() ) )
107         {
108             sink.body( attribs );
109         }
110         else if ( parser.getName().equals( DIV.toString() ) )
111         {
112             String divclass = parser.getAttributeValue( null, Attribute.CLASS.toString() );
113 
114             if ( "source".equals( divclass ) )
115             {
116                 this.boxed = true;
117             }
118 
119             super.baseStartTag( parser, sink ); // pick up other divs
120         }
121         /*
122          * The PRE element tells visual user agents that the enclosed text is
123          * "preformatted". When handling preformatted text, visual user agents:
124          * - May leave white space intact.
125          * - May render text with a fixed-pitch font.
126          * - May disable automatic word wrap.
127          * - Must not disable bidirectional processing.
128          * Non-visual user agents are not required to respect extra white space
129          * in the content of a PRE element.
130          */
131         else if ( parser.getName().equals( PRE.toString() ) )
132         {
133             if ( boxed )
134             {
135                 attribs.addAttributes( SinkEventAttributeSet.BOXED );
136             }
137 
138             verbatim();
139 
140             sink.verbatim( attribs );
141         }
142         else if ( !baseStartTag( parser, sink ) )
143         {
144             if ( isEmptyElement )
145             {
146                 handleUnknown( parser, sink, TAG_TYPE_SIMPLE );
147             }
148             else
149             {
150                 handleUnknown( parser, sink, TAG_TYPE_START );
151             }
152 
153             if ( getLog().isDebugEnabled() )
154             {
155                 String position = "[" + parser.getLineNumber() + ":"
156                     + parser.getColumnNumber() + "]";
157                 String tag = "<" + parser.getName() + ">";
158 
159                 getLog().debug( "Unrecognized xhtml tag: " + tag + " at " + position );
160             }
161         }
162     }
163 
164     /** {@inheritDoc} */
165     protected void handleEndTag( XmlPullParser parser, Sink sink )
166         throws XmlPullParserException, MacroExecutionException
167     {
168         if ( parser.getName().equals( HTML.toString() ) )
169         {
170             //Do nothing
171             return;
172         }
173         else if ( parser.getName().equals( HEAD.toString() ) )
174         {
175             sink.head_();
176         }
177         else if ( parser.getName().equals( TITLE.toString() ) )
178         {
179             sink.title_();
180         }
181         else if ( parser.getName().equals( BODY.toString() ) )
182         {
183             consecutiveSections( 0, sink );
184 
185             sink.body_();
186         }
187         else if ( parser.getName().equals( ADDRESS.toString() ) )
188         {
189             sink.author_();
190         }
191         else if ( parser.getName().equals( DIV.toString() ) )
192         {
193             this.boxed = false;
194             super.baseEndTag( parser, sink );
195         }
196         else if ( !baseEndTag( parser, sink ) )
197         {
198             if ( !isEmptyElement )
199             {
200                 handleUnknown( parser, sink, TAG_TYPE_END );
201             }
202         }
203 
204         isEmptyElement = false;
205     }
206 
207     /** {@inheritDoc} */
208     protected void init()
209     {
210         super.init();
211 
212         this.boxed = false;
213         this.isEmptyElement = false;
214     }
215 }