001package org.apache.maven.doxia.module.twiki.parser;
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.util.ArrayList;
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025
026import org.apache.maven.doxia.util.ByLineSource;
027import org.apache.maven.doxia.parser.ParseException;
028
029/**
030 * Parse looking for sections
031 *
032 * @author Juan F. Codagnone
033 * @version $Id$
034 */
035public class SectionBlockParser
036    implements BlockParser
037{
038    /**
039     * '---++ Header', '---## Header'
040     */
041    private static final Pattern HEADER_DA = Pattern.compile( "^---([+]+)\\s*(.+)\\s*$" );
042
043    /**
044     * {@link ParagraphBlockParser} to use. injected
045     */
046    private ParagraphBlockParser paraParser;
047
048    /**
049     * {@link ParagraphBlockParser} to use. injected
050     */
051    private HRuleBlockParser hrulerParser;
052
053    /** {@link VerbatimBlockParser} */
054    private VerbatimBlockParser verbatimBlockParser;
055
056    /**
057     * {@inheritDoc}
058     */
059    public final boolean accept( final String line )
060    {
061        return HEADER_DA.matcher( line ).lookingAt();
062    }
063
064    /**
065     * {@inheritDoc}
066     */
067    public final Block visit( final String line, final ByLineSource source )
068        throws ParseException
069    {
070        final Matcher m = HEADER_DA.matcher( line );
071
072        if ( !m.lookingAt() )
073        {
074            throw new IllegalArgumentException( "don't know how to handle: " + line );
075        }
076
077        String newLine;
078        final ArrayList<Block> blocks = new ArrayList<Block>();
079
080        while ( ( newLine = source.getNextLine() ) != null && !accept( newLine ) )
081        {
082            if ( hrulerParser.accept( newLine ) )
083            {
084                blocks.add( hrulerParser.visit( newLine, source ) );
085            }
086            else
087            {
088                if ( verbatimBlockParser.accept( newLine ) )
089                {
090                    blocks.add( verbatimBlockParser.visit( newLine, source ) );
091                }
092                else
093                {
094                    blocks.add( paraParser.visit( newLine, source ) );
095                }
096            }
097        }
098
099        if ( newLine != null )
100        {
101            source.ungetLine();
102        }
103
104        return new SectionBlock( m.group( 2 ), getLevel( m.group( 1 ) ), blocks.toArray( new Block[] {} ) );
105    }
106
107    /**
108     * @param s "++"
109     * @return tha level of the section
110     * @throws IllegalArgumentException on error
111     */
112    static int getLevel( final String s )
113        throws IllegalArgumentException
114    {
115        for ( int i = 0, n = s.length(); i < n; i++ )
116        {
117            if ( s.charAt( i ) != '+' )
118            {
119                throw new IllegalArgumentException( "the argument must have only" + " '+' characters" );
120            }
121        }
122        return s.length();
123    }
124
125    /**
126     * Sets the paraParser.
127     *
128     * @param paraParser <code>ParagraphBlockParser</code> with the paraParser.
129     */
130    public final void setParaParser( final ParagraphBlockParser paraParser )
131    {
132        if ( paraParser == null )
133        {
134            throw new IllegalArgumentException( "argument can't be null" );
135        }
136        this.paraParser = paraParser;
137    }
138
139    /**
140     * Sets the hrulerParser.
141     *
142     * @param hrulerParser <code>HRuleBlockParser</code> with the hrulerParser.
143     */
144    public final void setHrulerParser( final HRuleBlockParser hrulerParser )
145    {
146        if ( hrulerParser == null )
147        {
148            throw new IllegalArgumentException( "argument can't be null" );
149        }
150        this.hrulerParser = hrulerParser;
151    }
152
153    /**
154     * Sets the verbatimBlockParser.
155     *
156     * @param verbatimBlockParser <code>VerbatimBlockParser</code> with the verbatimBlockParser.
157     * @since 1.1
158     */
159    public final void setVerbatimBlockParser( VerbatimBlockParser verbatimBlockParser )
160    {
161        if ( verbatimBlockParser == null )
162        {
163            throw new IllegalArgumentException( "argument can't be null" );
164        }
165        this.verbatimBlockParser = verbatimBlockParser;
166    }
167}