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.IOException;
024import java.io.StringWriter;
025import java.io.Writer;
026
027import javax.xml.transform.TransformerException;
028
029import org.apache.maven.doxia.document.DocumentCover;
030import org.apache.maven.doxia.document.DocumentModel;
031import org.apache.maven.doxia.markup.Markup;
032import org.codehaus.plexus.util.WriterFactory;
033import org.xml.sax.SAXParseException;
034
035import junit.framework.TestCase;
036import org.xmlunit.matchers.CompareMatcher;
037
038import static org.junit.Assert.assertThat;
039
040/**
041 * Test FoAggregateSink.
042 *
043 * @author ltheussl
044 * @version $Id$
045 */
046public class FoAggregateSinkTest
047    extends TestCase
048{
049    private FoAggregateSink sink;
050
051    private Writer writer;
052
053    @Override
054    protected void setUp()
055        throws Exception
056    {
057        super.setUp();
058        writer = new StringWriter();
059    }
060    
061    protected String wrapXml( String xmlFragment )
062    {
063        return "<fo:fo xmlns:fo=\"" + FoMarkup.FO_NAMESPACE+ "\">" + xmlFragment + "</fo:fo>";
064    }
065
066
067    /**
068     * Test of body method, of class FoAggregateSink.
069     */
070    public void testBody()
071    {
072        try
073        {
074            sink = new FoAggregateSink( writer );
075
076            sink.setDocumentName( "folder/documentName.apt" );
077            sink.setDocumentTitle( "documentTitle" );
078            sink.body();
079            sink.body_();
080        }
081        finally
082        {
083            sink.close();
084        }
085
086        assertTrue( writer.toString().indexOf( "<fo:block id=\"./folder/documentName\">" ) != -1 );
087    }
088
089    /**
090     * Test of setDocumentName method, of class FoAggregateSink.
091     */
092    public void testSetDocumentName()
093    {
094        try
095        {
096            sink = new FoAggregateSink( writer );
097
098            sink.setDocumentName( "folder\\documentName.boo" );
099            sink.body();
100        }
101        finally
102        {
103            sink.close();
104        }
105
106        assertTrue( writer.toString().indexOf( "<fo:block id=\"./folder/documentName\">" ) != -1 );
107    }
108    
109    /**
110     * Test the FO PDF generation with some special characters in company name.
111     */
112    public void testSpecialCharacters()
113        throws IOException, TransformerException
114    {
115        DocumentModel model = new DocumentModel();
116        DocumentCover cover = new DocumentCover();
117
118        cover.setCompanyName( "Partner & Friends" );
119        cover.setCoverTitle( "A Masterpice in Encoding Theory <>&" );
120        cover.setCoverSubTitle( "Some nice Encodings & <METHODS>" );
121        cover.setProjectName( "A Masterpice in Encoding Theory <>&" );
122        cover.setAuthor( "Partner & Friends" );
123        model.setCover( cover );
124
125        File foFile = File.createTempFile( "fo-test", ".fo" );
126        File pdfFile = File.createTempFile( "fo-test", ".pdf" );
127        try
128        {
129
130            sink = new FoAggregateSink( WriterFactory.newXmlWriter( foFile ) );
131
132            sink.setDocumentModel( model );
133            sink.setDocumentTitle( "A Masterpice in Encoding Theory <>&" );
134            sink.beginDocument();
135            sink.coverPage();
136            // sink.toc();
137            sink.endDocument();
138        }
139        finally
140        {
141            sink.close();
142        }
143
144        try
145        {
146            FoUtils.convertFO2PDF( foFile, pdfFile, null, model );
147        }
148        catch ( TransformerException e )
149        {
150            if ( ( e.getCause() != null ) && ( e.getCause() instanceof SAXParseException ) )
151            {
152                SAXParseException sax = (SAXParseException) e.getCause();
153
154                StringBuffer sb = new StringBuffer();
155                sb.append( "Error creating PDF from " ).append( foFile.getAbsolutePath() ).append( ":" ).append( sax.getLineNumber() ).append( ":" ).append( sax.getColumnNumber() ).append( "\n" );
156                sb.append( e.getMessage() );
157
158                throw new RuntimeException( sb.toString() );
159            }
160
161            throw new TransformerException( "Error creating PDF from " + foFile + ": " + e.getMessage() );
162        }
163    }
164
165    /**
166     * Test of figureGraphics method, of class FoAggregateSink.
167     */
168    public void testFigureGraphics() throws Exception
169    {
170        try
171        {
172            sink = new FoAggregateSink( writer );
173            sink.setDocumentName( "./folder\\docName.xml" );
174            sink.figureGraphics( "./../images/fig.png", null );
175        }
176        finally
177        {
178            sink.close();
179        }
180
181        String expected = "<fo:external-graphic src=\"./images/fig.png\" "
182                        + "content-width=\"scale-down-to-fit\" "
183                        + "content-height=\"scale-down-to-fit\" "
184                        + "height=\"100%\" "
185                        + "width=\"100%\"/>" + Markup.EOL;
186        String actual = writer.toString();
187
188        assertThat ( wrapXml( actual ), CompareMatcher.isIdenticalTo( wrapXml( expected ) ));
189    }
190
191    /**
192     * Test of anchor method, of class FoAggregateSink.
193     */
194    public void testAnchor()
195    {
196        try
197        {
198            sink = new FoAggregateSink( writer );
199            sink.anchor( "invalid Anchor" );
200            sink.setDocumentName( "./folder\\docName.xml" );
201            sink.anchor( "validAnchor" );
202        }
203        finally
204        {
205            sink.close();
206        }
207
208        assertTrue( writer.toString().indexOf( "<fo:inline id=\"#invalid_Anchor\">" ) != -1 );
209        assertTrue( writer.toString().indexOf( "<fo:inline id=\"./folder/docName#validAnchor\">" ) != -1 );
210    }
211
212    /**
213     * Test of link method, of class FoAggregateSink.
214     */
215    public void testLink()
216    {
217        try
218        {
219            sink = new FoAggregateSink( writer );
220            sink.link( "http://www.example.com/" );
221            sink.text( "http://www.example.com/" );
222            sink.link_();
223            sink.setDocumentName( "./folder\\docName.xml" );
224            sink.link( "#anchor" );
225            sink.text( "#anchor" );
226            sink.link_();
227            sink.link( "./././index.html" );
228            sink.text( "./././index.html" );
229            sink.link_();
230            sink.link( "./../download.html" );
231            sink.text( "./../download.html" );
232            sink.link_();
233            sink.link( ".///test.html" );
234            sink.text( "./test.html" );
235            sink.link_();
236            sink.link( "./whatsnew-1.1.html" );
237            sink.text( "./whatsnew-1.1.html" );
238            sink.link_();
239            sink.setDocumentName( ".///whatsnew-1.1.html" );
240            sink.body();
241            sink.body_();
242        }
243        finally
244        {
245            sink.close();
246        }
247
248        String result = writer.toString();
249
250        assertTrue( result.indexOf( "<fo:basic-link external-destination=\"http://www.example.com/\">" ) != -1 );
251        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./folder/docName#anchor\">" ) != -1 );
252        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./folder/index\">" ) != -1 );
253        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./download\">" ) != -1 );
254        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./folder/test\">" ) != -1 );
255        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./folder/whatsnew-1.1\">" ) != -1 );
256        assertTrue( result.indexOf( "<fo:block id=\"./whatsnew-1.1\">" ) != -1 );
257
258        writer = new StringWriter();
259        try
260        {
261            sink = new FoAggregateSink( writer );
262            sink.setDocumentName( "./subdir/dir/index.html" );
263            sink.link( "../../root.html" );
264            sink.text( "../../root.html" );
265            sink.link_();
266            sink.link( "../../../outside.html" );
267            sink.text( "../../../outside.html" );
268            sink.link_();
269            sink.body();
270            sink.body_();
271        }
272        finally
273        {
274            sink.close();
275        }
276
277        result = writer.toString();
278
279        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./root\">" ) != -1 );
280        assertTrue( result.indexOf( "<fo:basic-link internal-destination=\"./outside\">" ) != -1 );
281    }
282}