001package org.apache.maven.doxia.module.confluence;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.Reader;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.maven.doxia.module.confluence.parser.Block;
027import org.apache.maven.doxia.module.confluence.parser.BlockParser;
028import org.apache.maven.doxia.module.confluence.parser.DefinitionListBlockParser;
029import org.apache.maven.doxia.module.confluence.parser.FigureBlockParser;
030import org.apache.maven.doxia.module.confluence.parser.HorizontalRuleBlockParser;
031import org.apache.maven.doxia.module.confluence.parser.ParagraphBlockParser;
032import org.apache.maven.doxia.module.confluence.parser.SectionBlockParser;
033import org.apache.maven.doxia.module.confluence.parser.VerbatimBlockParser;
034import org.apache.maven.doxia.module.confluence.parser.list.ListBlockParser;
035import org.apache.maven.doxia.module.confluence.parser.table.TableBlockParser;
036import org.apache.maven.doxia.parser.AbstractTextParser;
037import org.apache.maven.doxia.parser.ParseException;
038import org.apache.maven.doxia.parser.Parser;
039import org.apache.maven.doxia.sink.Sink;
040import org.apache.maven.doxia.util.ByLineReaderSource;
041import org.apache.maven.doxia.util.ByLineSource;
042import org.codehaus.plexus.component.annotations.Component;
043
044/**
045 * Parse the <a href="http://www.atlassian.com/software/confluence/">Confluence</a>.
046 * See <a href="http://confluence.atlassian.com/display/CONF25/Confluence+Notation+Guide+Overview">
047 * Confluence Notation Guide Overview</a>
048 *
049 * @since 1.0
050 */
051@Component( role = Parser.class, hint = "confluence" )
052public class ConfluenceParser
053    extends AbstractTextParser
054{
055    private BlockParser[] parsers;
056
057    /**
058     * <p>Constructor for ConfluenceParser.</p>
059     */
060    public ConfluenceParser()
061    {
062        init();
063    }
064
065    private List<Block> parse( ByLineSource source )
066        throws ParseException
067    {
068        init();
069
070        List<Block> blocks = new ArrayList<>();
071
072        String line;
073
074        while ( ( line = source.getNextLine() ) != null )
075        {
076            //boolean accepted = false;
077
078            for ( BlockParser parser : parsers )
079            {
080                if ( line.trim().length() == 0 )
081                {
082                    continue;
083                }
084
085                if ( parser.accept( line, source ) )
086                {
087                    //accepted = true;
088
089                    blocks.add( parser.visit( line, source ) );
090
091                    break;
092                }
093            }
094
095/*
096            if ( !accepted )
097            {
098                throw new ParseException( "don't know how to handle line: " + source.getLineNumber() + ": " + line );
099            }
100*/
101        }
102
103        return blocks;
104    }
105
106    /** {@inheritDoc} */
107    @Override
108    public void parse( Reader source, Sink sink )
109        throws ParseException
110    {
111        parse( source, sink, "" );
112    }
113
114    /** {@inheritDoc} */
115    @Override
116    public synchronized void parse( Reader source, Sink sink, String reference )
117        throws ParseException
118    {
119        ByLineSource src = new ByLineReaderSource( source, reference );
120
121        try
122        {
123            List<Block> blocks = parse( src );
124
125            sink.head();
126
127            sink.head_();
128
129            sink.body();
130
131            for ( Block block : blocks )
132            {
133                block.traverse( sink );
134            }
135
136            sink.body_();
137        }
138        catch ( Exception e )
139        {
140            // TODO handle column number
141            throw new ParseException( e, src.getName(), src.getLineNumber(), -1 );
142        }
143        finally
144        {
145            setSecondParsing( false );
146            init();
147        }
148    }
149
150    /**
151     * {@inheritDoc}
152     */
153    protected void init()
154    {
155        super.init();
156
157        BlockParser headingParser = new SectionBlockParser();
158        BlockParser figureParser = new FigureBlockParser();
159        BlockParser verbatimParser = new VerbatimBlockParser();
160        BlockParser definitionParser = new DefinitionListBlockParser();
161        BlockParser horizontalRuleParser = new HorizontalRuleBlockParser();
162        BlockParser listParser = new ListBlockParser();
163        BlockParser tableParser = new TableBlockParser();
164
165        BlockParser[] subparsers =
166                new BlockParser[] { headingParser, figureParser, listParser, tableParser, verbatimParser };
167        BlockParser paragraphParser = new ParagraphBlockParser( subparsers );
168
169        this.parsers =
170            new BlockParser[] { headingParser, figureParser, verbatimParser, definitionParser, horizontalRuleParser,
171                listParser, tableParser, paragraphParser };
172    }
173}