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 1726913 2016-01-26 22:01:54Z rfscholte $
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     @Override
135     public void parse( Reader source, Sink sink )
136         throws ParseException
137     {
138         parse( source, sink, "" );
139     }
140     
141     @Override
142     public final synchronized void parse( final Reader source, final Sink sink, String reference )
143         throws ParseException
144     {
145         init();
146 
147         List<Block> blocks;
148         final ByLineSource src = new ByLineReaderSource( source, reference );
149 
150         try
151         {
152             blocks = parse( src );
153         }
154         catch ( final Exception e )
155         {
156             // TODO handle column number
157             throw new ParseException( e, src.getName(), src.getLineNumber(), -1 );
158         }
159 
160         sink.head();
161 
162         final String title = getTitle( blocks, src );
163         if ( title != null )
164         {
165             sink.title();
166             sink.text( title );
167             sink.title_();
168         }
169 
170         sink.head_();
171         sink.body();
172         for ( Block block : blocks )
173         {
174             block.traverse( sink );
175         }
176         sink.body_();
177         sink.flush();
178         sink.close();
179 
180         setSecondParsing( false );
181         init();
182     }
183 
184     /**
185      * Guess a title for the page. It uses the first section that it finds.
186      * If it doesn't find any section tries to get it from
187      * {@link ByLineReaderSource#getName()}
188      *
189      * @param blocks blocks to parse
190      * @param source source to parse
191      * @return a title for a page
192      * @since 1.1
193      */
194     public final String getTitle( final List<Block> blocks, final ByLineSource source )
195     {
196         String title = null;
197 
198         for ( Block block : blocks )
199         {
200             if ( block instanceof SectionBlock )
201             {
202                 final SectionBlock sectionBlock = (SectionBlock) block;
203                 title = sectionBlock.getTitle();
204                 break;
205             }
206         }
207 
208         if ( title == null )
209         {
210             String name = source.getName();
211             if ( name != null )
212             {
213                 name = name.trim();
214 
215                 if ( name.length() != 0 )
216                 {
217                     if ( name.endsWith( ".twiki" ) )
218                     {
219                         title = name.substring( 0, name.length() - EXTENSION_LENGTH );
220                     }
221                     else
222                     {
223                         title = name;
224                     }
225                 }
226             }
227         }
228 
229         return title;
230     }
231 
232     /** {@inheritDoc} */
233     protected void init()
234     {
235         super.init();
236 
237         paraParser.setSectionParser( sectionParser );
238         paraParser.setListParser( listParser );
239         paraParser.setTextParser( formatTextParser );
240         paraParser.setHrulerParser( hrulerParser );
241         paraParser.setTableBlockParser( tableParser );
242         paraParser.setVerbatimParser( verbatimParser );
243         sectionParser.setParaParser( paraParser );
244         sectionParser.setHrulerParser( hrulerParser );
245         sectionParser.setVerbatimBlockParser( verbatimParser );
246         listParser.setTextParser( formatTextParser );
247         formatTextParser.setTextParser( textParser );
248         tableParser.setTextParser( formatTextParser );
249 
250         this.parsers = new BlockParser[] { sectionParser, hrulerParser, verbatimParser, paraParser };
251     }
252 }