View Javadoc
1   package org.apache.maven.doxia.module.confluence.parser.table;
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 java.io.StringReader;
23  import java.util.ArrayList;
24  import java.util.LinkedList;
25  import java.util.List;
26  
27  import org.apache.maven.doxia.module.confluence.ConfluenceMarkup;
28  import org.apache.maven.doxia.module.confluence.parser.Block;
29  import org.apache.maven.doxia.module.confluence.parser.BlockParser;
30  import org.apache.maven.doxia.module.confluence.parser.BoldBlock;
31  import org.apache.maven.doxia.module.confluence.parser.FigureBlockParser;
32  import org.apache.maven.doxia.module.confluence.parser.ParagraphBlockParser;
33  import org.apache.maven.doxia.module.confluence.parser.SectionBlockParser;
34  import org.apache.maven.doxia.module.confluence.parser.list.ListBlockParser;
35  import org.apache.maven.doxia.parser.ParseException;
36  import org.apache.maven.doxia.util.ByLineReaderSource;
37  import org.apache.maven.doxia.util.ByLineSource;
38  import org.codehaus.plexus.util.StringUtils;
39  
40  /**
41   * Parse tables
42   * 
43   * @author Juan F. Codagnone
44   * @version $Id: TableBlockParser.java 1509970 2013-08-03 12:27:37Z rfscholte $
45   */
46  public class TableBlockParser
47      implements BlockParser
48  {
49      private static final String EMPTY_STRING = "";
50  
51      private static final String ANY_CHARACTER = ".*";
52  
53      private static final String ESCAPE_CHARACTER = "\\";
54  
55      private BlockParser[] parsers;
56  
57      /**
58       * Default constructor TableBlockParser.
59       */
60      public TableBlockParser()
61      {
62          BlockParser headingParser = new SectionBlockParser();
63          BlockParser figureParser = new FigureBlockParser();
64          BlockParser listParser = new ListBlockParser();
65  
66          BlockParser[] subparsers = new BlockParser[] { headingParser, figureParser, listParser };
67          BlockParser paragraphParser = new ParagraphBlockParser( subparsers );
68  
69          this.parsers = new BlockParser[] { headingParser, figureParser, listParser, paragraphParser };
70  
71      }
72  
73      /** {@inheritDoc} */
74      public boolean accept( String line, ByLineSource source )
75      {
76          return line.startsWith( "|" );
77      }
78  
79      /** {@inheritDoc} */
80      public Block visit( String line, ByLineSource source )
81          throws ParseException
82      {
83          if ( !accept( line, source ) )
84          {
85              throw new IllegalAccessError( "call accept before this ;)" );
86          }
87  
88          List<Block> rows = new ArrayList<Block>();
89  
90          String l = line;
91  
92          do
93          {
94              l = l.substring( 0, l.lastIndexOf( "|" ) );
95  
96              List<Block> cells = new ArrayList<Block>();
97  
98              if ( l.startsWith( "||" ) )
99              {
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                 String[] pText = texts.toArray( new String[0] );
137                 for ( int i = 0; i < pText.length; i++ )
138                 {
139                     List<Block> blocks = new ArrayList<Block>();
140 
141                     blocks.add( parseLine( pText[i], new ByLineReaderSource( new StringReader( EMPTY_STRING ) ) ) );
142 
143                     cells.add( new TableCellBlock( blocks ) );
144                 }
145             }
146 
147             rows.add( new TableRowBlock( cells ) );
148         }
149 
150         while ( ( l = source.getNextLine() ) != null && accept( l, source ) );
151 
152         assert rows.size() >= 1;
153 
154         return new TableBlock( rows );
155     }
156 
157     private Block parseLine( String text, ByLineSource source )
158         throws ParseException
159     {
160         if ( text.trim().length() > 0 )
161         {
162             for ( BlockParser parser : parsers )
163             {
164                 if ( parser.accept( text, source ) )
165                 {
166                     if ( parser instanceof ParagraphBlockParser )
167                     {
168                         return ( (ParagraphBlockParser) parser ).visit( text, source, false );
169                     }
170                     else
171                     {
172                         return parser.visit( text, source );
173                     }
174                 }
175             }
176         }
177         return null;
178     }
179 }