001package org.apache.maven.doxia.module.confluence.parser.table;
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.StringReader;
023import java.util.ArrayList;
024import java.util.LinkedList;
025import java.util.List;
026
027import org.apache.maven.doxia.module.confluence.ConfluenceMarkup;
028import org.apache.maven.doxia.module.confluence.parser.Block;
029import org.apache.maven.doxia.module.confluence.parser.BlockParser;
030import org.apache.maven.doxia.module.confluence.parser.BoldBlock;
031import org.apache.maven.doxia.module.confluence.parser.FigureBlockParser;
032import org.apache.maven.doxia.module.confluence.parser.ParagraphBlockParser;
033import org.apache.maven.doxia.module.confluence.parser.SectionBlockParser;
034import org.apache.maven.doxia.module.confluence.parser.list.ListBlockParser;
035import org.apache.maven.doxia.parser.ParseException;
036import org.apache.maven.doxia.util.ByLineReaderSource;
037import org.apache.maven.doxia.util.ByLineSource;
038import org.codehaus.plexus.util.StringUtils;
039
040/**
041 * Parse tables
042 * 
043 * @author Juan F. Codagnone
044 * @version $Id: TableBlockParser.html 979316 2016-02-02 21:51:43Z hboutemy $
045 */
046public class TableBlockParser
047    implements BlockParser
048{
049    private static final String EMPTY_STRING = "";
050
051    private static final String ANY_CHARACTER = ".*";
052
053    private static final String ESCAPE_CHARACTER = "\\";
054
055    private BlockParser[] parsers;
056
057    /**
058     * Default constructor TableBlockParser.
059     */
060    public TableBlockParser()
061    {
062        BlockParser headingParser = new SectionBlockParser();
063        BlockParser figureParser = new FigureBlockParser();
064        BlockParser listParser = new ListBlockParser();
065
066        BlockParser[] subparsers = new BlockParser[] { headingParser, figureParser, listParser };
067        BlockParser paragraphParser = new ParagraphBlockParser( subparsers );
068
069        this.parsers = new BlockParser[] { headingParser, figureParser, listParser, paragraphParser };
070
071    }
072
073    /** {@inheritDoc} */
074    public boolean accept( String line, ByLineSource source )
075    {
076        return line.startsWith( "|" );
077    }
078
079    /** {@inheritDoc} */
080    public Block visit( String line, ByLineSource source )
081        throws ParseException
082    {
083        if ( !accept( line, source ) )
084        {
085            throw new IllegalAccessError( "call accept before this ;)" );
086        }
087
088        List<Block> rows = new ArrayList<Block>();
089
090        String l = line;
091
092        do
093        {
094            l = l.substring( 0, l.lastIndexOf( "|" ) );
095
096            List<Block> cells = new ArrayList<Block>();
097
098            if ( l.startsWith( "||" ) )
099            {
100                String[] text = StringUtils.split( l, "||" );
101
102                for ( int i = 0; i < text.length; i++ )
103                {
104                    List<Block> textBlocks = new ArrayList<Block>();
105
106                    textBlocks.add( parseLine( text[i], new ByLineReaderSource( new StringReader( EMPTY_STRING ) ) ) );
107
108                    List<Block> blocks = new ArrayList<Block>();
109
110                    blocks.add( new BoldBlock( textBlocks ) );
111
112                    cells.add( new TableCellHeaderBlock( blocks ) );
113                }
114            }
115            else
116            {
117                int it = 0;
118                String[] text = StringUtils.split( l, "|" );
119                List<String> texts = new LinkedList<String>();
120
121                while ( it < text.length )
122                {
123                    if ( text[it].matches( ANY_CHARACTER + ESCAPE_CHARACTER + ConfluenceMarkup.LINK_START_MARKUP
124                        + ANY_CHARACTER )
125                        && !text[it].matches( ANY_CHARACTER + ESCAPE_CHARACTER + ConfluenceMarkup.LINK_END_MARKUP
126                            + ANY_CHARACTER ) )
127                    {
128                        texts.add( text[it] + ConfluenceMarkup.TABLE_CELL_MARKUP + text[it + 1] );
129                        it += 2;
130                        continue;
131                    }
132                    texts.add( text[it] );
133                    it++;
134                }
135
136                for ( String pText : texts )
137                {
138                    List<Block> blocks = new ArrayList<Block>();
139
140                    blocks.add( parseLine( pText, new ByLineReaderSource( new StringReader( EMPTY_STRING ) ) ) );
141
142                    cells.add( new TableCellBlock( blocks ) );
143                }
144            }
145
146            rows.add( new TableRowBlock( cells ) );
147        }
148        while ( ( l = source.getNextLine() ) != null && accept( l, source ) );
149
150        assert rows.size() >= 1;
151
152        return new TableBlock( rows );
153    }
154
155    private Block parseLine( String text, ByLineSource source )
156        throws ParseException
157    {
158        if ( text.length() > 0 )
159        {
160            for ( BlockParser parser : parsers )
161            {
162                if ( parser.accept( text, source ) )
163                {
164                    if ( parser instanceof ParagraphBlockParser )
165                    {
166                        return ( (ParagraphBlockParser) parser ).visit( text, source, false );
167                    }
168                    else
169                    {
170                        return parser.visit( text, source );
171                    }
172                }
173            }
174        }
175        return null;
176    }
177}