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.Arrays; 024import java.util.List; 025import java.util.regex.Matcher; 026import java.util.regex.Pattern; 027 028import org.apache.maven.doxia.util.ByLineSource; 029import org.apache.maven.doxia.parser.ParseException; 030 031/** 032 * Parse paragraphs. 033 * 034 * @author Juan F. Codagnone 035 * @version $Id$ 036 */ 037public class ParagraphBlockParser 038 implements BlockParser 039{ 040 /** 041 * pattern used to dectect end of paragraph 042 */ 043 private final Pattern paragraphSeparator = Pattern.compile( "^(\\s*)$" ); 044 045 /** 046 * {@link SectionBlockParser} to use. injected 047 */ 048 private SectionBlockParser sectionParser; 049 050 /** 051 * {@link ListBlockParser} to use. injected 052 */ 053 private GenericListBlockParser listParser; 054 055 /** 056 * {@link FormatedTextParser} to use. injected 057 */ 058 private FormatedTextParser textParser; 059 060 /** 061 * {@link HRuleBlockParser} to use. injected 062 */ 063 private HRuleBlockParser hrulerParser; 064 065 /** 066 * {@link TableBlockParser} to use. injected 067 */ 068 private TableBlockParser tableBlockParser; 069 070 /** 071 * {@link TableBlockParser} to use. injected 072 */ 073 private VerbatimBlockParser verbatimParser; 074 075 /** 076 * no operation block 077 */ 078 private static final NopBlock NOP = new NopBlock(); 079 080 /** {@inheritDoc} */ 081 public final boolean accept( final String line ) 082 { 083 return !sectionParser.accept( line ) && !hrulerParser.accept( line ) && !verbatimParser.accept( line ); 084 } 085 086 /** 087 * {@inheritDoc} 088 */ 089 public final Block visit( final String line, final ByLineSource source ) 090 throws ParseException 091 { 092 StringBuilder sb = new StringBuilder(); 093 List<Block> childs = new ArrayList<Block>(); 094 095 boolean sawText = false; 096 097 /* 098 * 1. Skip begininig new lines 099 * 2. Get the text, while \n\n is not found 100 */ 101 boolean pre = false; 102 String l = line; 103 do 104 { 105 Matcher m = paragraphSeparator.matcher( l ); 106 107 if ( m.lookingAt() ) 108 { 109 if ( sawText ) 110 { 111 break; 112 } 113 } 114 else 115 { 116 sawText = true; 117 118 /* be able to parse lists / enumerations */ 119 if ( listParser.accept( l ) ) 120 { 121 if ( sb.length() != 0 ) 122 { 123 childs.addAll( Arrays.asList( textParser.parse( sb.toString().trim() ) ) ); 124 sb = new StringBuilder(); 125 } 126 childs.add( listParser.visit( l, source ) ); 127 } 128 else if ( tableBlockParser.accept( l ) ) 129 { 130 childs.add( tableBlockParser.visit( l, source ) ); 131 } 132 else 133 { 134 sb.append( l ); 135 // specific 136 if ( l.indexOf( "<pre>" ) != -1 ) 137 { 138 pre = true; 139 } 140 if ( l.indexOf( "</pre>" ) != -1 ) 141 { 142 pre = false; 143 } 144 145 if ( !pre ) 146 { 147 sb.append( " " ); 148 } 149 else 150 { 151 // TODO use EOL 152 sb.append( "\n" ); 153 } 154 } 155 } 156 l = source.getNextLine(); 157 } 158 while ( l != null && accept( l ) ); 159 160 if ( line != null ) 161 { 162 source.ungetLine(); 163 } 164 165 if ( sb.length() != 0 ) 166 { 167 childs.addAll( Arrays.asList( textParser.parse( sb.toString().trim() ) ) ); 168 sb = new StringBuilder(); 169 } 170 171 if ( childs.size() == 0 ) 172 { 173 return NOP; 174 } 175 176 return new ParagraphBlock( childs.toArray( new Block[] {} ) ); 177 } 178 179 /** 180 * Sets the sectionParser. 181 * 182 * @param aSectionParser <code>SectionBlockParser</code> with the sectionParser. 183 */ 184 public final void setSectionParser( final SectionBlockParser aSectionParser ) 185 { 186 if ( aSectionParser == null ) 187 { 188 throw new IllegalArgumentException( "arg can't be null" ); 189 } 190 this.sectionParser = aSectionParser; 191 } 192 193 /** 194 * Sets the listParser. 195 * 196 * @param aListParser <code>ListBlockParser</code> with the listParser. 197 */ 198 public final void setListParser( final GenericListBlockParser aListParser ) 199 { 200 if ( aListParser == null ) 201 { 202 throw new IllegalArgumentException( "arg can't be null" ); 203 } 204 205 this.listParser = aListParser; 206 } 207 208 /** 209 * Sets the formatTextParser. 210 * 211 * @param aTextParser <code>FormatedTextParser</code> 212 * with the formatTextParser. 213 */ 214 public final void setTextParser( final FormatedTextParser aTextParser ) 215 { 216 if ( aTextParser == null ) 217 { 218 throw new IllegalArgumentException( "arg can't be null" ); 219 } 220 this.textParser = aTextParser; 221 } 222 223 /** 224 * Sets the hrulerParser. 225 * 226 * @param aHrulerParser <code>HRuleBlockParser</code> with the hrulerParser. 227 */ 228 public final void setHrulerParser( final HRuleBlockParser aHrulerParser ) 229 { 230 if ( aHrulerParser == null ) 231 { 232 throw new IllegalArgumentException( "arg can't be null" ); 233 } 234 235 this.hrulerParser = aHrulerParser; 236 } 237 238 /** 239 * <p>Setter for the field <code>tableBlockParser</code>.</p> 240 * 241 * @param aTableBlockParser Table parser to use 242 */ 243 public final void setTableBlockParser( final TableBlockParser aTableBlockParser ) 244 { 245 if ( aTableBlockParser == null ) 246 { 247 throw new IllegalArgumentException( "arg can't be null" ); 248 } 249 250 this.tableBlockParser = aTableBlockParser; 251 } 252 253 /** 254 * Sets the verbatimParser. 255 * 256 * @param aVerbatimParser <code>VerbatimBlockParser</code> with the verbatimParser. 257 * @since 1.1 258 */ 259 public final void setVerbatimParser( final VerbatimBlockParser aVerbatimParser ) 260 { 261 if ( aVerbatimParser == null ) 262 { 263 throw new IllegalArgumentException( "arg can't be null" ); 264 } 265 this.verbatimParser = aVerbatimParser; 266 } 267}