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$ 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 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}