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