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.custommonkey.xmlunit.Diff;
034import org.custommonkey.xmlunit.XMLUnit;
035import org.xml.sax.SAXParseException;
036
037import junit.framework.TestCase;
038
039/**
040 * Test FoAggregateSink.
041 *
042 * @author ltheussl
043 * @version $Id$
044 */
045public class FoAggregateSinkTest
046    extends TestCase
047{
048    private FoAggregateSink sink;
049
050    private Writer writer;
051
052    @Override
053    protected void setUp()
054        throws Exception
055    {
056        super.setUp();
057        writer = new StringWriter();
058    }
059    
060    protected String wrapXml( String xmlFragment )
061    {
062        return "<fo:fo xmlns:fo=\"" + FoMarkup.FO_NAMESPACE+ "\">" + xmlFragment + "</fo:fo>";
063    }
064
065
066    /**
067     * Test of body method, of class FoAggregateSink.
068     */
069    public void testBody()
070    {
071        try
072        {
073            sink = new FoAggregateSink( writer );
074
075            sink.setDocumentName( "folder/documentName.apt" );
076            sink.setDocumentTitle( "documentTitle" );
077            sink.body();
078            sink.body_();
079        }
080        finally
081        {
082            sink.close();
083        }
084
085        assertTrue( writer.toString().indexOf( "<fo:block id=\"./folder/documentName\">" ) != -1 );
086    }
087
088    /**
089     * Test of setDocumentName method, of class FoAggregateSink.
090     */
091    public void testSetDocumentName()
092    {
093        try
094        {
095            sink = new FoAggregateSink( writer );
096
097            sink.setDocumentName( "folder\\documentName.boo" );
098            sink.body();
099        }
100        finally
101        {
102            sink.close();
103        }
104
105        assertTrue( writer.toString().indexOf( "<fo:block id=\"./folder/documentName\">" ) != -1 );
106    }
107    
108    /**
109     * Test the FO PDF generation with some special characters in company name.
110     */
111    public void testSpecialCharacters()
112        throws IOException, TransformerException
113    {
114        DocumentModel model = new DocumentModel();
115        DocumentCover cover = new DocumentCover();
116
117        cover.setCompanyName( "Partner & Friends" );
118        cover.setCoverTitle( "A Masterpice in Encoding Theory <>&" );
119        cover.setCoverSubTitle( "Some nice Encodings & <METHODS>" );
120        cover.setProjectName( "A Masterpice in Encoding Theory <>&" );
121        cover.setAuthor( "Partner & Friends" );
122        model.setCover( cover );
123
124        File foFile = File.createTempFile( "fo-test", ".fo" );
125        File pdfFile = File.createTempFile( "fo-test", ".pdf" );
126        try
127        {
128
129            sink = new FoAggregateSink( WriterFactory.newXmlWriter( foFile ) );
130
131            sink.setDocumentModel( model );
132            sink.setDocumentTitle( "A Masterpice in Encoding Theory <>&" );
133            sink.beginDocument();
134            sink.coverPage();
135            // sink.toc();
136            sink.endDocument();
137        }
138        finally
139        {
140            sink.close();
141        }
142
143        try
144        {
145            FoUtils.convertFO2PDF( foFile, pdfFile, null, model );
146        }
147        catch ( TransformerException e )
148        {
149            if ( ( e.getCause() != null ) && ( e.getCause() instanceof SAXParseException ) )
150            {
151                SAXParseException sax = (SAXParseException) e.getCause();
152
153                StringBuffer sb = new StringBuffer();
154                sb.append( "Error creating PDF from " ).append( foFile.getAbsolutePath() ).append( ":" ).append( sax.getLineNumber() ).append( ":" ).append( sax.getColumnNumber() ).append( "\n" );
155                sb.append( e.getMessage() );
156
157                throw new RuntimeException( sb.toString() );
158            }
159
160            throw new TransformerException( "Error creating PDF from " + foFile + ": " + e.getMessage() );
161        }
162    }
163
164    /**
165     * Test of figureGraphics method, of class FoAggregateSink.
166     */
167    public void testFigureGraphics() throws Exception
168    {
169        try
170        {
171            sink = new FoAggregateSink( writer );
172            sink.setDocumentName( "./folder\\docName.xml" );
173            sink.figureGraphics( "./../images/fig.png", null );
174        }
175        finally
176        {
177            sink.close();
178        }
179
180        String expected = "<fo:external-graphic src=\"./images/fig.png\" "
181                        + "content-width=\"scale-down-to-fit\" "
182                        + "content-height=\"scale-down-to-fit\" "
183                        + "height=\"100%\" "
184                        + "width=\"100%\"/>" + Markup.EOL;
185        String actual = writer.toString();
186
187        Diff diff = XMLUnit.compareXML( wrapXml( expected ), wrapXml( actual ) );
188        assertTrue( "Wrong figure!", diff.identical() );
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}