blob: 8e90cf67d907ddf0118a68a48d184c0dcb0d6722 [file] [log] [blame]
package org.apache.maven.doxia.module.twiki;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.doxia.module.twiki.parser.Block;
import org.apache.maven.doxia.module.twiki.parser.BlockParser;
import org.apache.maven.doxia.module.twiki.parser.FormatedTextParser;
import org.apache.maven.doxia.module.twiki.parser.GenericListBlockParser;
import org.apache.maven.doxia.module.twiki.parser.HRuleBlockParser;
import org.apache.maven.doxia.module.twiki.parser.ParagraphBlockParser;
import org.apache.maven.doxia.module.twiki.parser.SectionBlock;
import org.apache.maven.doxia.module.twiki.parser.SectionBlockParser;
import org.apache.maven.doxia.module.twiki.parser.TableBlockParser;
import org.apache.maven.doxia.module.twiki.parser.TextParser;
import org.apache.maven.doxia.module.twiki.parser.VerbatimBlockParser;
import org.apache.maven.doxia.module.twiki.parser.XHTMLWikiWordLinkResolver;
import org.apache.maven.doxia.parser.AbstractTextParser;
import org.apache.maven.doxia.parser.ParseException;
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.util.ByLineReaderSource;
import org.apache.maven.doxia.util.ByLineSource;
import org.codehaus.plexus.component.annotations.Component;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* Parse the <a href="http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules">
* twiki file format</a>
*
* @author Juan F. Codagnone
* @version $Id$
* @since 1.0
*/
@Component( role = Parser.class, hint = "twiki" )
public class TWikiParser
extends AbstractTextParser
{
private static final int EXTENSION_LENGTH = 6;
/** paragraph parser. */
private final ParagraphBlockParser paraParser = new ParagraphBlockParser();
/** section parser. */
private final SectionBlockParser sectionParser = new SectionBlockParser();
/** enumeration parser. */
private final GenericListBlockParser listParser = new GenericListBlockParser();
/** Text parser. */
private final FormatedTextParser formatTextParser = new FormatedTextParser();
/**
* text parser.
* This only works for xhtml output, but there is no way
* of transforming a wikiWord in another context.
*/
private final TextParser textParser = new TextParser( new XHTMLWikiWordLinkResolver() );
/** hruler parser. */
private final HRuleBlockParser hrulerParser = new HRuleBlockParser();
/** table parser. */
private final TableBlockParser tableParser = new TableBlockParser();
/** verbatim parser. */
private final VerbatimBlockParser verbatimParser = new VerbatimBlockParser();
/** list of parsers to try to apply to the toplevel */
private BlockParser[] parsers;
/**
* Creates the TWikiParser.
*/
public TWikiParser()
{
init();
}
/**
* <p>parse.</p>
*
* @param source source to parse.
* @return the blocks that represent source.
* @throws org.apache.maven.doxia.parser.ParseException on error.
*/
public final List<Block> parse( final ByLineSource source )
throws ParseException
{
final List<Block> ret = new ArrayList<Block>();
String line;
while ( ( line = source.getNextLine() ) != null )
{
boolean accepted = false;
for ( BlockParser parser : parsers )
{
if ( parser.accept( line ) )
{
accepted = true;
ret.add( parser.visit( line, source ) );
break;
}
}
if ( !accepted )
{
throw new ParseException( "Line number not handle : " + source.getLineNumber() + ": " + line );
}
}
return ret;
}
@Override
public void parse( Reader source, Sink sink )
throws ParseException
{
parse( source, sink, "" );
}
@Override
public final synchronized void parse( final Reader source, final Sink sink, String reference )
throws ParseException
{
init();
List<Block> blocks;
final ByLineSource src = new ByLineReaderSource( source, reference );
try
{
blocks = parse( src );
}
catch ( final Exception e )
{
// TODO handle column number
throw new ParseException( e, src.getName(), src.getLineNumber(), -1 );
}
sink.head();
final String title = getTitle( blocks, src );
if ( title != null )
{
sink.title();
sink.text( title );
sink.title_();
}
sink.head_();
sink.body();
for ( Block block : blocks )
{
block.traverse( sink );
}
sink.body_();
sink.flush();
sink.close();
setSecondParsing( false );
init();
}
/**
* Guess a title for the page. It uses the first section that it finds.
* If it doesn't find any section tries to get it from
* {@link ByLineReaderSource#getName()}
*
* @param blocks blocks to parse
* @param source source to parse
* @return a title for a page
* @since 1.1
*/
public final String getTitle( final List<Block> blocks, final ByLineSource source )
{
String title = null;
for ( Block block : blocks )
{
if ( block instanceof SectionBlock )
{
final SectionBlock sectionBlock = (SectionBlock) block;
title = sectionBlock.getTitle();
break;
}
}
if ( title == null )
{
String name = source.getName();
if ( name != null )
{
name = name.trim();
if ( name.length() != 0 )
{
if ( name.endsWith( ".twiki" ) )
{
title = name.substring( 0, name.length() - EXTENSION_LENGTH );
}
else
{
title = name;
}
}
}
}
return title;
}
/** {@inheritDoc} */
protected void init()
{
super.init();
paraParser.setSectionParser( sectionParser );
paraParser.setListParser( listParser );
paraParser.setTextParser( formatTextParser );
paraParser.setHrulerParser( hrulerParser );
paraParser.setTableBlockParser( tableParser );
paraParser.setVerbatimParser( verbatimParser );
sectionParser.setParaParser( paraParser );
sectionParser.setHrulerParser( hrulerParser );
sectionParser.setVerbatimBlockParser( verbatimParser );
listParser.setTextParser( formatTextParser );
formatTextParser.setTextParser( textParser );
tableParser.setTextParser( formatTextParser );
this.parsers = new BlockParser[] { sectionParser, hrulerParser, verbatimParser, paraParser };
}
}