View Javadoc

1   package org.apache.maven.doxia.module.twiki;
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 org.apache.maven.doxia.module.twiki.parser.Block;
23  import org.apache.maven.doxia.module.twiki.parser.BlockParser;
24  import org.apache.maven.doxia.module.twiki.parser.FormatedTextParser;
25  import org.apache.maven.doxia.module.twiki.parser.GenericListBlockParser;
26  import org.apache.maven.doxia.module.twiki.parser.HRuleBlockParser;
27  import org.apache.maven.doxia.module.twiki.parser.ParagraphBlockParser;
28  import org.apache.maven.doxia.module.twiki.parser.SectionBlock;
29  import org.apache.maven.doxia.module.twiki.parser.SectionBlockParser;
30  import org.apache.maven.doxia.module.twiki.parser.TableBlockParser;
31  import org.apache.maven.doxia.module.twiki.parser.TextParser;
32  import org.apache.maven.doxia.module.twiki.parser.VerbatimBlockParser;
33  import org.apache.maven.doxia.module.twiki.parser.XHTMLWikiWordLinkResolver;
34  import org.apache.maven.doxia.parser.AbstractTextParser;
35  import org.apache.maven.doxia.parser.ParseException;
36  import org.apache.maven.doxia.sink.Sink;
37  import org.apache.maven.doxia.util.ByLineReaderSource;
38  import org.apache.maven.doxia.util.ByLineSource;
39  
40  import java.io.Reader;
41  import java.util.ArrayList;
42  import java.util.List;
43  
44  /**
45   * Parse the <a href="http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules">
46   * twiki file format</a>
47   *
48   * @author Juan F. Codagnone
49   * @version $Id: TWikiParser.java 1090706 2011-04-09 23:15:28Z hboutemy $
50   * @since 1.0
51   * @plexus.component role="org.apache.maven.doxia.parser.Parser" role-hint="twiki"
52   */
53  public class TWikiParser
54      extends AbstractTextParser
55  {
56      private static final int EXTENSION_LENGTH = 6;
57  
58      /** paragraph parser. */
59      private final ParagraphBlockParser paraParser = new ParagraphBlockParser();
60  
61      /** section parser. */
62      private final SectionBlockParser sectionParser = new SectionBlockParser();
63  
64      /** enumeration parser. */
65      private final GenericListBlockParser listParser = new GenericListBlockParser();
66  
67      /** Text parser. */
68      private final FormatedTextParser formatTextParser = new FormatedTextParser();
69  
70      /**
71       * text parser.
72       * This only works for xhtml output, but there is no way
73       * of transforming a wikiWord in another context.
74       */
75      private final TextParser textParser = new TextParser( new XHTMLWikiWordLinkResolver() );
76  
77      /** hruler parser. */
78      private final HRuleBlockParser hrulerParser = new HRuleBlockParser();
79  
80      /** table parser. */
81      private final TableBlockParser tableParser = new TableBlockParser();
82  
83      /** verbatim parser. */
84      private final VerbatimBlockParser verbatimParser = new VerbatimBlockParser();
85  
86      /** list of parsers to try to apply to the toplevel */
87      private BlockParser[] parsers;
88  
89      /**
90       * Creates the TWikiParser.
91       */
92      public TWikiParser()
93      {
94          init();
95      }
96  
97      /**
98       * <p>parse.</p>
99       *
100      * @param source source to parse.
101      * @return the blocks that represent source.
102      * @throws org.apache.maven.doxia.parser.ParseException on error.
103      */
104     public final List<Block> parse( final ByLineSource source )
105         throws ParseException
106     {
107         final List<Block> ret = new ArrayList<Block>();
108 
109         String line;
110         while ( ( line = source.getNextLine() ) != null )
111         {
112             boolean accepted = false;
113 
114             for ( BlockParser parser : parsers )
115             {
116                 if ( parser.accept( line ) )
117                 {
118                     accepted = true;
119                     ret.add( parser.visit( line, source ) );
120                     break;
121                 }
122             }
123             if ( !accepted )
124             {
125                 throw new ParseException( "Line number not handle : " + source.getLineNumber() + ": " + line );
126             }
127         }
128 
129         return ret;
130     }
131 
132     /** {@inheritDoc} */
133     public final synchronized void parse( final Reader source, final Sink sink )
134         throws ParseException
135     {
136         init();
137 
138         List<Block> blocks;
139         final ByLineSource src = new ByLineReaderSource( source );
140 
141         try
142         {
143             blocks = parse( src );
144         }
145         catch ( final Exception e )
146         {
147             // TODO handle column number
148             throw new ParseException( e, src.getName(), src.getLineNumber(), -1 );
149         }
150 
151         sink.head();
152 
153         final String title = getTitle( blocks, src );
154         if ( title != null )
155         {
156             sink.title();
157             sink.text( title );
158             sink.title_();
159         }
160 
161         sink.head_();
162         sink.body();
163         for ( Block block : blocks )
164         {
165             block.traverse( sink );
166         }
167         sink.body_();
168         sink.flush();
169         sink.close();
170 
171         setSecondParsing( false );
172         init();
173     }
174 
175     /**
176      * Guess a title for the page. It uses the first section that it finds.
177      * If it doesn't find any section tries to get it from
178      * {@link ByLineReaderSource#getName()}
179      *
180      * @param blocks blocks to parse
181      * @param source source to parse
182      * @return a title for a page
183      * @since 1.1
184      */
185     public final String getTitle( final List<Block> blocks, final ByLineSource source )
186     {
187         String title = null;
188 
189         for ( Block block : blocks )
190         {
191             if ( block instanceof SectionBlock )
192             {
193                 final SectionBlock sectionBlock = (SectionBlock) block;
194                 title = sectionBlock.getTitle();
195                 break;
196             }
197         }
198 
199         if ( title == null )
200         {
201             String name = source.getName();
202             if ( name != null )
203             {
204                 name = name.trim();
205 
206                 if ( name.length() != 0 )
207                 {
208                     if ( name.endsWith( ".twiki" ) )
209                     {
210                         title = name.substring( 0, name.length() - EXTENSION_LENGTH );
211                     }
212                     else
213                     {
214                         title = name;
215                     }
216                 }
217             }
218         }
219 
220         return title;
221     }
222 
223     /** {@inheritDoc} */
224     protected void init()
225     {
226         super.init();
227 
228         paraParser.setSectionParser( sectionParser );
229         paraParser.setListParser( listParser );
230         paraParser.setTextParser( formatTextParser );
231         paraParser.setHrulerParser( hrulerParser );
232         paraParser.setTableBlockParser( tableParser );
233         paraParser.setVerbatimParser( verbatimParser );
234         sectionParser.setParaParser( paraParser );
235         sectionParser.setHrulerParser( hrulerParser );
236         sectionParser.setVerbatimBlockParser( verbatimParser );
237         listParser.setTextParser( formatTextParser );
238         formatTextParser.setTextParser( textParser );
239         tableParser.setTextParser( formatTextParser );
240 
241         this.parsers = new BlockParser[] { sectionParser, hrulerParser, verbatimParser, paraParser };
242     }
243 }