View Javadoc

1   package org.apache.maven.doxia.book.services.renderer;
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.FileNotFoundException;
24  import java.io.IOException;
25  import java.io.Reader;
26  import java.io.Writer;
27  import java.text.DateFormat;
28  import java.util.Date;
29  
30  import org.apache.maven.doxia.Doxia;
31  import org.apache.maven.doxia.book.BookDoxiaException;
32  import org.apache.maven.doxia.book.context.BookContext;
33  import org.apache.maven.doxia.book.model.BookModel;
34  import org.apache.maven.doxia.book.model.Chapter;
35  import org.apache.maven.doxia.book.model.Section;
36  import org.apache.maven.doxia.module.itext.ITextSinkFactory;
37  import org.apache.maven.doxia.parser.ParseException;
38  import org.apache.maven.doxia.parser.manager.ParserNotFoundException;
39  import org.apache.maven.doxia.sink.Sink;
40  import org.codehaus.plexus.logging.AbstractLogEnabled;
41  import org.codehaus.plexus.util.IOUtil;
42  import org.codehaus.plexus.util.ReaderFactory;
43  import org.codehaus.plexus.util.StringUtils;
44  import org.codehaus.plexus.util.WriterFactory;
45  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
46  
47  /**
48   * Base class for <code>iText</code> renderer.
49   *
50   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
51   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
52   * @version $Id: AbstractITextBookRenderer.java 1090706 2011-04-09 23:15:28Z hboutemy $
53   */
54  public abstract class AbstractITextBookRenderer
55      extends AbstractLogEnabled
56      implements BookRenderer
57  {
58      /**
59       * @plexus.requirement
60       */
61      private Doxia doxia;
62  
63      // ----------------------------------------------------------------------
64      // BookRenderer Implementation
65      // ----------------------------------------------------------------------
66  
67      /** {@inheritDoc} */
68      public void renderBook( BookContext context )
69          throws BookDoxiaException
70      {
71          BookModel book = context.getBook();
72  
73          if ( !context.getOutputDirectory().exists() )
74          {
75              if ( !context.getOutputDirectory().mkdirs() )
76              {
77                  throw new BookDoxiaException( "Could not make directory: "
78                      + context.getOutputDirectory().getAbsolutePath() + "." );
79              }
80          }
81  
82          File bookFile = new File( context.getOutputDirectory(), book.getId() + ".xml" );
83  
84          Writer fileWriter;
85          try
86          {
87              fileWriter = WriterFactory.newXmlWriter( bookFile );
88          }
89          catch ( IOException e )
90          {
91              throw new BookDoxiaException( "Error while opening file.", e );
92          }
93  
94          // ----------------------------------------------------------------------
95          // Create the XML File
96          // ----------------------------------------------------------------------
97  
98          PrettyPrintXMLWriter writer = new PrettyPrintXMLWriter( fileWriter, "UTF-8", null );
99          writer.startElement( "itext" );
100         writer.addAttribute( "creationdate", DateFormat.getDateTimeInstance().format( new Date() ) );
101         writer.addAttribute( "producer", "Doxia iText" );
102 
103         //        writer.startElement( "paragraph" );
104         //        writer.addAttribute( "leading", "18.0" );
105         //        writer.addAttribute( "font", "unknown" );
106         //        writer.addAttribute( "align", "Default" );
107         //        writer.writeText( "Please visit my" + System.getProperty( "line.separator" ) );
108         //
109         //        writer.startElement( "anchor" );
110         //        writer.addAttribute( "leading", "18.0" );
111         //        writer.addAttribute( "font", "Helvetica" );
112         //        writer.addAttribute( "size", "12.0" );
113         //        writer.addAttribute( "fontstyle", "normal, underline" );
114         //        writer.addAttribute( "red", "0" );
115         //        writer.addAttribute( "green", "0" );
116         //        writer.addAttribute( "blue", "255" );
117         //        writer.addAttribute( "name", "top" );
118         //        writer.addAttribute( "reference", "http://www.lowagie.com/iText/" );
119         //
120         //        writer.startElement( "chunk" );
121         //        writer.addAttribute( "font", "Helvetica" );
122         //        writer.addAttribute( "size", "12.0" );
123         //        writer.addAttribute( "fontstyle", "normal, underline" );
124         //        writer.addAttribute( "red", "0" );
125         //        writer.addAttribute( "green", "0" );
126         //        writer.addAttribute( "blue", "255" );
127         //        writer.writeText( "website (external reference)" );
128         //        writer.endElement();
129         //
130         //        writer.endElement(); // anchor
131         //
132         //        writer.endElement(); // paragraph
133 
134         // TODO: Write out TOC
135 
136         System.setProperty( "itext.basedir", bookFile.getParentFile().getAbsolutePath() );
137         Sink sink = new ITextSinkFactory().createSink( writer );
138 
139         try
140         {
141             for ( Chapter chapter : book.getChapters() )
142             {
143                 renderChapter( sink, writer, chapter, context );
144             }
145 
146             writer.endElement(); // itext
147         }
148         finally
149         {
150             sink.flush();
151             sink.close();
152 
153             IOUtil.close( fileWriter );
154             System.getProperties().remove( "itext.basedir" );
155         }
156 
157         // ----------------------------------------------------------------------
158         // Render the XML to PDF
159         // ----------------------------------------------------------------------
160         File outputFile = new File( context.getOutputDirectory(), book.getId() + "." + getOutputExtension() );
161         try
162         {
163             renderXML( bookFile, outputFile );
164         }
165         catch ( IOException e )
166         {
167             throw new BookDoxiaException( "Error while rendering file", e );
168         }
169     }
170 
171     /**
172      * Get the output extension supported.
173      *
174      * @return the ouput extension supported.
175      */
176     public abstract String getOutputExtension();
177 
178     /**
179      * Generate an ouput file with the iText framework.
180      *
181      * @param iTextFile the input file.
182      * @param iTextOutput the output file.
183      * @throws java.io.IOException if any.
184      */
185     public abstract void renderXML( File iTextFile, File iTextOutput )
186         throws IOException;
187 
188     // ----------------------------------------------------------------------
189     // Private
190     // ----------------------------------------------------------------------
191 
192     /**
193      * Write a chapter.
194      *
195      * @param writer the writer.
196      * @param chapter the Chapter.
197      * @param context the BookContext.
198      * @throws BookDoxiaException if the chapter cannot be written.
199      */
200     private void renderChapter( Sink sink, PrettyPrintXMLWriter writer, Chapter chapter, BookContext context )
201         throws BookDoxiaException
202     {
203         writer.startElement( "chapter" );
204         writer.addAttribute( "numberdepth", "1" );
205         writer.addAttribute( "depth", "1" );
206         writer.addAttribute( "indent", "1" );
207 
208         startTitle( writer, "36.0", "Helvetica", "24.0", "normal", "255", "0", "0" );
209         chunk( writer, chapter.getTitle(), "Helvetica", "24.0", "normal", "255", "0", "0" );
210         writer.endElement(); // title
211 
212         //        writer.startElement( "sectioncontent" );
213         for ( Section section : chapter.getSections() )
214         {
215             renderSection( sink, writer, section, context );
216         }
217         //        writer.endElement(); // sectioncontent
218 
219         writer.endElement(); // chapter
220     }
221 
222     /**
223      * Write a section.
224      *
225      * @param writer the writer.
226      * @param section the Section.
227      * @param context the BookContext.
228      * @throws BookDoxiaException if the section cannot be written.
229      */
230     private void renderSection( Sink sink, PrettyPrintXMLWriter writer, Section section, BookContext context )
231         throws BookDoxiaException
232     {
233         //        writer.startElement( "section" );
234 
235         // ----------------------------------------------------------------------
236         //
237         // ----------------------------------------------------------------------
238 
239         BookContext.BookFile bookFile = (BookContext.BookFile) context.getFiles().get( section.getId() );
240 
241         if ( bookFile == null )
242         {
243             throw new BookDoxiaException( "No document that matches section with id=" + section.getId() + "." );
244         }
245 
246         // ----------------------------------------------------------------------
247         //
248         // ----------------------------------------------------------------------
249 
250         Reader reader = null;
251         try
252         {
253             reader = ReaderFactory.newReader( bookFile.getFile(), context.getInputEncoding() );
254             doxia.parse( reader, bookFile.getParserId(), sink );
255         }
256         catch ( ParserNotFoundException e )
257         {
258             throw new BookDoxiaException( "Parser not found: " + bookFile.getParserId() + ".", e );
259         }
260         catch ( ParseException e )
261         {
262             throw new BookDoxiaException(
263                                           "Error while parsing document: " + bookFile.getFile().getAbsolutePath() + ".",
264                                           e );
265         }
266         catch ( FileNotFoundException e )
267         {
268             throw new BookDoxiaException( "Could not find document: " + bookFile.getFile().getAbsolutePath() + ".", e );
269         }
270         catch ( IOException e )
271         {
272             throw new BookDoxiaException( "Error while rendering book: "
273                       + bookFile.getFile().getAbsolutePath() + ".", e );
274         }
275         finally
276         {
277             IOUtil.close( reader );
278         }
279     }
280 
281     /**
282      * Start a title.
283      *
284      * @param writer the writer.
285      * @param leading leading.
286      * @param font the font.
287      * @param size the size.
288      * @param fontstyle the fontstyle.
289      * @param red red.
290      * @param green green.
291      * @param blue blue.
292      */
293     private void startTitle( PrettyPrintXMLWriter writer, String leading, String font, String size, String fontstyle,
294                              String red, String green, String blue )
295     {
296         writer.startElement( "title" );
297         writer.addAttribute( "leading", leading );
298         writer.addAttribute( "font", font );
299         writer.addAttribute( "size", size );
300         writer.addAttribute( "fontstyle", fontstyle );
301         writer.addAttribute( "red", red );
302         writer.addAttribute( "green", green );
303         writer.addAttribute( "blue", blue );
304     }
305 
306     /**
307      * Write a chunk.
308      *
309      * @param writer the writer.
310      * @param title the title.
311      * @param font the font.
312      * @param size the size.
313      * @param fontstyle the fontstyle.
314      * @param red red.
315      * @param green green.
316      * @param blue blue.
317      */
318     private void chunk( PrettyPrintXMLWriter writer, String title, String font, String size, String fontstyle,
319                         String red, String green, String blue )
320     {
321         writer.startElement( "chunk" );
322         writer.addAttribute( "font", font );
323         writer.addAttribute( "size", size );
324         writer.addAttribute( "fontstyle", fontstyle );
325         writer.addAttribute( "red", red );
326         writer.addAttribute( "green", green );
327         writer.addAttribute( "blue", blue );
328         if ( StringUtils.isNotEmpty( title ) )
329         {
330             writer.writeText( title );
331         }
332         else
333         {
334             writer.writeText( "<Missing title>" );
335         }
336         writer.endElement(); // chunk
337     }
338 }