View Javadoc
1   package org.apache.maven.doxia.module.fo;
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.File;
23  import java.io.StringReader;
24  import java.io.Writer;
25  
26  import org.apache.maven.doxia.document.DocumentMeta;
27  import org.apache.maven.doxia.document.DocumentModel;
28  import org.apache.maven.doxia.document.DocumentTOC;
29  import org.apache.maven.doxia.document.DocumentTOCItem;
30  import org.apache.maven.doxia.parser.XhtmlBaseParser;
31  import org.apache.maven.doxia.sink.Sink;
32  import org.apache.maven.doxia.sink.impl.AbstractSinkTest;
33  import org.apache.maven.doxia.sink.impl.SinkTestDocument;
34  
35  import static org.apache.maven.doxia.util.HtmlTools.escapeHTML;
36  
37  /**
38   * <code>FO Sink</code> Test case.
39   */
40  public class FoSinkTest
41      extends AbstractSinkTest
42  {
43      private FoConfiguration config;
44  
45      // ----------------------------------------------------------------------
46      // Specific test methods
47      // ----------------------------------------------------------------------
48  
49      @Override
50      protected String wrapXml( String xmlFragment )
51      {
52          return "<fo:fo xmlns:fo=\"" + FoMarkup.FO_NAMESPACE + "\">" + xmlFragment + "</fo:fo>";
53      }
54  
55      /**
56       * Uses fop to generate a pdf from a test document.
57       * @throws Exception If the conversion fails.
58       */
59      public void testConvertFO2PDF()
60          throws Exception
61      {
62          String fileName = "test";
63          // first create fo
64          FoSink fosink = new FoSink( getTestWriter( fileName ) );
65          fosink.beginDocument();
66          SinkTestDocument.generate( fosink );
67          fosink.endDocument();
68          fosink.close();
69  
70          // then generate PDF
71          fo2pdf( fileName );
72      }
73  
74      /**
75       * Uses fop to generate an aggregated pdf from two test documents.
76       * @throws Exception If the conversion fails.
77       */
78      public void testAggregateMode()
79          throws Exception
80      {
81          FoAggregateSink fosink = new FoAggregateSink( getTestWriter( "aggregate" ) );
82  
83          fosink.setDocumentModel( getModel() );
84  
85          fosink.beginDocument();
86  
87          fosink.coverPage();
88  
89          fosink.toc();
90  
91          fosink.setDocumentName( "doc1" );
92          fosink.setDocumentTitle( "Document 1" );
93          SinkTestDocument.generate( fosink );
94  
95          // re-use the same source
96          fosink.setDocumentName( "doc2" );
97          fosink.setDocumentTitle( "Document 2" );
98          SinkTestDocument.generate( fosink );
99  
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     protected String getArticleBlock()
203     {
204         return "";
205     }
206 
207     protected String getNavigationBlock()
208     {
209         return "";
210     }
211 
212     protected String getSidebarBlock()
213     {
214         return "";
215     }
216 
217     /** {@inheritDoc} */
218     protected String getSectionTitleBlock( String title )
219     {
220         return title;
221     }
222 
223     /** {@inheritDoc} */
224     protected String getSection1Block( String title )
225     {
226         String attribs = getConfig().getAttributeString( "body.text" );
227         String attrib2 = getConfig().getAttributeString( "body.h1" );
228         return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">1   " + title
229             + "</fo:block>" + EOL + "</fo:block>" + EOL;
230     }
231 
232     /** {@inheritDoc} */
233     protected String getSection2Block( String title )
234     {
235         String attribs = getConfig().getAttributeString( "body.text" );
236         String attrib2 = getConfig().getAttributeString( "body.h2" );
237         return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">0.1   " + title
238             + "</fo:block>" + EOL + "</fo:block>" + EOL;
239     }
240 
241     /** {@inheritDoc} */
242     protected String getSection3Block( String title )
243     {
244         String attribs = getConfig().getAttributeString( "body.text" );
245         String attrib2 = getConfig().getAttributeString( "body.h3" );
246         return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">0.0.1   " + title
247             + "</fo:block>" + EOL + "</fo:block>" + EOL;
248     }
249 
250     /** {@inheritDoc} */
251     protected String getSection4Block( String title )
252     {
253         String attribs = getConfig().getAttributeString( "body.text" );
254         String attrib2 = getConfig().getAttributeString( "body.h4" );
255         return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">" + title
256             + "</fo:block>" + EOL + "</fo:block>" + EOL;
257     }
258 
259     /** {@inheritDoc} */
260     protected String getSection5Block( String title )
261     {
262         String attribs = getConfig().getAttributeString( "body.text" );
263         String attrib2 = getConfig().getAttributeString( "body.h5" );
264         return EOL + EOL + "<fo:block" + attribs + ">" + EOL + EOL + "<fo:block" + attrib2 + ">" + title
265             + "</fo:block>" + EOL + "</fo:block>" + EOL;
266     }
267 
268     protected String getHeaderBlock()
269     {
270         return "";
271     }
272 
273     /** {@inheritDoc} */
274     protected String getContentBlock()
275     {
276         return "";
277     }
278 
279     protected String getFooterBlock()
280     {
281         return "";
282     }
283 
284     /** {@inheritDoc} */
285     protected String getListBlock( String item )
286     {
287         String attribs = getConfig().getAttributeString( "list" );
288         String itemAttribs = getConfig().getAttributeString( "list.item" );
289         return EOL + EOL + "<fo:list-block" + attribs + ">" + EOL + "<fo:list-item" + itemAttribs
290             + "><fo:list-item-label><fo:block>&#8226;</fo:block></fo:list-item-label>" + EOL + EOL
291             + "<fo:list-item-body" + itemAttribs + ">" + EOL + "<fo:block>" + item + "</fo:block>" + EOL
292             + "</fo:list-item-body>" + EOL + "</fo:list-item>" + EOL + "</fo:list-block>" + EOL;
293     }
294 
295     /** {@inheritDoc} */
296     protected String getNumberedListBlock( String item )
297     {
298         String attribs = getConfig().getAttributeString( "list" );
299         String itemAttribs = getConfig().getAttributeString( "list.item" );
300         return EOL + EOL + "<fo:list-block" + attribs + ">" + EOL + "<fo:list-item" + itemAttribs + ">" + EOL
301             + "<fo:list-item-label>" + EOL + "<fo:block>i.</fo:block>" + EOL + "</fo:list-item-label>" + EOL + EOL
302             + "<fo:list-item-body" + itemAttribs + ">" + EOL + "<fo:block>" + item + "</fo:block>" + EOL
303             + "</fo:list-item-body>" + EOL + "</fo:list-item>" + EOL + "</fo:list-block>" + EOL;
304     }
305 
306     /** {@inheritDoc} */
307     protected String getDefinitionListBlock( String definum, String definition )
308     {
309         String dlAtts = getConfig().getAttributeString( "dl" );
310         String dtAtts = getConfig().getAttributeString( "dt" );
311         String ddAtts = getConfig().getAttributeString( "dd" );
312         return EOL + EOL + "<fo:block" + dlAtts + ">" + EOL + "<fo:block" + dtAtts + ">" + definum + "</fo:block>"
313             + EOL + EOL + EOL + "<fo:block" + ddAtts + ">" + definition + "</fo:block>" + EOL + "</fo:block>"
314             + EOL;
315     }
316 
317     /** {@inheritDoc} */
318     protected String getFigureBlock( String source, String caption )
319     {
320         String dlAtts = getConfig().getAttributeString( "figure.display" );
321         String dtAtts = getConfig().getAttributeString( "figure.graphics" );
322         String ddAtts = getConfig().getAttributeString( "figure.caption" );
323 
324         String figureBlock = EOL + EOL + "<fo:block" + dlAtts + ">" +
325                 "<fo:external-graphic" + " src=\"" + escapeHTML( source ) + "\"" + dtAtts + "/>" + EOL;
326         if ( caption != null )
327         {
328             figureBlock += EOL + "<fo:block" + ddAtts + ">" + caption + "</fo:block>" + EOL;
329         }
330         figureBlock +=  "</fo:block>" + EOL;
331         
332         
333         return figureBlock;
334     }
335 
336     /** {@inheritDoc} */
337     protected String getTableBlock( String cell, String caption )
338     {
339         String dlAtts = getConfig().getAttributeString( "table.padding" );
340         String dtAtts = getConfig().getAttributeString( "table.layout" );
341         String ddAtts = getConfig().getAttributeString( "table.body.row" );
342         // String deAtts = getConfig().getAttributeString( "table.body.cell" );
343 
344         return EOL + EOL + "<fo:block" + dlAtts + ">" + EOL + "<fo:table" + dtAtts + ">" + EOL
345             + "<fo:table-column column-width=\"proportional-column-width(1)\"/>" + EOL + EOL + "<fo:table-body>"
346             + EOL + "<fo:table-row" + ddAtts
347             + "><fo:table-cell column-number=\"1\" padding-after=\"1.5pt\" padding-end=\"5pt\" "
348             + "keep-together.within-column=\"always\" padding-start=\"2.5pt\" "
349             + "background-color=\"#eeeeee\" padding-before=\"4pt\">" + EOL + "<fo:block line-height=\"1.2em\" "
350             + "text-align=\"center\" font-family=\"Helvetica,sans-serif\" font-size=\"9pt\">" + EOL + cell
351             + "</fo:block>" + EOL + "</fo:table-cell>" + EOL + "</fo:table-row>" + EOL + "</fo:table-body>" + EOL
352             + "</fo:table>" + EOL + "</fo:block>" + EOL + EOL
353             + "<fo:block white-space-collapse=\"true\" space-after=\"6pt\" space-before=\"3pt\" "
354             + "font-family=\"Garamond,serif\" line-height=\"12pt\" text-align=\"center\" font-size=\"11pt\">"
355             + "Table_caption</fo:block>" + EOL;
356     }
357 
358     /** {@inheritDoc} */
359     protected String getParagraphBlock( String text )
360     {
361         String attribs = getConfig().getAttributeString( "normal.paragraph" );
362         return EOL + "<fo:block" + attribs + ">" + text + "</fo:block>" + EOL;
363     }
364 
365     /** {@inheritDoc} */
366     protected String getDataBlock( String value, String text )
367     {
368         return text;
369     }
370 
371     /** {@inheritDoc} */
372     protected String getTimeBlock( String datetime, String text )
373     {
374         return text;
375     }
376 
377     /** {@inheritDoc} */
378     protected String getAddressBlock( String text )
379     {
380         return text;
381     }
382 
383     /** {@inheritDoc} */
384     protected String getBlockquoteBlock( String text )
385     {
386         return text;
387     }
388 
389     /** {@inheritDoc} */
390     protected String getDivisionBlock( String text )
391     {
392         return text;
393     }
394 
395     /** {@inheritDoc} */
396     protected String getVerbatimBlock( String text )
397     {
398         String attribs = getConfig().getAttributeString( "body.source" );
399         return EOL + "<fo:block" + attribs + ">" + text + "</fo:block>" + EOL;
400     }
401 
402     /** {@inheritDoc} */
403     protected String getHorizontalRuleBlock()
404     {
405         String attribs = getConfig().getAttributeString( "body.rule" );
406         return EOL + EOL + "<fo:block>" + EOL + "<fo:leader" + attribs + " /></fo:block>" + EOL;
407     }
408 
409     /** {@inheritDoc} */
410     protected String getPageBreakBlock()
411     {
412         return EOL + "<fo:block break-before=\"page\" />" + EOL;
413     }
414 
415     /** {@inheritDoc} */
416     protected String getAnchorBlock( String anchor )
417     {
418         // all anchors get '#' pre-pended
419         return EOL + "<fo:inline id=\"#" + anchor + "\">" + anchor + "</fo:inline>";
420     }
421 
422     /** {@inheritDoc} */
423     protected String getLinkBlock( String link, String text )
424     {
425         String attribs = getConfig().getAttributeString( "href.internal" );
426         return EOL + "<fo:basic-link internal-destination=\"" + link + "\">" + EOL + "<fo:inline" + attribs + ">"
427             + text + "</fo:inline></fo:basic-link>";
428     }
429 
430     /** {@inheritDoc} */
431     protected String getInlineBlock( String text )
432     {
433         return text;
434     }
435 
436     /** {@inheritDoc} */
437     protected String getInlineItalicBlock( String text )
438     {
439         String attribs = getConfig().getAttributeString( "italic" );
440         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
441     }
442 
443     /** {@inheritDoc} */
444     protected String getInlineBoldBlock( String text )
445     {
446         String attribs = getConfig().getAttributeString( "bold" );
447         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
448     }
449 
450     /** {@inheritDoc} */
451     protected String getInlineCodeBlock( String text )
452     {
453         String attribs = getConfig().getAttributeString( "monospace" );
454         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
455     }
456 
457     /** {@inheritDoc} */
458     protected String getItalicBlock( String text )
459     {
460         String attribs = getConfig().getAttributeString( "italic" );
461         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
462     }
463 
464     /** {@inheritDoc} */
465     protected String getBoldBlock( String text )
466     {
467         String attribs = getConfig().getAttributeString( "bold" );
468         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
469     }
470 
471     /** {@inheritDoc} */
472     protected String getMonospacedBlock( String text )
473     {
474         String attribs = getConfig().getAttributeString( "monospace" );
475         return EOL + "<fo:inline" + attribs + ">" + text + "</fo:inline>";
476     }
477 
478     /** {@inheritDoc} */
479     protected String getLineBreakBlock()
480     {
481         return EOL + EOL + "<fo:block />";
482     }
483 
484     /** {@inheritDoc} */
485     protected String getLineBreakOpportunityBlock()
486     {
487         return "";
488     }
489 
490     /** {@inheritDoc} */
491     protected String getNonBreakingSpaceBlock()
492     {
493         return "&#160;";
494     }
495 
496     /** {@inheritDoc} */
497     protected String getTextBlock( String text )
498     {
499         return FoSink.escaped( text, false );
500     }
501 
502     /** {@inheritDoc} */
503     protected String getRawTextBlock( String text )
504     {
505         return text;
506     }
507 
508     // ----------------------------------------------------------------------
509     // Auxiliary methods
510     // ----------------------------------------------------------------------
511 
512     private void fo2pdf( String baseName )
513         throws Exception
514     {
515         // File outputDirectory = new File( getBasedirFile(), getOutputDir() );
516         File outputDirectory = new File( getBasedir(), outputBaseDir() + getOutputDir() );
517         File resourceDirectory = new File( getBasedirFile(), "target/test-classes" );
518         File foFile = new File( outputDirectory, baseName + "." + outputExtension() );
519         File pdfFile = new File( outputDirectory, baseName + ".pdf" );
520         FoUtils.convertFO2PDF( foFile, pdfFile, resourceDirectory.getCanonicalPath() );
521     }
522 
523     private FoConfiguration getConfig()
524     {
525         if ( config == null )
526         {
527             config = ( (FoSink) getSink() ).getFoConfiguration();
528         }
529 
530         return config;
531     }
532 
533     /** {@inheritDoc} */
534     protected String getCommentBlock( String text )
535     {
536         return "<!--" + toXmlComment( text ) + "-->";
537     }
538 
539     /**
540      * DOXIA-357
541      *
542      * @throws Exception if any
543      */
544     public void testTableCaption()
545         throws Exception
546     {
547         StringBuilder html = new StringBuilder();
548         html.append( "<table>" ).append( EOL );
549         html.append( "<caption>caption table</caption>" ).append( EOL );
550         html.append( "<tr>" ).append( EOL );
551         html.append( "<td>foo</td>" ).append( EOL );
552         html.append( "</tr>" ).append( EOL );
553         html.append( "<tr>" ).append( EOL );
554         html.append( "<td>bar</td>" ).append( EOL );
555         html.append( "</tr>" ).append( EOL );
556         html.append( "</table>" ).append( EOL );
557 
558         String fileName = "testTableCaption";
559 
560         // first create fo
561         FoSink fosink = new FoSink( getTestWriter( fileName ) );
562         fosink.beginDocument();
563         SinkTestDocument.generateHead( fosink );
564 
565         fosink.body();
566         XhtmlBaseParser parser = new XhtmlBaseParser();
567         parser.parse( new StringReader( html.toString() ), fosink );
568         fosink.body_();
569 
570         fosink.endDocument();
571         fosink.close();
572 
573         // then generate PDF
574         fo2pdf( fileName );
575     }
576 
577     /**
578      * @throws Exception if any
579      */
580     public void testNestedTables()
581         throws Exception
582     {
583         StringBuilder html = new StringBuilder();
584         html.append( "<table>" ).append( EOL );
585         html.append( "<caption>first caption</caption>" ).append( EOL );
586         html.append( "<tr>" ).append( EOL );
587         html.append( "<td>foo</td>" ).append( EOL );
588         html.append( "</tr>" ).append( EOL );
589         html.append( "<tr>" ).append( EOL );
590         html.append( "<td>" ).append( EOL );
591 
592         html.append( "<table>" ).append( EOL );
593         html.append( "<caption>second caption</caption>" ).append( EOL );
594         html.append( "<tr>" ).append( EOL );
595         html.append( "<td>foo</td>" ).append( EOL );
596         html.append( "<td>bar</td>" ).append( EOL );
597         html.append( "</tr>" ).append( EOL );
598         html.append( "<tr>" ).append( EOL );
599         html.append( "<td>foo1</td>" ).append( EOL );
600         html.append( "<td>" ).append( EOL );
601 
602         html.append( "<table>" ).append( EOL );
603         html.append( "<caption>third caption</caption>" ).append( EOL );
604         html.append( "<tr>" ).append( EOL );
605         html.append( "<td>foo1</td>" ).append( EOL );
606         html.append( "<td>bar1</td>" ).append( EOL );
607         html.append( "</tr>" ).append( EOL );
608         html.append( "</table>" ).append( EOL );
609         html.append( "</td>" ).append( EOL );
610 
611         html.append( "</tr>" ).append( EOL );
612         html.append( "</table>" ).append( EOL );
613 
614         html.append( "</td>" ).append( EOL );
615         html.append( "</tr>" ).append( EOL );
616         html.append( "</table>" ).append( EOL );
617 
618         String fileName = "testNestedTables";
619 
620         // first create fo
621         FoSink fosink = new FoSink( getTestWriter( fileName ) );
622         fosink.beginDocument();
623         SinkTestDocument.generateHead( fosink );
624 
625         fosink.body();
626         XhtmlBaseParser parser = new XhtmlBaseParser();
627         parser.parse( new StringReader( html.toString() ), fosink );
628         fosink.body_();
629 
630         fosink.endDocument();
631         fosink.close();
632 
633         // then generate PDF
634         fo2pdf( fileName );
635     }
636 }