001package org.apache.maven.doxia.module.fo; 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.File; 023import java.io.StringReader; 024import java.io.Writer; 025 026import org.apache.maven.doxia.document.DocumentMeta; 027import org.apache.maven.doxia.document.DocumentModel; 028import org.apache.maven.doxia.document.DocumentTOC; 029import org.apache.maven.doxia.document.DocumentTOCItem; 030import org.apache.maven.doxia.parser.XhtmlBaseParser; 031import org.apache.maven.doxia.sink.Sink; 032import org.apache.maven.doxia.sink.impl.AbstractSinkTest; 033import org.apache.maven.doxia.sink.impl.SinkTestDocument; 034 035/** 036 * <code>FO Sink</code> Test case. 037 * 038 * @version $Id$ 039 */ 040public class FoSinkTest 041 extends AbstractSinkTest 042{ 043 private FoConfiguration config; 044 045 // ---------------------------------------------------------------------- 046 // Specific test methods 047 // ---------------------------------------------------------------------- 048 049 @Override 050 protected String wrapXml( String xmlFragment ) 051 { 052 return "<fo:fo xmlns:fo=\"" + FoMarkup.FO_NAMESPACE + "\">" + xmlFragment + "</fo:fo>"; 053 } 054 055 /** 056 * Uses fop to generate a pdf from a test document. 057 * @throws Exception If the conversion fails. 058 */ 059 public void testConvertFO2PDF() 060 throws Exception 061 { 062 String fileName = "test"; 063 // first create fo 064 FoSink fosink = new FoSink( getTestWriter( fileName ) ); 065 fosink.beginDocument(); 066 SinkTestDocument.generate( fosink ); 067 fosink.endDocument(); 068 fosink.close(); 069 070 // then generate PDF 071 fo2pdf( fileName ); 072 } 073 074 /** 075 * Uses fop to generate an aggregated pdf from two test documents. 076 * @throws Exception If the conversion fails. 077 */ 078 public void testAggregateMode() 079 throws Exception 080 { 081 FoAggregateSink fosink = new FoAggregateSink( getTestWriter( "aggregate" ) ); 082 083 fosink.setDocumentModel( getModel() ); 084 085 fosink.beginDocument(); 086 087 fosink.coverPage(); 088 089 fosink.toc(); 090 091 fosink.setDocumentName( "doc1" ); 092 fosink.setDocumentTitle( "Document 1" ); 093 SinkTestDocument.generate( fosink ); 094 095 // re-use the same source 096 fosink.setDocumentName( "doc2" ); 097 fosink.setDocumentTitle( "Document 2" ); 098 SinkTestDocument.generate( fosink ); 099 100 fosink.endDocument(); 101 102 // then generate PDF 103 fo2pdf( "aggregate" ); 104 } 105 106 private DocumentModel getModel() 107 { 108 DocumentModel model = new DocumentModel(); 109 model.setToc( getToc() ); 110 model.setMeta( getMeta() ); 111 return model; 112 } 113 114 private DocumentMeta getMeta() 115 { 116 DocumentMeta meta = new DocumentMeta(); 117 meta.setAuthor( "The Apache Maven Project" ); 118 meta.setTitle( "Doxia FO Sink" ); 119 return meta; 120 } 121 122 private DocumentTOC getToc() 123 { 124 DocumentTOCItem item1 = new DocumentTOCItem(); 125 item1.setName( "First document" ); 126 item1.setRef( "doc1.apt" ); 127 128 DocumentTOCItem item2 = new DocumentTOCItem(); 129 item2.setName( "Second document" ); 130 item2.setRef( "doc2.xml" ); 131 132 DocumentTOC toc = new DocumentTOC(); 133 toc.setName( "What's in here" ); 134 toc.addItem( item1 ); 135 toc.addItem( item2 ); 136 137 return toc; 138 } 139 140 // ---------------------------------------------------------------------- 141 // Abstract methods the individual SinkTests must provide 142 // ---------------------------------------------------------------------- 143 144 /** {@inheritDoc} */ 145 protected String outputExtension() 146 { 147 return "fo"; 148 } 149 150 /** {@inheritDoc} */ 151 protected Sink createSink( Writer writer ) 152 { 153 return new FoSink( writer ); 154 } 155 156 /** {@inheritDoc} */ 157 protected boolean isXmlSink() 158 { 159 return true; 160 } 161 162 /** {@inheritDoc} */ 163 protected String getTitleBlock( String title ) 164 { 165 String attribs = getConfig().getAttributeString( "doc.header.title" ); 166 return EOL + "<fo:block" + attribs + ">" + title + "</fo:block>" + EOL; 167 } 168 169 /** {@inheritDoc} */ 170 protected String getAuthorBlock( String author ) 171 { 172 String attribs = getConfig().getAttributeString( "doc.header.author" ); 173 return EOL + "<fo:block" + attribs + ">" + author + "</fo:block>" + EOL; 174 } 175 176 /** {@inheritDoc} */ 177 protected String getDateBlock( String date ) 178 { 179 String attribs = getConfig().getAttributeString( "doc.header.date" ); 180 return EOL + "<fo:block" + attribs + ">" + date + "</fo:block>" + EOL; 181 } 182 183 // TODO 184 protected String getHeadBlock() 185 { 186 return ""; 187 } 188 189 // TODO: remove 190 public void testHead() 191 { 192 String expected = ""; 193 assertEquals( "Wrong head!", expected, getHeadBlock() ); 194 } 195 196 /** {@inheritDoc} */ 197 protected String getBodyBlock() 198 { 199 return EOL + "</fo:flow>" + EOL + "</fo:page-sequence>" + EOL + "</fo:root>" + EOL; 200 } 201 202 /** {@inheritDoc} */ 203 protected String getSectionTitleBlock( String title ) 204 { 205 return title; 206 } 207 208 /** {@inheritDoc} */ 209 protected String getSection1Block( String title ) 210 { 211 String attribs = getConfig().getAttributeString( "body.text" ); 212 String attrib2 = getConfig().getAttributeString( "body.h1" ); 213 return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">1 " + title 214 + "</fo:block>" + EOL + "</fo:block>" + EOL; 215 } 216 217 /** {@inheritDoc} */ 218 protected String getSection2Block( String title ) 219 { 220 String attribs = getConfig().getAttributeString( "body.text" ); 221 String attrib2 = getConfig().getAttributeString( "body.h2" ); 222 return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">0.1 " + title 223 + "</fo:block>" + EOL + "</fo:block>" + EOL; 224 } 225 226 /** {@inheritDoc} */ 227 protected String getSection3Block( String title ) 228 { 229 String attribs = getConfig().getAttributeString( "body.text" ); 230 String attrib2 = getConfig().getAttributeString( "body.h3" ); 231 return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">0.0.1 " + title 232 + "</fo:block>" + EOL + "</fo:block>" + EOL; 233 } 234 235 /** {@inheritDoc} */ 236 protected String getSection4Block( String title ) 237 { 238 String attribs = getConfig().getAttributeString( "body.text" ); 239 String attrib2 = getConfig().getAttributeString( "body.h4" ); 240 return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">" + title 241 + "</fo:block>" + EOL + "</fo:block>" + EOL; 242 } 243 244 /** {@inheritDoc} */ 245 protected String getSection5Block( String title ) 246 { 247 String attribs = getConfig().getAttributeString( "body.text" ); 248 String attrib2 = getConfig().getAttributeString( "body.h5" ); 249 return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">" + title 250 + "</fo:block>" + EOL + "</fo:block>" + EOL; 251 } 252 253 /** {@inheritDoc} */ 254 protected String getListBlock( String item ) 255 { 256 String attribs = getConfig().getAttributeString( "list" ); 257 String itemAttribs = getConfig().getAttributeString( "list.item" ); 258 return EOL + EOL + "<fo:list-block" + attribs + ">" + EOL + "<fo:list-item" + itemAttribs 259 + "><fo:list-item-label><fo:block>•</fo:block></fo:list-item-label>" + EOL + EOL 260 + "<fo:list-item-body" + itemAttribs + ">" + EOL + "<fo:block>" + item + "</fo:block>" + EOL 261 + "</fo:list-item-body>" + EOL + "</fo:list-item>" + EOL + "</fo:list-block>" + EOL; 262 } 263 264 /** {@inheritDoc} */ 265 protected String getNumberedListBlock( String item ) 266 { 267 String attribs = getConfig().getAttributeString( "list" ); 268 String itemAttribs = getConfig().getAttributeString( "list.item" ); 269 return EOL + EOL + "<fo:list-block" + attribs + ">" + EOL + "<fo:list-item" + itemAttribs + ">" + EOL 270 + "<fo:list-item-label>" + EOL + "<fo:block>i.</fo:block>" + EOL + "</fo:list-item-label>" + EOL + EOL 271 + "<fo:list-item-body" + itemAttribs + ">" + EOL + "<fo:block>" + item + "</fo:block>" + EOL 272 + "</fo:list-item-body>" + EOL + "</fo:list-item>" + EOL + "</fo:list-block>" + EOL; 273 } 274 275 /** {@inheritDoc} */ 276 protected String getDefinitionListBlock( String definum, String definition ) 277 { 278 String dlAtts = getConfig().getAttributeString( "dl" ); 279 String dtAtts = getConfig().getAttributeString( "dt" ); 280 String ddAtts = getConfig().getAttributeString( "dd" ); 281 return EOL + EOL + "<fo:block" + dlAtts + ">" + EOL + "<fo:block" + dtAtts + ">" + definum + "</fo:block>" 282 + EOL + EOL + EOL + "<fo:block" + ddAtts + ">" + definition + "</fo:block>" + EOL + "</fo:block>" 283 + EOL; 284 } 285 286 /** {@inheritDoc} */ 287 protected String getFigureBlock( String source, String caption ) 288 { 289 String dlAtts = getConfig().getAttributeString( "figure.display" ); 290 String dtAtts = getConfig().getAttributeString( "figure.graphics" ); 291 String ddAtts = getConfig().getAttributeString( "figure.caption" ); 292 293 String figureBlock = EOL + EOL + "<fo:block" + dlAtts + "><fo:external-graphic" + " src=\"" + source + "\"" + dtAtts 294 + "/>" + EOL; 295 if ( caption != null ) 296 { 297 figureBlock += EOL + "<fo:block" + ddAtts + ">" + caption + "</fo:block>" + EOL; 298 } 299 figureBlock += "</fo:block>" + EOL; 300 301 302 return figureBlock; 303 } 304 305 /** {@inheritDoc} */ 306 protected String getTableBlock( String cell, String caption ) 307 { 308 String dlAtts = getConfig().getAttributeString( "table.padding" ); 309 String dtAtts = getConfig().getAttributeString( "table.layout" ); 310 String ddAtts = getConfig().getAttributeString( "table.body.row" ); 311 // String deAtts = getConfig().getAttributeString( "table.body.cell" ); 312 313 return EOL + EOL + "<fo:block" + dlAtts + ">" + EOL + "<fo:table" + dtAtts + ">" + EOL 314 + "<fo:table-column column-width=\"proportional-column-width(1)\"/>" + EOL + EOL + "<fo:table-body>" 315 + EOL + "<fo:table-row" + ddAtts 316 + "><fo:table-cell column-number=\"1\" padding-after=\"1.5pt\" padding-end=\"5pt\" " 317 + "keep-together.within-column=\"always\" padding-start=\"2.5pt\" " 318 + "background-color=\"#eeeeee\" padding-before=\"4pt\">" + EOL + "<fo:block line-height=\"1.2em\" " 319 + "text-align=\"center\" font-family=\"Helvetica,sans-serif\" font-size=\"9pt\">" + EOL + cell 320 + "</fo:block>" + EOL + "</fo:table-cell>" + EOL + "</fo:table-row>" + EOL + "</fo:table-body>" + EOL 321 + "</fo:table>" + EOL + "</fo:block>" + EOL + EOL 322 + "<fo:block white-space-collapse=\"true\" space-after=\"6pt\" space-before=\"3pt\" " 323 + "font-family=\"Garamond,serif\" line-height=\"12pt\" text-align=\"center\" font-size=\"11pt\">" 324 + "Table_caption</fo:block>" + EOL; 325 } 326 327 /** {@inheritDoc} */ 328 protected String getParagraphBlock( String text ) 329 { 330 String attribs = getConfig().getAttributeString( "normal.paragraph" ); 331 return EOL + "<fo:block" + attribs + ">" + text + "</fo:block>" + EOL; 332 } 333 334 /** {@inheritDoc} */ 335 protected String getVerbatimBlock( String text ) 336 { 337 String attribs = getConfig().getAttributeString( "body.source" ); 338 return EOL + "<fo:block" + attribs + ">" + text + "</fo:block>" + EOL; 339 } 340 341 /** {@inheritDoc} */ 342 protected String getHorizontalRuleBlock() 343 { 344 String attribs = getConfig().getAttributeString( "body.rule" ); 345 return EOL + EOL + "<fo:block>" + EOL + "<fo:leader" + attribs + " /></fo:block>" + EOL; 346 } 347 348 /** {@inheritDoc} */ 349 protected String getPageBreakBlock() 350 { 351 return EOL + "<fo:block break-before=\"page\" />" + EOL; 352 } 353 354 /** {@inheritDoc} */ 355 protected String getAnchorBlock( String anchor ) 356 { 357 // all anchors get '#' pre-pended 358 return EOL + "<fo:inline id=\"#" + anchor + "\">" + anchor + "</fo:inline>"; 359 } 360 361 /** {@inheritDoc} */ 362 protected String getLinkBlock( String link, String text ) 363 { 364 String attribs = getConfig().getAttributeString( "href.internal" ); 365 return EOL + "<fo:basic-link internal-destination=\"" + link + "\">" + EOL + "<fo:inline" + attribs + ">" 366 + text + "</fo:inline></fo:basic-link>"; 367 } 368 369 /** {@inheritDoc} */ 370 protected String getItalicBlock( String text ) 371 { 372 String attribs = getConfig().getAttributeString( "italic" ); 373 return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>"; 374 } 375 376 /** {@inheritDoc} */ 377 protected String getBoldBlock( String text ) 378 { 379 String attribs = getConfig().getAttributeString( "bold" ); 380 return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>"; 381 } 382 383 /** {@inheritDoc} */ 384 protected String getMonospacedBlock( String text ) 385 { 386 String attribs = getConfig().getAttributeString( "monospace" ); 387 return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>"; 388 } 389 390 /** {@inheritDoc} */ 391 protected String getLineBreakBlock() 392 { 393 return EOL + EOL + "<fo:block />"; 394 } 395 396 /** {@inheritDoc} */ 397 protected String getNonBreakingSpaceBlock() 398 { 399 return " "; 400 } 401 402 /** {@inheritDoc} */ 403 protected String getTextBlock( String text ) 404 { 405 return FoSink.escaped( text, false ); 406 } 407 408 /** {@inheritDoc} */ 409 protected String getRawTextBlock( String text ) 410 { 411 return text; 412 } 413 414 // ---------------------------------------------------------------------- 415 // Auxiliary methods 416 // ---------------------------------------------------------------------- 417 418 private void fo2pdf( String baseName ) 419 throws Exception 420 { 421 // File outputDirectory = new File( getBasedirFile(), getOutputDir() ); 422 File outputDirectory = new File( getBasedir(), outputBaseDir() + getOutputDir() ); 423 File resourceDirectory = new File( getBasedirFile(), "target/test-classes" ); 424 File foFile = new File( outputDirectory, baseName + "." + outputExtension() ); 425 File pdfFile = new File( outputDirectory, baseName + ".pdf" ); 426 FoUtils.convertFO2PDF( foFile, pdfFile, resourceDirectory.getCanonicalPath() ); 427 } 428 429 private FoConfiguration getConfig() 430 { 431 if ( config == null ) 432 { 433 config = ( (FoSink) getSink() ).getFoConfiguration(); 434 } 435 436 return config; 437 } 438 439 /** {@inheritDoc} */ 440 protected String getCommentBlock( String text ) 441 { 442 return "<!--" + toXmlComment( text ) + "-->"; 443 } 444 445 /** 446 * DOXIA-357 447 * 448 * @throws Exception if any 449 */ 450 public void testTableCaption() 451 throws Exception 452 { 453 StringBuilder html = new StringBuilder(); 454 html.append( "<table>" ).append( EOL ); 455 html.append( "<caption>caption table</caption>" ).append( EOL ); 456 html.append( "<tr>" ).append( EOL ); 457 html.append( "<td>foo</td>" ).append( EOL ); 458 html.append( "</tr>" ).append( EOL ); 459 html.append( "<tr>" ).append( EOL ); 460 html.append( "<td>bar</td>" ).append( EOL ); 461 html.append( "</tr>" ).append( EOL ); 462 html.append( "</table>" ).append( EOL ); 463 464 String fileName = "testTableCaption"; 465 466 // first create fo 467 FoSink fosink = new FoSink( getTestWriter( fileName ) ); 468 fosink.beginDocument(); 469 SinkTestDocument.generateHead( fosink ); 470 471 fosink.body(); 472 XhtmlBaseParser parser = new XhtmlBaseParser(); 473 parser.parse( new StringReader( html.toString() ), fosink ); 474 fosink.body_(); 475 476 fosink.endDocument(); 477 fosink.close(); 478 479 // then generate PDF 480 fo2pdf( fileName ); 481 } 482 483 /** 484 * @throws Exception if any 485 */ 486 public void testNestedTables() 487 throws Exception 488 { 489 StringBuilder html = new StringBuilder(); 490 html.append( "<table>" ).append( EOL ); 491 html.append( "<caption>first caption</caption>" ).append( EOL ); 492 html.append( "<tr>" ).append( EOL ); 493 html.append( "<td>foo</td>" ).append( EOL ); 494 html.append( "</tr>" ).append( EOL ); 495 html.append( "<tr>" ).append( EOL ); 496 html.append( "<td>" ).append( EOL ); 497 498 html.append( "<table>" ).append( EOL ); 499 html.append( "<caption>second caption</caption>" ).append( EOL ); 500 html.append( "<tr>" ).append( EOL ); 501 html.append( "<td>foo</td>" ).append( EOL ); 502 html.append( "<td>bar</td>" ).append( EOL ); 503 html.append( "</tr>" ).append( EOL ); 504 html.append( "<tr>" ).append( EOL ); 505 html.append( "<td>foo1</td>" ).append( EOL ); 506 html.append( "<td>" ).append( EOL ); 507 508 html.append( "<table>" ).append( EOL ); 509 html.append( "<caption>third caption</caption>" ).append( EOL ); 510 html.append( "<tr>" ).append( EOL ); 511 html.append( "<td>foo1</td>" ).append( EOL ); 512 html.append( "<td>bar1</td>" ).append( EOL ); 513 html.append( "</tr>" ).append( EOL ); 514 html.append( "</table>" ).append( EOL ); 515 html.append( "</td>" ).append( EOL ); 516 517 html.append( "</tr>" ).append( EOL ); 518 html.append( "</table>" ).append( EOL ); 519 520 html.append( "</td>" ).append( EOL ); 521 html.append( "</tr>" ).append( EOL ); 522 html.append( "</table>" ).append( EOL ); 523 524 String fileName = "testNestedTables"; 525 526 // first create fo 527 FoSink fosink = new FoSink( getTestWriter( fileName ) ); 528 fosink.beginDocument(); 529 SinkTestDocument.generateHead( fosink ); 530 531 fosink.body(); 532 XhtmlBaseParser parser = new XhtmlBaseParser(); 533 parser.parse( new StringReader( html.toString() ), fosink ); 534 fosink.body_(); 535 536 fosink.endDocument(); 537 fosink.close(); 538 539 // then generate PDF 540 fo2pdf( fileName ); 541 } 542}